• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "pipeline/rs_uni_render_visitor.h"
17 
18 #ifdef RS_ENABLE_OLD_VK
19 #include <vulkan_window.h>
20 #endif
21 
22 #include "draw/color.h"
23 #ifndef USE_ROSEN_DRAWING
24 #include "include/core/SkRegion.h"
25 #include "include/core/SkTextBlob.h"
26 #else
27 #include "recording/recording_canvas.h"
28 #include "skia_adapter/skia_canvas.h"
29 #endif
30 
31 #include "src/core/SkCanvasPriv.h"
32 
33 #include "common/rs_background_thread.h"
34 #include "common/rs_common_def.h"
35 #include "common/rs_obj_abs_geometry.h"
36 #include "common/rs_optional_trace.h"
37 #include "common/rs_singleton.h"
38 #include "memory/rs_tag_tracker.h"
39 #include "pipeline/rs_base_render_node.h"
40 #include "pipeline/rs_base_render_util.h"
41 #include "pipeline/rs_canvas_drawing_render_node.h"
42 #include "pipeline/rs_display_render_node.h"
43 #include "pipeline/rs_draw_cmd.h"
44 #include "pipeline/rs_effect_render_node.h"
45 #include "pipeline/rs_main_thread.h"
46 #include "pipeline/rs_paint_filter_canvas.h"
47 #include "pipeline/rs_processor_factory.h"
48 #include "pipeline/rs_proxy_render_node.h"
49 #include "pipeline/rs_realtime_refresh_rate_manager.h"
50 #include "pipeline/rs_root_render_node.h"
51 #include "pipeline/rs_surface_render_node.h"
52 #include "pipeline/rs_uni_render_listener.h"
53 #include "pipeline/rs_uni_render_virtual_processor.h"
54 #include "pipeline/rs_uni_render_util.h"
55 #include "platform/common/rs_log.h"
56 #include "platform/common/rs_system_properties.h"
57 #include "platform/ohos/rs_jank_stats.h"
58 #include "property/rs_properties_painter.h"
59 #include "property/rs_point_light_manager.h"
60 #include "render/rs_skia_filter.h"
61 #include "pipeline/parallel_render/rs_parallel_render_manager.h"
62 #include "pipeline/parallel_render/rs_sub_thread_manager.h"
63 #include "system/rs_system_parameters.h"
64 #include "scene_board_judgement.h"
65 #include "hgm_core.h"
66 #include "benchmarks/rs_recording_thread.h"
67 #include "scene_board_judgement.h"
68 #include "metadata_helper.h"
69 #include <v1_0/buffer_handle_meta_key_type.h>
70 #include <v1_0/cm_color_space.h>
71 
72 #include "pipeline/round_corner_display/rs_round_corner_display.h"
73 #include "pipeline/round_corner_display/rs_message_bus.h"
74 namespace OHOS {
75 namespace Rosen {
76 namespace {
77 constexpr uint32_t PHONE_MAX_APP_WINDOW_NUM = 1;
78 constexpr uint32_t CACHE_MAX_UPDATE_TIME = 2;
79 constexpr int ROTATION_90 = 90;
80 constexpr int ROTATION_270 = 270;
81 constexpr float EPSILON_SCALE = 0.00001f;
82 static const std::string CAPTURE_WINDOW_NAME = "CapsuleWindow";
83 constexpr const char* CLEAR_GPU_CACHE = "ClearGpuCache";
84 static const std::string BIGFLODER_BUNDLE_NAME = "SCBDesktop2";
85 static std::map<NodeId, uint32_t> cacheRenderNodeMap = {};
86 static uint32_t cacheReuseTimes = 0;
87 static std::mutex cacheRenderNodeMapMutex;
88 static std::mutex groupedTransitionNodesMutex;
89 using groupedTransitionNodesType = std::unordered_map<NodeId, std::pair<RSUniRenderVisitor::RenderParam,
90     std::unordered_map<NodeId, RSUniRenderVisitor::RenderParam>>>;
91 static std::unordered_map<NodeId, std::pair<RSUniRenderVisitor::RenderParam,
92     std::unordered_map<NodeId, RSUniRenderVisitor::RenderParam>>> groupedTransitionNodes = {};
93 static const std::map<DirtyRegionType, std::string> DIRTY_REGION_TYPE_MAP {
94     { DirtyRegionType::UPDATE_DIRTY_REGION, "UPDATE_DIRTY_REGION" },
95     { DirtyRegionType::OVERLAY_RECT, "OVERLAY_RECT" },
96     { DirtyRegionType::FILTER_RECT, "FILTER_RECT" },
97     { DirtyRegionType::SHADOW_RECT, "SHADOW_RECT" },
98     { DirtyRegionType::PREPARE_CLIP_RECT, "PREPARE_CLIP_RECT" },
99     { DirtyRegionType::REMOVE_CHILD_RECT, "REMOVE_CHILD_RECT" },
100     { DirtyRegionType::RENDER_PROPERTIES_RECT, "RENDER_PROPERTIES_RECT" },
101     { DirtyRegionType::CANVAS_NODE_SKIP_RECT, "CANVAS_NODE_SKIP_RECT" },
102     { DirtyRegionType::OUTLINE_RECT, "OUTLINE_RECT" },
103 };
104 
CheckRootNodeReadyToDraw(const std::shared_ptr<RSBaseRenderNode> & child)105 bool CheckRootNodeReadyToDraw(const std::shared_ptr<RSBaseRenderNode>& child)
106 {
107     if (child != nullptr && child->IsInstanceOf<RSRootRenderNode>()) {
108         auto rootNode = child->ReinterpretCastTo<RSRootRenderNode>();
109         const auto& property = rootNode->GetRenderProperties();
110         if (property.GetFrameWidth() > 0 && property.GetFrameHeight() > 0 && rootNode->GetEnableRender()) {
111             return true;
112         }
113     }
114     return false;
115 }
116 
CheckScbReadyToDraw(const std::shared_ptr<RSBaseRenderNode> & child)117 bool CheckScbReadyToDraw(const std::shared_ptr<RSBaseRenderNode>& child)
118 {
119     if (child != nullptr && child->IsInstanceOf<RSCanvasRenderNode>()) {
120         auto canvasRenderNode = child->ReinterpretCastTo<RSCanvasRenderNode>();
121         const auto& property = canvasRenderNode->GetRenderProperties();
122         if (property.GetFrameWidth() > 0 && property.GetFrameHeight() > 0) {
123             return true;
124         }
125     }
126     return false;
127 }
128 
IsFirstFrameReadyToDraw(RSSurfaceRenderNode & node)129 bool IsFirstFrameReadyToDraw(RSSurfaceRenderNode& node)
130 {
131     bool result = false;
132     auto sortedChildren = node.GetSortedChildren();
133     if (node.IsScbScreen()) {
134         for (const auto& child : *sortedChildren) {
135             result = CheckScbReadyToDraw(child);
136         }
137         return result;
138     }
139     for (auto& child : *sortedChildren) {
140         result = CheckRootNodeReadyToDraw(child);
141         // when appWindow has abilityComponent node
142         if (child != nullptr && child->IsInstanceOf<RSSurfaceRenderNode>()) {
143             for (const auto& surfaceNodeChild : *child->GetSortedChildren()) {
144                 result = CheckRootNodeReadyToDraw(surfaceNodeChild);
145             }
146         }
147     }
148     return result;
149 }
150 }
151 
DoScreenRcdTask(std::shared_ptr<RSProcessor> & processor,std::unique_ptr<RcdInfo> & rcdInfo,ScreenInfo & screenInfo_)152 void DoScreenRcdTask(std::shared_ptr<RSProcessor>& processor, std::unique_ptr<RcdInfo>& rcdInfo,
153     ScreenInfo& screenInfo_)
154 {
155     if (screenInfo_.state != ScreenState::HDI_OUTPUT_ENABLE) {
156         RS_LOGD("DoScreenRcdTask is not at HDI_OUPUT mode");
157         return;
158     }
159     if (RSSingleton<RoundCornerDisplay>::GetInstance().GetRcdEnable()) {
160         RSSingleton<RoundCornerDisplay>::GetInstance().RunHardwareTask(
161             [&processor, &rcdInfo]() {
162                 auto hardInfo = RSSingleton<RoundCornerDisplay>::GetInstance().GetHardwareInfo();
163                 rcdInfo->processInfo = {processor, hardInfo.topLayer, hardInfo.bottomLayer,
164                     hardInfo.resourceChanged};
165                 RSRcdRenderManager::GetInstance().DoProcessRenderTask(rcdInfo->processInfo);
166             }
167         );
168     }
169 }
170 
171 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
172 constexpr uint32_t PARALLEL_RENDER_MINIMUM_RENDER_NODE_NUMBER = 50;
173 #endif
174 
RSUniRenderVisitor()175 RSUniRenderVisitor::RSUniRenderVisitor()
176     : curSurfaceDirtyManager_(std::make_shared<RSDirtyRegionManager>())
177 {
178     PartialRenderOptionInit();
179     auto mainThread = RSMainThread::Instance();
180     renderEngine_ = mainThread->GetRenderEngine();
181     quickSkipPrepareType_ = RSSystemParameters::GetQuickSkipPrepareType();
182     isOcclusionEnabled_ = RSSystemProperties::GetOcclusionEnabled();
183     isQuickSkipPreparationEnabled_ = (quickSkipPrepareType_ != QuickSkipPrepareType::DISABLED);
184     isDrawingCacheEnabled_ = RSSystemParameters::GetDrawingCacheEnabled();
185     RSTagTracker::UpdateReleaseResourceEnabled(RSSystemProperties::GetReleaseResourceEnabled());
186     isScreenRotationAnimating_ = RSSystemProperties::GetCacheEnabledForRotation();
187     isSubSurfaceEnabled_ = RSSystemProperties::GetSubSurfaceEnabled();
188     isSkipCanvasNodeOutOfScreen_ = RSSystemParameters::GetSkipCanvasNodeOutofScreenEnabled();
189 #if defined(RS_ENABLE_DRIVEN_RENDER)
190     if (RSDrivenRenderManager::GetInstance().GetDrivenRenderEnabled()) {
191         drivenInfo_ = std::make_unique<DrivenInfo>();
192     }
193 #endif
194     if (RSRcdRenderManager::GetInstance().GetRcdRenderEnabled()) {
195         rcdInfo_ = std::make_unique<RcdInfo>();
196     }
197     surfaceNodePrepareMutex_ = std::make_shared<std::mutex>();
198     parallelRenderType_ = ParallelRenderingType::DISABLE;
199 #if defined(RS_ENABLE_PARALLEL_RENDER)
200     isCalcCostEnable_ = RSSystemParameters::GetCalcCostEnabled();
201 #endif
202 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
203     if (renderEngine_ && renderEngine_->GetRenderContext()) {
204         auto subThreadManager = RSSubThreadManager::Instance();
205         subThreadManager->Start(renderEngine_->GetRenderContext().get());
206     }
207 #endif
208     isUIFirst_ = RSMainThread::Instance()->IsUIFirstOn();
209     isPhone_ = RSMainThread::Instance()->GetDeviceType() == DeviceType::PHONE;
210     isPc_ = RSMainThread::Instance()->GetDeviceType() == DeviceType::PC;
211 }
212 
PartialRenderOptionInit()213 void RSUniRenderVisitor::PartialRenderOptionInit()
214 {
215     partialRenderType_ = RSSystemProperties::GetUniPartialRenderEnabled();
216     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
217     auto screenNum = screenManager->GetAllScreenIds().size();
218     isPartialRenderEnabled_ = (screenNum <= 1) && (partialRenderType_ != PartialRenderType::DISABLED) &&
219         RSMainThread::Instance()->IsSingleDisplay();
220     dirtyRegionDebugType_ = RSSystemProperties::GetDirtyRegionDebugType();
221     surfaceRegionDebugType_ = RSSystemProperties::GetSurfaceRegionDfxType();
222     isRegionDebugEnabled_ = (dirtyRegionDebugType_ != DirtyRegionDebugType::DISABLED) ||
223         (surfaceRegionDebugType_ != SurfaceRegionDebugType::DISABLED);
224     isVisibleRegionDfxEnabled_ = (surfaceRegionDebugType_ == SurfaceRegionDebugType::VISIBLE_REGION);
225     isOpaqueRegionDfxEnabled_ = (surfaceRegionDebugType_ == SurfaceRegionDebugType::OPAQUE_REGION);
226     isTargetDirtyRegionDfxEnabled_ = RSSystemProperties::GetTargetDirtyRegionDfxEnabled(dfxTargetSurfaceNames_) &&
227         (surfaceRegionDebugType_ == SurfaceRegionDebugType::DISABLED);
228     isDirtyRegionDfxEnabled_ = !isTargetDirtyRegionDfxEnabled_ &&
229         (dirtyRegionDebugType_ == DirtyRegionDebugType::EGL_DAMAGE);
230     isDisplayDirtyDfxEnabled_ = !isTargetDirtyRegionDfxEnabled_ &&
231         (dirtyRegionDebugType_ == DirtyRegionDebugType::DISPLAY_DIRTY);
232     isCanvasNodeSkipDfxEnabled_ = (dirtyRegionDebugType_ == DirtyRegionDebugType::CANVAS_NODE_SKIP_RECT);
233     isOpDropped_ = isPartialRenderEnabled_ &&
234         (partialRenderType_ != PartialRenderType::SET_DAMAGE) && !isRegionDebugEnabled_;
235     isCacheBlurPartialRenderEnabled_ = RSSystemProperties::GetCachedBlurPartialRenderEnabled();
236 }
237 
RSUniRenderVisitor(std::shared_ptr<RSPaintFilterCanvas> canvas,uint32_t surfaceIndex)238 RSUniRenderVisitor::RSUniRenderVisitor(std::shared_ptr<RSPaintFilterCanvas> canvas, uint32_t surfaceIndex)
239     : RSUniRenderVisitor()
240 {
241 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
242     parallelRenderVisitorIndex_ = surfaceIndex;
243 #if defined(RS_ENABLE_GL)
244     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
245         canvas_ = canvas;
246     }
247 #endif
248 #endif
249 }
250 
RSUniRenderVisitor(const RSUniRenderVisitor & visitor)251 RSUniRenderVisitor::RSUniRenderVisitor(const RSUniRenderVisitor& visitor) : RSUniRenderVisitor()
252 {
253     currentVisitDisplay_ = visitor.currentVisitDisplay_;
254     screenInfo_ = visitor.screenInfo_;
255     displayHasSecSurface_ = visitor.displayHasSecSurface_;
256     displayHasSkipSurface_ = visitor.displayHasSkipSurface_;
257     hasCaptureWindow_ = visitor.hasCaptureWindow_;
258     parentSurfaceNodeMatrix_ = visitor.parentSurfaceNodeMatrix_;
259     curAlpha_ = visitor.curAlpha_;
260     dirtyFlag_ = visitor.dirtyFlag_;
261     curDisplayNode_ = visitor.curDisplayNode_;
262     currentFocusedNodeId_ = visitor.currentFocusedNodeId_;
263     surfaceNodePrepareMutex_ = visitor.surfaceNodePrepareMutex_;
264     prepareClipRect_ = visitor.prepareClipRect_;
265     isOpDropped_ = visitor.isOpDropped_;
266     isPartialRenderEnabled_ = visitor.isPartialRenderEnabled_;
267     isHardwareForcedDisabled_ = visitor.isHardwareForcedDisabled_;
268     doAnimate_ = visitor.doAnimate_;
269     isDirty_ = visitor.isDirty_;
270 }
271 
~RSUniRenderVisitor()272 RSUniRenderVisitor::~RSUniRenderVisitor() {}
273 
CopyVisitorInfos(std::shared_ptr<RSUniRenderVisitor> visitor)274 void RSUniRenderVisitor::CopyVisitorInfos(std::shared_ptr<RSUniRenderVisitor> visitor)
275 {
276     std::unique_lock<std::mutex> lock(copyVisitorInfosMutex_);
277     currentVisitDisplay_ = visitor->currentVisitDisplay_;
278     screenInfo_ = visitor->screenInfo_;
279     displayHasSecSurface_ = visitor->displayHasSecSurface_;
280     displayHasSkipSurface_ = visitor->displayHasSkipSurface_;
281     hasCaptureWindow_ = visitor->hasCaptureWindow_;
282     parentSurfaceNodeMatrix_ = visitor->parentSurfaceNodeMatrix_;
283     curAlpha_ = visitor->curAlpha_;
284     dirtyFlag_ = visitor->dirtyFlag_;
285     curDisplayNode_ = visitor->curDisplayNode_;
286     currentFocusedNodeId_ = visitor->currentFocusedNodeId_;
287     surfaceNodePrepareMutex_ = visitor->surfaceNodePrepareMutex_;
288     prepareClipRect_ = visitor->prepareClipRect_;
289     isOpDropped_ = visitor->isOpDropped_;
290     isPartialRenderEnabled_ = visitor->isPartialRenderEnabled_;
291     isHardwareForcedDisabled_ = visitor->isHardwareForcedDisabled_;
292     doAnimate_ = visitor->doAnimate_;
293     isDirty_ = visitor->isDirty_;
294 }
295 
CopyPropertyForParallelVisitor(RSUniRenderVisitor * mainVisitor)296 void RSUniRenderVisitor::CopyPropertyForParallelVisitor(RSUniRenderVisitor *mainVisitor)
297 {
298     if (!mainVisitor) {
299         RS_LOGE("main thread visitor is nullptr");
300         return;
301     }
302     doAnimate_ = mainVisitor->doAnimate_;
303     isParallel_ = mainVisitor->isParallel_;
304     isUpdateCachedSurface_ = mainVisitor->isUpdateCachedSurface_;
305     isHardwareForcedDisabled_ = mainVisitor->isHardwareForcedDisabled_;
306     isOpDropped_ = mainVisitor->isOpDropped_;
307     isPartialRenderEnabled_ = mainVisitor->isPartialRenderEnabled_;
308     isUIFirst_ = mainVisitor->isUIFirst_;
309     isSubThread_ = true;
310 }
311 
UpdateSubTreeInCache(const std::shared_ptr<RSRenderNode> & cacheRootNode,const std::vector<RSRenderNode::SharedPtr> & children)312 void RSUniRenderVisitor::UpdateSubTreeInCache(const std::shared_ptr<RSRenderNode>& cacheRootNode,
313     const std::vector<RSRenderNode::SharedPtr>& children)
314 {
315     for (auto& child : children) {
316         if (child == nullptr) {
317             continue;
318         }
319         if (child->IsDirty()) {
320             curDirty_ = child->IsDirty();
321             child->Prepare(shared_from_this());
322             continue;
323         }
324         // set flag for surface node whose children contain shared transition node
325         if (child->GetSharedTransitionParam().has_value() && curSurfaceNode_) {
326             SetHasSharedTransitionNode(*curSurfaceNode_, true);
327         }
328         // [planning] pay attention to outofparent case
329         if (auto surfaceNode = child->ReinterpretCastTo<RSSurfaceRenderNode>()) {
330             // fully prepare hwcLayer Layer and its subnodes
331             if (surfaceNode->IsHardwareEnabledType()) {
332                 PrepareSurfaceRenderNode(*surfaceNode);
333                 return;
334             }
335             UpdateSecurityAndSkipLayerRecord(*surfaceNode);
336         } else if (auto effectNode = child->ReinterpretCastTo<RSEffectRenderNode>()) {
337             // effectNode need to update effectRegion so effectNode and use-effect child should be updated
338             PrepareEffectNodeIfCacheReuse(cacheRootNode, effectNode);
339             return;
340         }
341         if (child->GetRenderProperties().NeedFilter() || child->GetRenderProperties().GetUseEffect()) {
342             child->Update(*curSurfaceDirtyManager_, cacheRootNode, dirtyFlag_, prepareClipRect_);
343         }
344         if (child->GetRenderProperties().NeedFilter()) {
345             UpdateForegroundFilterCacheWithDirty(*child, *curSurfaceDirtyManager_);
346             if (curSurfaceNode_ && curSurfaceNode_->GetId() == child->GetInstanceRootNodeId()) {
347                 curSurfaceNode_->UpdateChildrenFilterRects(child, child->GetOldDirtyInSurface(),
348                     child->IsBackgroundFilterCacheValid());
349             }
350         }
351         UpdateSubTreeInCache(child, *child->GetSortedChildren());
352     }
353 }
354 
PrepareEffectNodeIfCacheReuse(const std::shared_ptr<RSRenderNode> & cacheRootNode,std::shared_ptr<RSEffectRenderNode> effectNode)355 void RSUniRenderVisitor::PrepareEffectNodeIfCacheReuse(const std::shared_ptr<RSRenderNode>& cacheRootNode,
356     std::shared_ptr<RSEffectRenderNode> effectNode)
357 {
358     if (effectNode == nullptr || curSurfaceDirtyManager_ == nullptr) {
359         return;
360     }
361     // set rotationChanged true when screen is rotating or folding/expanding screen.
362     if (curDisplayNode_->IsRotationChanged() || (!curDisplayNode_->IsRotationChanged() && doAnimate_)) {
363         effectNode->SetRotationChanged(true);
364         int invalidateTimes = 2; // node call invalidate cache 3 times in one frame.
365         effectNode->SetInvalidateTimesForRotation(invalidateTimes);
366     } else {
367         effectNode->SetRotationChanged(false);
368     }
369     effectNode->SetVisitedFilterCacheStatus(curSurfaceDirtyManager_->IsCacheableFilterRectEmpty());
370     effectNode->Update(*curSurfaceDirtyManager_, cacheRootNode, dirtyFlag_, prepareClipRect_);
371     UpdateSubTreeInCache(effectNode, *effectNode->GetSortedChildren());
372     if (effectNode->GetRenderProperties().NeedFilter()) {
373         UpdateForegroundFilterCacheWithDirty(*effectNode, *curSurfaceDirtyManager_);
374         if (curSurfaceNode_ && curSurfaceNode_->GetId() == effectNode->GetInstanceRootNodeId()) {
375             curSurfaceNode_->UpdateChildrenFilterRects(effectNode, effectNode->GetOldDirtyInSurface(),
376                 effectNode->IsBackgroundFilterCacheValid());
377         }
378     }
379 }
380 
PrepareChildren(RSRenderNode & node)381 void RSUniRenderVisitor::PrepareChildren(RSRenderNode& node)
382 {
383     // GetSortedChildren() may remove disappearingChildren_ when transition animation end.
384     // So the judgement whether node has removed child should be executed after this.
385     // NOTE: removal of transition node is moved to RSMainThread::Animate
386     MergeRemovedChildDirtyRegion(node);
387     // backup environment variables.
388     auto parentNode = std::move(logicParentNode_);
389     logicParentNode_ = node.weak_from_this();
390     node.ResetChildrenRect();
391 
392     auto tempCornerRadius = curCornerRadius_;
393     if (!isSubNodeOfSurfaceInPrepare_) {
394         Vector4f::Max(node.GetRenderProperties().GetCornerRadius(), curCornerRadius_, curCornerRadius_);
395     }
396     if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
397         node.SetGlobalCornerRadius(curCornerRadius_);
398     }
399 
400     float alpha = curAlpha_;
401     curAlpha_ *= node.GetRenderProperties().GetAlpha();
402     node.SetGlobalAlpha(curAlpha_);
403     auto children = node.GetSortedChildren();
404     // check curSurfaceDirtyManager_ for SubTree updates
405     if (curSurfaceDirtyManager_ != nullptr && isCachedSurfaceReuse_ && !node.HasMustRenewedInfo()) {
406         RS_OPTIONAL_TRACE_NAME_FMT("CachedSurfaceReuse node %llu quickSkip subtree", node.GetId());
407     } else if (curSurfaceDirtyManager_ != nullptr && curDisplayNode_ != nullptr &&
408         (isCachedSurfaceReuse_ || isSurfaceDirtyNodeLimited_ || !UpdateCacheChangeStatus(node))) {
409         RS_OPTIONAL_TRACE_NAME_FMT("UpdateCacheChangeStatus node %llu simply update subtree, isCachedSurfaceReuse_ %d,"
410             " isSurfaceDirtyNodeLimited_ %d, hasUseEffect %d", node.GetId(), isCachedSurfaceReuse_,
411             isSurfaceDirtyNodeLimited_, node.HasUseEffectNodes());
412         UpdateSubTreeInCache(node.ReinterpretCastTo<RSRenderNode>(), *children);
413         node.UpdateEffectRegion(effectRegion_,
414             (node.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE && node.HasUseEffectNodes()));
415     } else {
416         // Get delay flag to restore geo changes
417         if (node.GetCacheGeoPreparationDelay()) {
418             dirtyFlag_ = true;
419         }
420         node.SetUseEffectNodes(false);
421         for (auto& child : *children) {
422             if (child && UNLIKELY(child->GetSharedTransitionParam().has_value())) {
423                 PrepareSharedTransitionNode(*child);
424             }
425             SaveCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
426             curDirty_ = child->IsDirty();
427             child->Prepare(shared_from_this());
428             if (child->HasUseEffectNodes()) {
429                 node.SetUseEffectNodes(true);
430             }
431             RestoreCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
432         }
433         // Reset delay flag
434         node.ResetCacheGeoPreparationDelay();
435         SetNodeCacheChangeStatus(node);
436     }
437 
438     curCornerRadius_ = std::move(tempCornerRadius);
439     curAlpha_ = alpha;
440     // restore environment variables
441     logicParentNode_ = std::move(parentNode);
442 }
443 
MergeRemovedChildDirtyRegion(RSRenderNode & node)444 void RSUniRenderVisitor::MergeRemovedChildDirtyRegion(RSRenderNode& node)
445 {
446     if (curSurfaceDirtyManager_ && curSurfaceNode_ && node.HasRemovedChild()) {
447         RectI dirtyRect = prepareClipRect_.IntersectRect(node.GetChildrenRect());
448         if (isSubNodeOfSurfaceInPrepare_) {
449             curSurfaceDirtyManager_->MergeDirtyRect(dirtyRect);
450             if (curSurfaceDirtyManager_->IsTargetForDfx()) {
451                 // since childRect includes multiple rects, defaultly marked as canvas_node
452                 curSurfaceDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::CANVAS_NODE,
453                     DirtyRegionType::REMOVE_CHILD_RECT, dirtyRect);
454             }
455         } else {
456             curDisplayDirtyManager_->MergeDirtyRect(dirtyRect);
457         }
458         node.ResetHasRemovedChild();
459     }
460 }
461 
IsDrawingCacheStatic(RSRenderNode & node)462 bool RSUniRenderVisitor::IsDrawingCacheStatic(RSRenderNode& node)
463 {
464     // since this function only called by drawing group root
465     // if cache valid, cacheRenderNodeMapCnt > 0
466     // check all dirtynodes of app instance if there's any in cache subtree
467     if (curContentDirty_ || node.GetDrawingCacheChanged() || !node.IsCacheSurfaceValid() ||
468         curSurfaceNode_ == nullptr || curSurfaceNode_->GetId() != node.GetInstanceRootNodeId() ||
469         RSMainThread::Instance()->IsDrawingGroupChanged(node)) {
470         return false;
471     }
472     // skip targeted cache node when first visited node is forced cache
473     if (node.GetDrawingCacheType() == RSDrawingCacheType::TARGETED_CACHE && firstVisitedCache_ != node.GetId() &&
474         IsFirstVisitedCacheForced()) {
475         return false;
476     }
477     // simplify Cache status reset
478     node.GetFilterRectsInCache(allCacheFilterRects_);
479     node.SetDrawingCacheChanged(false);
480     node.SetCacheGeoPreparationDelay(dirtyFlag_);
481     if (allCacheFilterRects_.count(node.GetId())) {
482         node.SetChildHasFilter(true);
483         if (const auto directParent = node.GetParent().lock()) {
484             directParent->SetChildHasFilter(true);
485         }
486     }
487     return true;
488 }
489 
UpdateCacheChangeStatus(RSRenderNode & node)490 bool RSUniRenderVisitor::UpdateCacheChangeStatus(RSRenderNode& node)
491 {
492     node.SetChildHasFilter(false);
493     if (!isDrawingCacheEnabled_) {
494         return true;
495     }
496     node.CheckDrawingCacheType();
497     if (node.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE && !node.IsStaticCached() &&
498         (!node.ShouldPaint() || isScreenRotationAnimating_)) {
499         node.SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
500     }
501     // skip status check if there is no upper cache mark
502     if (node.GetDrawingCacheType() == RSDrawingCacheType::DISABLED_CACHE && firstVisitedCache_ == INVALID_NODEID) {
503         return true;
504     }
505     // subroot's dirty and cached filter should be count for parent root
506     if (!isDrawingCacheChanged_.empty()) {
507         // Any child node dirty causes cache change
508         isDrawingCacheChanged_.top() = isDrawingCacheChanged_.top() || curDirty_;
509     }
510     if (!curCacheFilterRects_.empty() && !node.IsInstanceOf<RSEffectRenderNode>() &&
511         (node.GetRenderProperties().GetBackgroundFilter() || node.GetRenderProperties().GetUseEffect() ||
512         node.GetRenderProperties().GetShadowColorStrategy() != SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE)) {
513         curCacheFilterRects_.top().emplace(node.GetId());
514     }
515     // drawing group root node
516     if (node.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE) {
517         // if firstVisitedCache_ valid, upper cache should be updated so sub cache shouldn't skip
518         // [planning] static subcache could be skip and reuse
519         if ((quickSkipPrepareType_ >= QuickSkipPrepareType::STATIC_CACHE) &&
520             (firstVisitedCache_ == INVALID_NODEID) && IsDrawingCacheStatic(node)) {
521             return false;
522         }
523         // For rootnode, init drawing changes only if there is any content dirty
524         isDrawingCacheChanged_.push(curContentDirty_);
525         RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVisitor::UpdateCacheChangeStatus: cachable node %" PRIu64 ""
526             "contentDirty(cacheChanged): %d", node.GetId(), static_cast<int>(isDrawingCacheChanged_.top()));
527         curCacheFilterRects_.push({});
528         if (firstVisitedCache_ == INVALID_NODEID) {
529             firstVisitedCache_ = node.GetId();
530         }
531     }
532     return true;
533 }
534 
DisableNodeCacheInSetting(RSRenderNode & node)535 void RSUniRenderVisitor::DisableNodeCacheInSetting(RSRenderNode& node)
536 {
537     if (node.IsStaticCached()) {
538         return;
539     }
540     // Attention: filter node should be marked. Only enable lowest suggested cached node
541     if (node.GetDrawingCacheType() == RSDrawingCacheType::TARGETED_CACHE) {
542         // if target cached is reused, keep enable -- prepareskip
543         // disable cache if it has outOfParent -- cannot cache right
544         // [planning] if there is dirty subcache, disable upper targetcache
545         // disable targeted cache node when first visited node is forced cache to avoid problem in case with blur
546         if (node.HasChildrenOutOfRect() || (firstVisitedCache_ != node.GetId() && IsFirstVisitedCacheForced())) {
547             node.SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
548             allCacheFilterRects_[firstVisitedCache_].insert(allCacheFilterRects_[node.GetId()].begin(),
549                 allCacheFilterRects_[node.GetId()].end());
550             allCacheFilterRects_.erase(node.GetId());
551             RS_OPTIONAL_TRACE_NAME_FMT("Disable cache %llu: outofparent %d, firstVisitedCache_ %llu & cacheforce %d",
552                 node.GetId(), node.HasChildrenOutOfRect(), firstVisitedCache_, IsFirstVisitedCacheForced());
553         }
554     }
555     if (firstVisitedCache_ == INVALID_NODEID) {
556         node.SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
557         std::stack<bool>().swap(isDrawingCacheChanged_);
558         visitedCacheNodeIds_.clear();
559     }
560 }
561 
IsFirstVisitedCacheForced() const562 bool RSUniRenderVisitor::IsFirstVisitedCacheForced() const
563 {
564     if (firstVisitedCache_ != INVALID_NODEID) {
565         auto firstVisitedNode = RSMainThread::Instance()->GetContext().GetNodeMap().GetRenderNode<RSRenderNode>(
566             firstVisitedCache_);
567         if (firstVisitedNode && firstVisitedNode->GetDrawingCacheType() == RSDrawingCacheType::FORCED_CACHE) {
568             return true;
569         }
570     }
571     return false;
572 }
573 
SaveCurSurface(std::shared_ptr<RSDirtyRegionManager> dirtyManager,std::shared_ptr<RSSurfaceRenderNode> surfaceNode)574 void RSUniRenderVisitor::SaveCurSurface(std::shared_ptr<RSDirtyRegionManager> dirtyManager,
575     std::shared_ptr<RSSurfaceRenderNode> surfaceNode)
576 {
577     if (!isSubSurfaceEnabled_) {
578         return;
579     }
580     surfaceDirtyManager_.push(dirtyManager);
581     surfaceNode_.push(surfaceNode);
582 }
583 
RestoreCurSurface(std::shared_ptr<RSDirtyRegionManager> & dirtyManager,std::shared_ptr<RSSurfaceRenderNode> & surfaceNode)584 void RSUniRenderVisitor::RestoreCurSurface(std::shared_ptr<RSDirtyRegionManager> &dirtyManager,
585     std::shared_ptr<RSSurfaceRenderNode> &surfaceNode)
586 {
587     if (!isSubSurfaceEnabled_) {
588         return;
589     }
590     dirtyManager = surfaceDirtyManager_.top();
591     surfaceNode = surfaceNode_.top();
592     surfaceDirtyManager_.pop();
593     surfaceNode_.pop();
594 }
595 
PrepareSubSurfaceNodes(RSSurfaceRenderNode & node)596 void RSUniRenderVisitor::PrepareSubSurfaceNodes(RSSurfaceRenderNode& node)
597 {
598     if (!isSubSurfaceEnabled_) {
599         return;
600     }
601     for (auto &nodes : node.GetSubSurfaceNodes()) {
602         for (auto &node : nodes.second) {
603             auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.lock());
604             if (surfaceNode != nullptr) {
605                 SaveCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
606                 PrepareSurfaceRenderNode(*surfaceNode);
607                 RestoreCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
608             }
609         }
610     }
611 }
612 
ProcessSubSurfaceNodes(RSSurfaceRenderNode & node)613 void RSUniRenderVisitor::ProcessSubSurfaceNodes(RSSurfaceRenderNode& node)
614 {
615     if (!isSubSurfaceEnabled_) {
616         return;
617     }
618     for (auto &nodes : node.GetSubSurfaceNodes()) {
619         for (auto &node : nodes.second) {
620             auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.lock());
621             if (surfaceNode != nullptr && ProcessSharedTransitionNode(*surfaceNode)) {
622                 SaveCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
623                 ProcessSurfaceRenderNode(*surfaceNode);
624                 RestoreCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
625             }
626         }
627     }
628 }
629 
SetNodeCacheChangeStatus(RSRenderNode & node)630 void RSUniRenderVisitor::SetNodeCacheChangeStatus(RSRenderNode& node)
631 {
632     auto directParent = node.GetParent().lock();
633     if (directParent != nullptr && node.ChildHasFilter()) {
634         directParent->SetChildHasFilter(true);
635     }
636     if (!isDrawingCacheEnabled_ ||
637         node.GetDrawingCacheType() == RSDrawingCacheType::DISABLED_CACHE) {
638         return;
639     }
640     if (!curCacheFilterRects_.empty()) {
641         allCacheFilterRects_[node.GetId()].insert(curCacheFilterRects_.top().begin(),
642             curCacheFilterRects_.top().end());
643         node.ResetFilterRectsInCache(allCacheFilterRects_[node.GetId()]);
644         curCacheFilterRects_.pop();
645     }
646     DisableNodeCacheInSetting(node);
647     if (node.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE) {
648         // update visited cache roots including itself
649         visitedCacheNodeIds_.emplace(node.GetId());
650         node.SetVisitedCacheRootIds(visitedCacheNodeIds_);
651         if (curSurfaceNode_) {
652             curSurfaceNode_->UpdateDrawingCacheNodes(node.ReinterpretCastTo<RSRenderNode>());
653         }
654     }
655     bool isDrawingCacheChanged = isDrawingCacheChanged_.empty() ? true : isDrawingCacheChanged_.top();
656     RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVisitor::SetNodeCacheChangeStatus: node %" PRIu64 " drawingtype %d, "
657         "staticCache %d, cacheChange %d, childHasFilter|effect: %d|%d, outofparent: %d, visitedCacheNodeIds num: %lu",
658         node.GetId(), static_cast<int>(node.GetDrawingCacheType()), node.IsStaticCached(),
659         static_cast<int>(isDrawingCacheChanged), node.ChildHasFilter(), node.HasUseEffectNodes(),
660         static_cast<int>(node.HasChildrenOutOfRect()), visitedCacheNodeIds_.size());
661     if (node.IsStaticCached()) {
662         node.SetDrawingCacheChanged(false);
663     } else {
664         node.SetDrawingCacheChanged(isDrawingCacheChanged);
665     }
666     // reset counter after executing the very first marked node
667     if (firstVisitedCache_ == node.GetId()) {
668         std::stack<bool>().swap(isDrawingCacheChanged_);
669         firstVisitedCache_ = INVALID_NODEID;
670         visitedCacheNodeIds_.clear();
671     } else if (!isDrawingCacheChanged_.empty()) {
672         bool isChildChanged = isDrawingCacheChanged_.top();
673         isDrawingCacheChanged_.pop();
674         if (!isDrawingCacheChanged_.empty()) {
675             isDrawingCacheChanged_.top() = isDrawingCacheChanged_.top() || isChildChanged;
676         }
677     }
678 }
679 
CheckColorSpace(RSSurfaceRenderNode & node)680 void RSUniRenderVisitor::CheckColorSpace(RSSurfaceRenderNode& node)
681 {
682     const sptr<SurfaceBuffer>& buffer = node.GetBuffer();
683     if (buffer != nullptr) {
684         using namespace HDI::Display::Graphic::Common::V1_0;
685         CM_ColorSpaceInfo colorSpaceInfo;
686         if (MetadataHelper::GetColorSpaceInfo(buffer, colorSpaceInfo) != GSERROR_OK) {
687             RS_LOGD("RSUniRenderVisitor::CheckColorSpace: get color space info failed.");
688             return;
689         }
690 
691         if (colorSpaceInfo.primaries != COLORPRIMARIES_SRGB) {
692             newColorSpace_ = GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
693             RS_LOGD("RSUniRenderVisitor::CheckColorSpace: node(%{public}s) set new colorspace primaries %{public}d",
694                     node.GetName().c_str(), colorSpaceInfo.primaries);
695         }
696         return;
697     }
698 
699     if (node.IsAppWindow()) {
700         auto colorspace = node.GetColorSpace();
701         if (colorspace != GRAPHIC_COLOR_GAMUT_SRGB) {
702             newColorSpace_ = GRAPHIC_COLOR_GAMUT_DISPLAY_P3;
703             RS_LOGD("RSUniRenderVisitor::CheckColorSpace: node(%{public}s) set new colorgamut %{public}d",
704                     node.GetName().c_str(), colorspace);
705         }
706     }
707 }
708 
HandleColorGamuts(RSDisplayRenderNode & node,const sptr<RSScreenManager> & screenManager)709 void RSUniRenderVisitor::HandleColorGamuts(RSDisplayRenderNode& node, const sptr<RSScreenManager>& screenManager)
710 {
711     RSScreenType screenType = BUILT_IN_TYPE_SCREEN;
712     if (screenManager->GetScreenType(node.GetScreenId(), screenType) != SUCCESS) {
713         RS_LOGD("RSUniRenderVisitor::HandleColorGamuts get screen type failed.");
714         return;
715     }
716 
717     if (screenType == VIRTUAL_TYPE_SCREEN) {
718         ScreenColorGamut screenColorGamut;
719         if (screenManager->GetScreenColorGamut(node.GetScreenId(), screenColorGamut) != SUCCESS) {
720             RS_LOGD("RSUniRenderVisitor::HandleColorGamuts get screen color gamut failed.");
721             return;
722         }
723         newColorSpace_ = static_cast<GraphicColorGamut>(screenColorGamut);
724     }
725 }
726 
CheckPixelFormat(RSSurfaceRenderNode & node)727 void RSUniRenderVisitor::CheckPixelFormat(RSSurfaceRenderNode& node)
728 {
729     if (hasFingerprint_) {
730         RS_LOGD("RSUniRenderVisitor::CheckPixelFormat hasFingerprint is true.");
731         return;
732     }
733     const sptr<SurfaceBuffer>& buffer = node.GetBuffer();
734     if (buffer == nullptr) {
735         RS_LOGD("RSUniRenderVisitor::CheckPixelFormat node(%{public}s) did not have buffer.", node.GetName().c_str());
736         return;
737     }
738 
739     if (node.GetFingerprint()) {
740         hasFingerprint_ = true;
741         newPixelFormat_ = GRAPHIC_PIXEL_FMT_RGBA_1010102;
742         RS_LOGD("RSUniRenderVisitor::CheckPixelFormat newPixelFormat_ is set 1010102 for fingerprint.");
743         return;
744     }
745 
746     auto bufferPixelFormat = buffer->GetFormat();
747     if ((bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010102 ||
748         bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCBCR_P010 ||
749         bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCRCB_P010) && !IsHardwareComposerEnabled()) {
750         newPixelFormat_ = GRAPHIC_PIXEL_FMT_RGBA_1010102;
751         RS_LOGD("RSUniRenderVisitor::CheckPixelFormat pixelformat is set to 1010102 for 10bit buffer");
752     }
753 }
754 
HandlePixelFormat(RSDisplayRenderNode & node,const sptr<RSScreenManager> & screenManager)755 void RSUniRenderVisitor::HandlePixelFormat(RSDisplayRenderNode& node, const sptr<RSScreenManager>& screenManager)
756 {
757     RSScreenType screenType = BUILT_IN_TYPE_SCREEN;
758     if (screenManager->GetScreenType(node.GetScreenId(), screenType) != SUCCESS) {
759         RS_LOGD("RSUniRenderVisitor::HandlePixelFormat get screen type failed.");
760         return;
761     }
762 
763     if (screenType == VIRTUAL_TYPE_SCREEN) {
764         if (screenManager->GetPixelFormat(node.GetScreenId(), newPixelFormat_) != SUCCESS) {
765             RS_LOGD("RSUniRenderVisitor::HandlePixelFormat get screen color gamut failed.");
766         }
767     }
768 }
769 
PrepareDisplayRenderNode(RSDisplayRenderNode & node)770 void RSUniRenderVisitor::PrepareDisplayRenderNode(RSDisplayRenderNode& node)
771 {
772     currentVisitDisplay_ = node.GetScreenId();
773     displayHasSecSurface_.emplace(currentVisitDisplay_, false);
774     displayHasSkipSurface_.emplace(currentVisitDisplay_, false);
775     hasCaptureWindow_.emplace(currentVisitDisplay_, false);
776     dirtySurfaceNodeMap_.clear();
777 
778     RS_TRACE_NAME("RSUniRender:PrepareDisplay " + std::to_string(currentVisitDisplay_));
779     curDisplayDirtyManager_ = node.GetDirtyManager();
780     if (!curDisplayDirtyManager_) {
781         return;
782     }
783     // set 1st elem for display dirty
784     accumulatedDirtyRegions_.emplace_back(RectI());
785     curDisplayDirtyManager_->Clear();
786     curDisplayNode_ = node.shared_from_this()->ReinterpretCastTo<RSDisplayRenderNode>();
787 
788     dirtyFlag_ = isDirty_;
789     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
790     if (!screenManager) {
791         RS_LOGE("RSUniRenderVisitor::PrepareDisplayRenderNode ScreenManager is nullptr");
792         return;
793     }
794     screenInfo_ = screenManager->QueryScreenInfo(node.GetScreenId());
795     prepareClipRect_.SetAll(0, 0, screenInfo_.width, screenInfo_.height);
796     // rcd message send
797     if ((screenInfo_.state == ScreenState::HDI_OUTPUT_ENABLE) &&
798         RSSingleton<RoundCornerDisplay>::GetInstance().GetRcdEnable()) {
799         using rcd_msg = RSSingleton<RsMessageBus>;
800         rcd_msg::GetInstance().SendMsg<uint32_t, uint32_t>(TOPIC_RCD_DISPLAY_SIZE,
801             screenInfo_.width, screenInfo_.height);
802         rcd_msg::GetInstance().SendMsg<ScreenRotation>(TOPIC_RCD_DISPLAY_ROTATION,
803             node.GetScreenRotation());
804     }
805 
806 #ifndef USE_ROSEN_DRAWING
807     parentSurfaceNodeMatrix_ = SkMatrix::I();
808 #else
809     parentSurfaceNodeMatrix_ = Drawing::Matrix();
810 #endif
811     auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
812     if (geoPtr != nullptr) {
813         geoPtr->UpdateByMatrixFromSelf();
814         parentSurfaceNodeMatrix_ = geoPtr->GetAbsMatrix();
815         if (geoPtr->IsNeedClientCompose()) {
816             isHardwareForcedDisabled_ = true;
817         }
818     }
819     dirtyFlag_ = dirtyFlag_ || node.IsRotationChanged();
820 #if defined(RS_ENABLE_DRIVEN_RENDER)
821     if (drivenInfo_) {
822         drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
823             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || dirtyFlag_;
824     }
825 #endif
826     // when display is in rotation state, occlusion relationship will be ruined,
827     // hence partial-render quick-reject should be disabled.
828     if(node.IsRotationChanged()) {
829         isOpDropped_ = false;
830         RS_TRACE_NAME("ClosePartialRender 1 RotationChanged");
831     }
832     node.UpdateRotation();
833     curAlpha_ = node.GetRenderProperties().GetAlpha();
834     isParallel_ = false;
835     newColorSpace_ = GRAPHIC_COLOR_GAMUT_SRGB;
836     hasFingerprint_ = false;
837     newPixelFormat_ = GRAPHIC_PIXEL_FMT_RGBA_8888;
838 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
839     ParallelPrepareDisplayRenderNodeChildrens(node);
840 #else
841     PrepareChildren(node);
842 #endif
843     auto mirrorNode = node.GetMirrorSource().lock();
844     if (mirrorNode) {
845         mirroredDisplays_.insert(mirrorNode->GetScreenId());
846     }
847 
848     node.GetCurAllSurfaces().clear();
849     node.CollectSurface(node.shared_from_this(), node.GetCurAllSurfaces(), true, false);
850 
851     HandleColorGamuts(node, screenManager);
852     HandlePixelFormat(node, screenManager);
853 
854 #if defined(RS_ENABLE_DRIVEN_RENDER)
855     if (drivenInfo_) {
856         RS_OPTIONAL_TRACE_NAME("RSUniRender:DrivenRenderPrepare");
857         drivenInfo_->prepareInfo.hasInvalidScene = drivenInfo_->prepareInfo.hasInvalidScene ||
858             node.GetChildrenCount() >= 8 || // default value, count > 8 means invalid scene
859             isHardwareForcedDisabled_ || node.GetRotation() != ScreenRotation::ROTATION_0;
860         drivenInfo_->prepareInfo.screenRect = RectI(0, 0, screenInfo_.width, screenInfo_.height),
861         // prepare driven render tree
862         RSDrivenRenderManager::GetInstance().DoPrepareRenderTask(drivenInfo_->prepareInfo);
863         // merge dirty rect for driven render
864         auto uniDrivenRenderMode = RSDrivenRenderManager::GetInstance().GetUniDrivenRenderMode();
865         if (uniDrivenRenderMode == DrivenUniRenderMode::RENDER_WITH_CLIP_HOLE &&
866             drivenInfo_->surfaceDirtyManager != nullptr) {
867             auto drivenRenderDirtyRect = RSDrivenRenderManager::GetInstance().GetUniRenderSurfaceClipHoleRect();
868             RS_OPTIONAL_TRACE_NAME("merge driven render dirty rect: " + drivenRenderDirtyRect.ToString());
869             drivenInfo_->surfaceDirtyManager->MergeDirtyRect(drivenRenderDirtyRect);
870         }
871     }
872 #endif
873     RSRcdRenderManager::GetInstance().DoPrepareRenderTask(rcdInfo_->prepareInfo);
874 }
875 
ParallelPrepareDisplayRenderNodeChildrens(RSDisplayRenderNode & node)876 void RSUniRenderVisitor::ParallelPrepareDisplayRenderNodeChildrens(RSDisplayRenderNode& node)
877 {
878 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
879     auto parallelRenderManager = RSParallelRenderManager::Instance();
880     doParallelRender_ = (node.GetChildrenCount() >= PARALLEL_RENDER_MINIMUM_RENDER_NODE_NUMBER);
881     isParallel_ = AdaptiveSubRenderThreadMode(doParallelRender_) && parallelRenderManager->GetParallelMode();
882     isDirtyRegionAlignedEnable_ = false;
883     // we will open prepare parallel after check all properties.
884     if (isParallel_ &&
885         RSSystemProperties::GetPrepareParallelRenderingEnabled() != ParallelRenderingType::DISABLE) {
886         parallelRenderManager->CopyPrepareVisitorAndPackTask(*this, node);
887         parallelRenderManager->LoadBalanceAndNotify(TaskType::PREPARE_TASK);
888         parallelRenderManager->WaitPrepareEnd(*this);
889     } else {
890         PrepareChildren(node);
891     }
892 #endif
893 }
894 
CheckIfSurfaceRenderNodeStatic(RSSurfaceRenderNode & node)895 bool RSUniRenderVisitor::CheckIfSurfaceRenderNodeStatic(RSSurfaceRenderNode& node)
896 {
897     // dirtyFlag_ includes leashWindow dirty
898     // window layout change(e.g. move or zooming) | proxyRenderNode's cmd
899     // temporary cannot deal with leashWindow and scbScreen, restricted to mainwindow
900     if (dirtyFlag_ || node.IsDirty() || !node.IsMainWindowType() || curDisplayNode_ == nullptr) {
901         return false;
902     }
903     if (curDisplayDirtyManager_) {
904         accumulatedDirtyRegions_[0] = curDisplayDirtyManager_->GetCurrentFrameDirtyRegion();
905     }
906     // if node has to be prepared, it's not static
907     bool isClassifyByRootNode = (quickSkipPrepareType_ >= QuickSkipPrepareType::STATIC_APP_INSTANCE);
908     NodeId rootId = node.GetInstanceRootNodeId();
909     if (RSMainThread::Instance()->CheckNodeHasToBePreparedByPid(
910         isClassifyByRootNode ? rootId : node.GetId(), isClassifyByRootNode)) {
911         return false;
912     }
913     // [Attention] node's ability pid could be different but should have same rootId
914     auto abilityNodeIds = node.GetAbilityNodeIds();
915     bool result = isClassifyByRootNode
916         ? RSMainThread::Instance()->CheckNodeHasToBePreparedByPid(rootId, true)
917         : std::any_of(abilityNodeIds.begin(), abilityNodeIds.end(), [&](uint64_t nodeId) {
918             return RSMainThread::Instance()->CheckNodeHasToBePreparedByPid(nodeId, false);
919         });
920     if (result) {
921         return false;
922     }
923     node.UpdateSurfaceCacheContentStatic({});
924     RS_OPTIONAL_TRACE_NAME("Skip static surface " + node.GetName() + " nodeid - pid: " +
925         std::to_string(node.GetId()) + " - " + std::to_string(ExtractPid(node.GetId())));
926     // static node's dirty region is empty
927     auto dirtyManager = node.GetDirtyManager();
928     if (dirtyManager) {
929         dirtyManager->Clear();
930         if (node.IsTransparent()) {
931             dirtyManager->UpdateVisitedDirtyRects(accumulatedDirtyRegions_);
932         }
933         node.UpdateFilterCacheStatusIfNodeStatic(prepareClipRect_, curDisplayNode_->IsRotationChanged());
934     }
935     node.ResetDrawingCacheStatusIfNodeStatic(allCacheFilterRects_);
936     // Attention: curSurface info would be reset as upper surfaceParent if it has
937     ResetCurSurfaceInfoAsUpperSurfaceParent(node);
938     // static surface keeps same position
939     curDisplayNode_->UpdateSurfaceNodePos(node.GetId(), curDisplayNode_->GetLastFrameSurfacePos(node.GetId()));
940     return true;
941 }
942 
ResetCurSurfaceInfoAsUpperSurfaceParent(RSSurfaceRenderNode & node)943 void RSUniRenderVisitor::ResetCurSurfaceInfoAsUpperSurfaceParent(RSSurfaceRenderNode& node)
944 {
945     auto directParent = node.GetParent().lock();
946     if (directParent == nullptr) {
947         return;
948     }
949     if (auto parentInstance = directParent->GetInstanceRootNode()) {
950         // in case leashwindow is not directParent
951         auto surfaceParent = parentInstance->ReinterpretCastTo<RSSurfaceRenderNode>();
952         if (surfaceParent && (surfaceParent->IsLeashWindow() || surfaceParent->IsMainWindowType())) {
953             curSurfaceNode_ = surfaceParent;
954             curSurfaceDirtyManager_ = surfaceParent->GetDirtyManager();
955         }
956     }
957 }
958 
IsHardwareComposerEnabled()959 bool RSUniRenderVisitor::IsHardwareComposerEnabled()
960 {
961     return !isHardwareForcedDisabled_;
962 }
963 
ClearTransparentBeforeSaveLayer()964 void RSUniRenderVisitor::ClearTransparentBeforeSaveLayer()
965 {
966     RS_TRACE_NAME("ClearTransparentBeforeSaveLayer");
967     if (!IsHardwareComposerEnabled()) {
968         return;
969     }
970     for (auto& node : hardwareEnabledNodes_) {
971         if (!node->ShouldPaint()) {
972             continue;
973         }
974         auto dstRect = node->GetDstRect();
975         if (dstRect.IsEmpty()) {
976             continue;
977         }
978 #ifndef USE_ROSEN_DRAWING
979         canvas_->save();
980         canvas_->clipRect({ static_cast<float>(dstRect.GetLeft()), static_cast<float>(dstRect.GetTop()),
981                             static_cast<float>(dstRect.GetRight()), static_cast<float>(dstRect.GetBottom()) });
982         canvas_->clear(SK_ColorTRANSPARENT);
983         canvas_->restore();
984 #else
985         canvas_->Save();
986         canvas_->ClipRect({ static_cast<float>(dstRect.GetLeft()), static_cast<float>(dstRect.GetTop()),
987                               static_cast<float>(dstRect.GetRight()), static_cast<float>(dstRect.GetBottom()) },
988             Drawing::ClipOp::INTERSECT, false);
989         canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
990         canvas_->Restore();
991 #endif
992     }
993 }
994 
MarkSubHardwareEnableNodeState(RSSurfaceRenderNode & surfaceNode)995 void RSUniRenderVisitor::MarkSubHardwareEnableNodeState(RSSurfaceRenderNode& surfaceNode)
996 {
997     if (!IsHardwareComposerEnabled()) {
998         return;
999     }
1000 
1001     // hardware enabled type case: mark self
1002     if (surfaceNode.IsHardwareEnabledType()) {
1003         surfaceNode.SetHardwareForcedDisabledState(true);
1004         return;
1005     }
1006 
1007     if (!surfaceNode.IsAppWindow() && !surfaceNode.IsAbilityComponent() && !surfaceNode.IsLeashWindow()) {
1008         return;
1009     }
1010 
1011     // ability component type case: check pid
1012     if (surfaceNode.IsAbilityComponent()) {
1013         pid_t pid = ExtractPid(surfaceNode.GetId());
1014         for (auto& childNode : hardwareEnabledNodes_) {
1015             pid_t childPid = ExtractPid(childNode->GetId());
1016             if (pid == childPid) {
1017                 childNode->SetHardwareForcedDisabledState(true);
1018             }
1019         }
1020         return;
1021     }
1022     std::vector<std::weak_ptr<RSSurfaceRenderNode>> hardwareEnabledNodes;
1023     if (surfaceNode.IsAppWindow()) {
1024         hardwareEnabledNodes = surfaceNode.GetChildHardwareEnabledNodes();
1025     } else {
1026         for (auto& child : *surfaceNode.GetChildren()) {
1027             auto appNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child);
1028             if (appNode && appNode->IsAppWindow()) {
1029                 hardwareEnabledNodes = appNode->GetChildHardwareEnabledNodes();
1030                 break;
1031             }
1032         }
1033     }
1034     // app window type case: mark all child hardware enabled nodes
1035     for (auto& node : hardwareEnabledNodes) {
1036         auto childNode = node.lock();
1037         if (childNode) {
1038             childNode->SetHardwareForcedDisabledState(true);
1039         }
1040     }
1041 }
1042 
CollectAppNodeForHwc(std::shared_ptr<RSSurfaceRenderNode> surfaceNode)1043 void RSUniRenderVisitor::CollectAppNodeForHwc(std::shared_ptr<RSSurfaceRenderNode> surfaceNode)
1044 {
1045     if (!IsHardwareComposerEnabled() || !surfaceNode || surfaceNode->GetChildHardwareEnabledNodes().empty()) {
1046         return;
1047     }
1048 
1049     if (isParallel_ && !isUIFirst_) {
1050 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_GL)
1051         if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
1052             RSParallelRenderManager::Instance()->AddAppWindowNode(parallelRenderVisitorIndex_, surfaceNode);
1053         }
1054 #endif
1055     } else {
1056         if (surfaceNode->IsHardwareEnabledTopSurface()) {
1057             hardwareEnabledTopNodes_.emplace_back(surfaceNode);
1058         } else {
1059             appWindowNodesInZOrder_.emplace_back(surfaceNode);
1060         }
1061     }
1062 }
1063 
PrepareTypesOfSurfaceRenderNodeBeforeUpdate(RSSurfaceRenderNode & node)1064 void RSUniRenderVisitor::PrepareTypesOfSurfaceRenderNodeBeforeUpdate(RSSurfaceRenderNode& node)
1065 {
1066     // if current surfacenode is a main window type, reset the curSurfaceDirtyManager
1067     // reset leash window's dirtyManager pointer to avoid curSurfaceDirtyManager mis-pointing
1068     if (node.IsMainWindowType() || node.IsLeashWindow()) {
1069         node.SetFilterCacheFullyCovered(false);
1070         node.ResetFilterNodes();
1071         // [planning] check if it is not reset recursively
1072         firstVisitedCache_ = INVALID_NODEID;
1073         curSurfaceNode_ = node.ReinterpretCastTo<RSSurfaceRenderNode>();
1074         RSMainThread::Instance()->CheckAndUpdateInstanceContentStaticStatus(curSurfaceNode_);
1075         curSurfaceDirtyManager_ = node.GetDirtyManager();
1076         if (curSurfaceDirtyManager_ == nullptr) {
1077             RS_LOGE("RSUniRenderVisitor::PrepareTypesOfSurfaceRenderNodeBeforeUpdate %{public}s has no"
1078                 " SurfaceDirtyManager", node.GetName().c_str());
1079             return;
1080         }
1081         curSurfaceDirtyManager_->Clear();
1082         if (node.IsTransparent()) {
1083             curSurfaceDirtyManager_->UpdateVisitedDirtyRects(accumulatedDirtyRegions_);
1084         }
1085         curSurfaceDirtyManager_->SetSurfaceSize(screenInfo_.width, screenInfo_.height);
1086         if (isTargetDirtyRegionDfxEnabled_ && CheckIfSurfaceTargetedForDFX(node.GetName())) {
1087             curSurfaceDirtyManager_->MarkAsTargetForDfx();
1088         }
1089         ClassifyUIFirstSurfaceDirtyStatus(node);
1090     }
1091 
1092     // collect app window node's child hardware enabled node
1093     if (node.IsHardwareEnabledType() && curSurfaceNode_) {
1094         curSurfaceNode_->AddChildHardwareEnabledNode(node.ReinterpretCastTo<RSSurfaceRenderNode>());
1095         node.SetLocalZOrder(localZOrder_++);
1096     }
1097 
1098     // record whether child node is security or skip layer
1099     // it should be call after reset to false for each loop
1100     UpdateSecurityAndSkipLayerRecord(node);
1101 }
1102 
ClassifyUIFirstSurfaceDirtyStatus(RSSurfaceRenderNode & node)1103 void RSUniRenderVisitor::ClassifyUIFirstSurfaceDirtyStatus(RSSurfaceRenderNode& node)
1104 {
1105     if (node.IsMainWindowType()) {
1106         isCachedSurfaceReuse_ = (quickSkipPrepareType_ >= QuickSkipPrepareType::STATIC_CACHE_SURFACE) &&
1107             (RSMainThread::Instance()->GetDeviceType() == DeviceType::PC) &&
1108             CheckIfUIFirstSurfaceContentReusable(curSurfaceNode_, isSurfaceDirtyNodeLimited_);
1109         // The condition of childHasFilter in QuerySubAssignable can not be used here
1110         // Because child node's filter is not collected yet, so disable prepare optimization when node is transparent
1111         // [planning]: detect the filter change before prepare, and use the last frame result
1112         isSurfaceDirtyNodeLimited_ = (quickSkipPrepareType_ == QuickSkipPrepareType::CONTENT_DIRTY_CACHE_SURFACE) &&
1113             !node.IsTransparent() && isSurfaceDirtyNodeLimited_ &&
1114             node.IsOnlyBasicGeoTransform() && node.IsContentDirtyNodeLimited();
1115         if (isCachedSurfaceReuse_) {
1116             node.SetCacheGeoPreparationDelay(dirtyFlag_);
1117         }
1118     }
1119 }
1120 
CheckIfUIFirstSurfaceContentReusable(std::shared_ptr<RSSurfaceRenderNode> & node,bool & isAssigned)1121 bool RSUniRenderVisitor::CheckIfUIFirstSurfaceContentReusable(std::shared_ptr<RSSurfaceRenderNode>& node,
1122     bool& isAssigned)
1123 {
1124     if (!isUIFirst_ || node == nullptr) {
1125         return false;
1126     }
1127     auto deviceType = RSMainThread::Instance()->GetDeviceType();
1128     if (auto directParent = node->GetParent().lock()) {
1129         if (auto parentInstance = directParent->GetInstanceRootNode()) {
1130             auto surfaceParent = parentInstance->ReinterpretCastTo<RSSurfaceRenderNode>();
1131             if (surfaceParent && surfaceParent->IsLeashWindow()) {
1132                 isAssigned =
1133                     RSUniRenderUtil::IsNodeAssignSubThread(surfaceParent, curDisplayNode_->IsRotationChanged());
1134                 RS_OPTIONAL_TRACE_NAME_FMT("%s CheckIfUIFirstSurfaceContentReusable(leash): %d, isAssigned %d",
1135                     surfaceParent->GetName().c_str(), surfaceParent->IsUIFirstCacheReusable(deviceType), isAssigned);
1136                 return isAssigned && surfaceParent->IsUIFirstCacheReusable(deviceType);
1137             }
1138         }
1139     }
1140     isAssigned = RSUniRenderUtil::IsNodeAssignSubThread(node, curDisplayNode_->IsRotationChanged());
1141     RS_OPTIONAL_TRACE_NAME_FMT("%s CheckIfUIFirstSurfaceContentReusable(mainwindow): %d, isAssigned %d",
1142         node->GetName().c_str(), node->IsUIFirstCacheReusable(deviceType), isAssigned);
1143     return isAssigned && node->IsUIFirstCacheReusable(deviceType);
1144 }
1145 
PrepareTypesOfSurfaceRenderNodeAfterUpdate(RSSurfaceRenderNode & node)1146 void RSUniRenderVisitor::PrepareTypesOfSurfaceRenderNodeAfterUpdate(RSSurfaceRenderNode& node)
1147 {
1148     if (!curSurfaceDirtyManager_) {
1149         return;
1150     }
1151     const auto& properties = node.GetRenderProperties();
1152     if (properties.NeedFilter()) {
1153         UpdateForegroundFilterCacheWithDirty(node, *curSurfaceDirtyManager_);
1154         if (auto parentNode = node.GetParent().lock()) {
1155             parentNode->SetChildHasFilter(true);
1156         }
1157         if (curSurfaceNode_) {
1158             curSurfaceNode_->UpdateFilterNodes(node.shared_from_this());
1159         }
1160     }
1161     if (node.IsLeashWindow()) {
1162         auto children = node.GetSortedChildren();
1163         for (auto& child : *children) {
1164             if (child->ChildHasFilter()) {
1165                 node.SetChildHasFilter(true);
1166                 break;
1167             }
1168         }
1169     } else if (node.IsMainWindowType()) {
1170         isCachedSurfaceReuse_ = false;
1171         isSurfaceDirtyNodeLimited_ = false;
1172         bool hasFilter = node.IsTransparent() && properties.NeedFilter();
1173         bool hasHardwareNode = !node.GetChildHardwareEnabledNodes().empty();
1174         bool hasAbilityComponent = !node.GetAbilityNodeIds().empty();
1175         auto rsParent = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.GetParent().lock());
1176         if (rsParent && rsParent->IsLeashWindow()) {
1177             rsParent->SetHasFilter(hasFilter);
1178             rsParent->SetHasHardwareNode(hasHardwareNode);
1179             rsParent->SetHasAbilityComponent(hasAbilityComponent);
1180             // [uifirst] leashWindow add or clear abilityNodeId for checking subthread node status
1181             if (hasAbilityComponent) {
1182                 rsParent->AddAbilityComponentNodeIds(node.GetAbilityNodeIds());
1183             } else {
1184                 rsParent->ResetAbilityNodeIds();
1185             }
1186         } else {
1187             node.SetHasFilter(hasFilter);
1188             node.SetHasHardwareNode(hasHardwareNode);
1189             node.SetHasAbilityComponent(hasAbilityComponent);
1190         }
1191         if (node.IsTransparent() &&
1192             curSurfaceDirtyManager_->IfCacheableFilterRectFullyCover(node.GetOldDirtyInSurface())) {
1193             node.SetFilterCacheFullyCovered(true);
1194             RS_LOGD("SetFilterCacheFullyCovered surfacenode %{public}" PRIu64 " [%{public}s]",
1195                 node.GetId(), node.GetName().c_str());
1196         }
1197         node.CalcFilterCacheValidForOcclusion();
1198         RS_OPTIONAL_TRACE_NAME(node.GetName() + " PreparedNodes: " +
1199             std::to_string(preparedCanvasNodeInCurrentSurface_));
1200         preparedCanvasNodeInCurrentSurface_ = 0;
1201     }
1202     // accumulate all visited dirty rects including leash window's shadow dirty
1203     if ((node.IsMainWindowType() || node.IsLeashWindow()) && curSurfaceDirtyManager_->IsCurrentFrameDirty()) {
1204         accumulatedDirtyRegions_.emplace_back(curSurfaceDirtyManager_->GetCurrentFrameDirtyRegion());
1205     }
1206 }
1207 
UpdateSecurityAndSkipLayerRecord(RSSurfaceRenderNode & node)1208 void RSUniRenderVisitor::UpdateSecurityAndSkipLayerRecord(RSSurfaceRenderNode& node)
1209 {
1210     if (curSurfaceNode_ == nullptr) {
1211         return;
1212     }
1213     if (node.GetSecurityLayer() && curSurfaceNode_->GetId() == node.GetInstanceRootNodeId()) {
1214         curSurfaceNode_->SetHasSecurityLayer(true);
1215         displayHasSecSurface_[currentVisitDisplay_] = true;
1216     }
1217     if (node.GetSkipLayer() && curSurfaceNode_->GetId() == node.GetInstanceRootNodeId() &&
1218         node.GetName().find(CAPTURE_WINDOW_NAME) == std::string::npos) {
1219         curSurfaceNode_->SetHasSkipLayer(true);
1220         displayHasSkipSurface_[currentVisitDisplay_] = true;
1221     }
1222 }
1223 
UpdateForegroundFilterCacheWithDirty(RSRenderNode & node,RSDirtyRegionManager & dirtyManager)1224 void RSUniRenderVisitor::UpdateForegroundFilterCacheWithDirty(RSRenderNode& node,
1225     RSDirtyRegionManager& dirtyManager)
1226 {
1227     node.UpdateFilterCacheWithDirty(dirtyManager, true);
1228     node.UpdateFilterCacheManagerWithCacheRegion(dirtyManager, prepareClipRect_);
1229 }
1230 
PrepareSurfaceRenderNode(RSSurfaceRenderNode & node)1231 void RSUniRenderVisitor::PrepareSurfaceRenderNode(RSSurfaceRenderNode& node)
1232 {
1233     RS_OPTIONAL_TRACE_NAME("RSUniRender::Prepare:[" + node.GetName() + "] nodeid: " +
1234         std::to_string(node.GetId()) +  " pid: " + std::to_string(ExtractPid(node.GetId())) +
1235         ", nodeType " + std::to_string(static_cast<uint>(node.GetSurfaceNodeType())));
1236     if (curDisplayNode_ == nullptr) {
1237         ROSEN_LOGE("RSUniRenderVisitor::PrepareSurfaceRenderNode, curDisplayNode_ is nullptr.");
1238         return;
1239     }
1240     // avoid EntryView upload texture while screen rotation
1241     if (node.GetName() == "EntryView") {
1242         node.SetStaticCached(curDisplayNode_->IsRotationChanged());
1243     }
1244     node.UpdatePositionZ();
1245 #if defined(RS_ENABLE_DRIVEN_RENDER)
1246     if (drivenInfo_ && (node.GetName() == "imeWindow" || node.GetName() == "RecentView")) {
1247         drivenInfo_->prepareInfo.hasInvalidScene = true;
1248     }
1249 #endif
1250     if (node.GetName().find(CAPTURE_WINDOW_NAME) != std::string::npos) {
1251         hasCaptureWindow_[currentVisitDisplay_] = true;
1252     }
1253 
1254     node.SetAncestorDisplayNode(curDisplayNode_);
1255     CheckColorSpace(node);
1256     CheckPixelFormat(node);
1257 
1258     // stop traversal if node keeps static
1259     if (isQuickSkipPreparationEnabled_ && CheckIfSurfaceRenderNodeStatic(node)) {
1260         // node type is mainwindow.
1261         if (node.GetHasSecurityLayer() && node.GetId() == node.GetInstanceRootNodeId()) {
1262             displayHasSecSurface_[currentVisitDisplay_] = true;
1263         }
1264         if (node.GetHasSkipLayer() && node.GetId() == node.GetInstanceRootNodeId() &&
1265             node.GetName().find(CAPTURE_WINDOW_NAME) == std::string::npos) {
1266             displayHasSkipSurface_[currentVisitDisplay_] = true;
1267         }
1268         PrepareSubSurfaceNodes(node);
1269         return;
1270     }
1271     // Attension: Updateinfo before info reset
1272     node.StoreMustRenewedInfo();
1273     SetHasSharedTransitionNode(node, false);
1274     // reset HasSecurityLayer
1275     node.SetHasSecurityLayer(false);
1276     node.SetHasSkipLayer(false);
1277     node.CleanDstRectChanged();
1278     if (node.IsHardwareEnabledTopSurface()) {
1279         node.ResetSubNodeShouldPaint();
1280         node.ResetChildHardwareEnabledNodes();
1281     }
1282     curContentDirty_ = node.IsContentDirty();
1283     bool dirtyFlag = dirtyFlag_;
1284 
1285     RectI prepareClipRect = prepareClipRect_;
1286     bool isQuickSkipPreparationEnabled = isQuickSkipPreparationEnabled_;
1287 
1288     // update geoptr with ContextMatrix
1289     auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
1290     auto& property = node.GetMutableRenderProperties();
1291     auto geoPtr = (property.GetBoundsGeometry());
1292     if (geoPtr == nullptr) {
1293         return;
1294     }
1295     // before node update, prepare node's setting by types
1296     PrepareTypesOfSurfaceRenderNodeBeforeUpdate(node);
1297 
1298     if (curSurfaceDirtyManager_ == nullptr) {
1299         RS_LOGE("RSUniRenderVisitor::PrepareSurfaceRenderNode %{public}s curSurfaceDirtyManager is nullptr",
1300             node.GetName().c_str());
1301         return;
1302     }
1303     auto skipNodeMap = RSMainThread::Instance()->GetCacheCmdSkippedNodes();
1304     if (skipNodeMap.count(node.GetId()) != 0) {
1305         auto parentNode = node.GetParent().lock();
1306         auto rsParent = (parentNode);
1307         dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, rsParent, dirtyFlag_, prepareClipRect_);
1308         dirtyFlag_ = dirtyFlag;
1309         RS_TRACE_NAME(node.GetName() + " PreparedNodes cacheCmdSkiped");
1310         return;
1311     }
1312     // Update node properties, including position (dstrect), OldDirty()
1313     auto parentNode = node.GetParent().lock();
1314     auto rsParent = (parentNode);
1315     auto rsSurfaceParent = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(parentNode);
1316     if (node.IsAppWindow() && rsSurfaceParent && rsSurfaceParent->IsLeashWindow()
1317         && rsSurfaceParent->GetDstRect().IsEmpty()) {
1318             prepareClipRect_ = RectI {0, 0, 0, 0};
1319     }
1320     dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, rsParent, dirtyFlag_, prepareClipRect_);
1321 
1322     // Calculate the absolute destination rectangle of the node, initialize with absolute bounds rect
1323     auto dstRect = geoPtr->GetAbsRect();
1324     // If the screen is expanded, intersect the destination rectangle with the screen rectangle
1325     dstRect = dstRect.IntersectRect(RectI(curDisplayNode_->GetDisplayOffsetX(), curDisplayNode_->GetDisplayOffsetY(),
1326         screenInfo_.width, screenInfo_.height));
1327     // Remove the offset of the screen
1328     dstRect = RectI(dstRect.left_ - curDisplayNode_->GetDisplayOffsetX(),
1329         dstRect.top_ - curDisplayNode_->GetDisplayOffsetY(), dstRect.GetWidth(), dstRect.GetHeight());
1330     // If the node is a hardware-enabled type, intersect its destination rectangle with the prepare clip rectangle
1331     if (node.IsHardwareEnabledType()) {
1332         dstRect = dstRect.IntersectRect(prepareClipRect_);
1333     }
1334     // Set the destination rectangle of the node
1335     node.SetDstRect(dstRect);
1336 
1337     if (node.IsMainWindowType() || node.IsLeashWindow()) {
1338         // record visible node position for display render node dirtyManager
1339         if (node.ShouldPaint()) {
1340             curDisplayNode_->UpdateSurfaceNodePos(node.GetId(), node.GetOldDirty());
1341         }
1342 
1343         if (node.IsAppWindow()) {
1344             // if update appwindow, its children should not skip
1345             localZOrder_ = 0.0f;
1346             isQuickSkipPreparationEnabled_ = false;
1347             if (isSubSurfaceEnabled_) {
1348                 isQuickSkipPreparationEnabled_ = true;
1349             }
1350             node.ResetChildHardwareEnabledNodes();
1351 #ifndef USE_ROSEN_DRAWING
1352             boundsRect_ = SkRect::MakeWH(property.GetBoundsWidth(), property.GetBoundsHeight());
1353 #else
1354             boundsRect_ = Drawing::Rect(0, 0, property.GetBoundsWidth(), property.GetBoundsHeight());
1355 #endif
1356             frameGravity_ = property.GetFrameGravity();
1357         }
1358     }
1359 
1360     // [planning] Remove this after skia is upgraded, the clipRegion is supported
1361     // reset childrenFilterRects
1362     node.ResetChildrenFilterRects();
1363 
1364     dirtyFlag_ = dirtyFlag_ || node.GetDstRectChanged();
1365     parentSurfaceNodeMatrix_ = geoPtr->GetAbsMatrix();
1366     if (RSUniRenderUtil::GetRotationDegreeFromMatrix(parentSurfaceNodeMatrix_) % ROTATION_90 != 0) {
1367         isSurfaceRotationChanged_ = true;
1368         doAnimate_ = true;
1369         node.SetAnimateState();
1370     }
1371 
1372 #if defined(RS_ENABLE_DRIVEN_RENDER)
1373     bool isLeashWindowNode = false;
1374     if (drivenInfo_) {
1375         drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
1376             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || dirtyFlag_;
1377         if (drivenInfo_->drivenUniTreePrepareMode == DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_BEFORE) {
1378             drivenInfo_->prepareInfo.dirtyInfo.backgroundDirty =
1379                 drivenInfo_->prepareInfo.dirtyInfo.backgroundDirty || dirtyFlag_;
1380         } else if (drivenInfo_->drivenUniTreePrepareMode == DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_AFTER) {
1381             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
1382                 drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || node.GetRenderProperties().NeedFilter();
1383         }
1384 
1385         if (node.GetSurfaceNodeType() == RSSurfaceNodeType::LEASH_WINDOW_NODE) {
1386             isLeashWindowNode = true;
1387             drivenInfo_->isPrepareLeashWinSubTree = true;
1388         }
1389         if (node.IsSelfDrawingType()) {
1390             drivenInfo_->prepareInfo.hasInvalidScene = true;
1391         }
1392     }
1393 #endif
1394 
1395     bool isSubNodeOfSurfaceInPrepare = isSubNodeOfSurfaceInPrepare_;
1396     if (node.IsMainWindowType() || node.IsLeashWindow()) {
1397         isSubNodeOfSurfaceInPrepare_ = true;
1398     }
1399     node.UpdateChildrenOutOfRectFlag(false);
1400     // [planning] ShouldPrepareSubnodes would be applied again if condition constraint ensures
1401     PrepareChildren(node);
1402 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
1403     rsParent = (logicParentNode_.lock());
1404     if (rsParent == curDisplayNode_) {
1405         std::unique_lock<std::mutex> lock(*surfaceNodePrepareMutex_);
1406         node.UpdateParentChildrenRect(logicParentNode_.lock());
1407     } else {
1408         node.UpdateParentChildrenRect(logicParentNode_.lock());
1409     }
1410 #else
1411     node.UpdateParentChildrenRect(logicParentNode_.lock());
1412 #endif
1413     // restore flags
1414     parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
1415     dirtyFlag_ = dirtyFlag;
1416     isQuickSkipPreparationEnabled_ = isQuickSkipPreparationEnabled;
1417     prepareClipRect_ = prepareClipRect;
1418     if (node.IsMainWindowType() || node.IsLeashWindow()) {
1419         isSubNodeOfSurfaceInPrepare_ = isSubNodeOfSurfaceInPrepare;
1420     }
1421 
1422     PrepareTypesOfSurfaceRenderNodeAfterUpdate(node);
1423     if (node.GetDstRectChanged() || (node.GetDirtyManager() && node.GetDirtyManager()->IsCurrentFrameDirty())) {
1424         dirtySurfaceNodeMap_.emplace(node.GetId(), node.ReinterpretCastTo<RSSurfaceRenderNode>());
1425     }
1426     UpdateSurfaceRenderNodeScale(node);
1427 #if defined(RS_ENABLE_DRIVEN_RENDER)
1428     if (drivenInfo_ && isLeashWindowNode) {
1429         drivenInfo_->isPrepareLeashWinSubTree = false;
1430     }
1431 #endif
1432     // Due to the alpha is updated in PrepareChildren, so PrepareChildren
1433     // needs to be done before CheckOpaqueRegionBaseInfo
1434     auto screenRotation = curDisplayNode_->GetRotation();
1435     auto screenRect = RectI(0, 0, screenInfo_.width, screenInfo_.height);
1436     Vector4f cornerRadius;
1437     Vector4f::Max(node.GetWindowCornerRadius(), node.GetGlobalCornerRadius(), cornerRadius);
1438     Vector4<int> dstCornerRadius(static_cast<int>(std::ceil(cornerRadius.x_)),
1439                                  static_cast<int>(std::ceil(cornerRadius.y_)),
1440                                  static_cast<int>(std::ceil(cornerRadius.z_)),
1441                                  static_cast<int>(std::ceil(cornerRadius.w_)));
1442     auto parent = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.GetParent().lock());
1443     auto isFocused = node.IsFocusedNode(currentFocusedNodeId_) ||
1444         (parent && parent->IsLeashWindow() && parent->IsFocusedNode(focusedLeashWindowId_));
1445     if (!node.CheckOpaqueRegionBaseInfo(
1446         screenRect, geoPtr->GetAbsRect(), screenRotation, isFocused, dstCornerRadius)
1447         && node.GetSurfaceNodeType() != RSSurfaceNodeType::SELF_DRAWING_NODE) {
1448         node.ResetSurfaceOpaqueRegion(screenRect, geoPtr->GetAbsRect(), screenRotation, isFocused, dstCornerRadius);
1449     }
1450     node.SetOpaqueRegionBaseInfo(screenRect, geoPtr->GetAbsRect(), screenRotation, isFocused, dstCornerRadius);
1451     if (node.IsMainWindowType()) {
1452         // Attention: curSurface info would be reset as upper surfaceParent if it has
1453         ResetCurSurfaceInfoAsUpperSurfaceParent(node);
1454     }
1455 }
1456 
UpdateSurfaceRenderNodeScale(RSSurfaceRenderNode & node)1457 void RSUniRenderVisitor::UpdateSurfaceRenderNodeScale(RSSurfaceRenderNode& node)
1458 {
1459     if (!node.IsLeashWindow()) {
1460         return;
1461     }
1462     auto& property = node.GetMutableRenderProperties();
1463     auto geoPtr = (property.GetBoundsGeometry());
1464     if (geoPtr == nullptr) {
1465         return;
1466     }
1467     auto absMatrix = geoPtr->GetAbsMatrix();
1468     bool isScale = false;
1469     if (RSMainThread::Instance()->GetDeviceType() == DeviceType::PC) {
1470 #ifndef USE_ROSEN_DRAWING
1471         isScale = (!ROSEN_EQ(absMatrix.getScaleX(), 1.f, EPSILON_SCALE) ||
1472             !ROSEN_EQ(absMatrix.getScaleY(), 1.f, EPSILON_SCALE));
1473 #else
1474         isScale = (!ROSEN_EQ(absMatrix.Get(Drawing::Matrix::SCALE_X), 1.f, EPSILON_SCALE) ||
1475             !ROSEN_EQ(absMatrix.Get(Drawing::Matrix::SCALE_Y), 1.f, EPSILON_SCALE));
1476 #endif
1477     } else {
1478         bool getMinMaxScales = false;
1479 #ifndef USE_ROSEN_DRAWING
1480         // skScaleFactors[0]-minimum scaling factor, skScaleFactors[1]-maximum scaling factor
1481         SkScalar skScaleFactors[2];
1482         getMinMaxScales = absMatrix.getMinMaxScales(skScaleFactors);
1483         if (getMinMaxScales) {
1484             isScale = !ROSEN_EQ(skScaleFactors[0], 1.f) || !ROSEN_EQ(skScaleFactors[1], 1.f);
1485         }
1486 #else
1487         // scaleFactors[0]-minimum scaling factor, scaleFactors[1]-maximum scaling factor
1488         Drawing::scalar scaleFactors[2];
1489         getMinMaxScales = absMatrix.GetMinMaxScales(scaleFactors);
1490         if (getMinMaxScales) {
1491             isScale = !ROSEN_EQ(scaleFactors[0], 1.f) || !ROSEN_EQ(scaleFactors[1], 1.f);
1492         }
1493 #endif
1494         if (!getMinMaxScales) {
1495             RS_LOGD("getMinMaxScales fail, node:%{public}s %{public}" PRIu64 "", node.GetName().c_str(), node.GetId());
1496             auto dstRect = node.GetDstRect();
1497             float dstRectWidth = dstRect.GetWidth();
1498             float dstRectHeight = dstRect.GetHeight();
1499             float boundsWidth = property.GetBoundsWidth();
1500             float boundsHeight = property.GetBoundsHeight();
1501             isScale = !ROSEN_EQ(std::min(dstRectWidth, dstRectHeight), std::min(boundsWidth, boundsHeight))
1502                 || !ROSEN_EQ(std::max(dstRectWidth, dstRectHeight), std::max(boundsWidth, boundsHeight));
1503         }
1504     }
1505     node.SetIsScale(isScale);
1506 }
1507 
PrepareProxyRenderNode(RSProxyRenderNode & node)1508 void RSUniRenderVisitor::PrepareProxyRenderNode(RSProxyRenderNode& node)
1509 {
1510     // alpha is not affected by dirty flag, always update
1511     node.SetContextAlpha(curAlpha_);
1512     // skip matrix & clipRegion update if not dirty
1513     if (!dirtyFlag_) {
1514         return;
1515     }
1516     auto rsParent = (logicParentNode_.lock());
1517     if (rsParent == nullptr) {
1518         return;
1519     }
1520     auto& property = rsParent->GetMutableRenderProperties();
1521     auto geoPtr = (property.GetBoundsGeometry());
1522 
1523     // Context matrix should be relative to the parent surface node, so we need to revert the parentSurfaceNodeMatrix_.
1524 #ifndef USE_ROSEN_DRAWING
1525     SkMatrix invertMatrix;
1526     auto contextMatrix = geoPtr->GetAbsMatrix();
1527     if (parentSurfaceNodeMatrix_.invert(&invertMatrix)) {
1528         contextMatrix.preConcat(invertMatrix);
1529     } else {
1530         ROSEN_LOGE("RSUniRenderVisitor::PrepareProxyRenderNode, invert parentSurfaceNodeMatrix_ failed");
1531     }
1532 #else
1533     Drawing::Matrix invertMatrix;
1534     Drawing::Matrix contextMatrix = geoPtr->GetAbsMatrix();
1535 
1536     if (parentSurfaceNodeMatrix_.Invert(invertMatrix)) {
1537         contextMatrix.PreConcat(invertMatrix);
1538     } else {
1539         ROSEN_LOGE("RSUniRenderVisitor::PrepareProxyRenderNode, invert parentSurfaceNodeMatrix_ failed");
1540     }
1541 #endif
1542     node.SetContextMatrix(contextMatrix);
1543 
1544     // For now, we only set the clipRegion if the parent node has ClipToBounds set to true.
1545     if (!property.GetClipToBounds()) {
1546         node.SetContextClipRegion(std::nullopt);
1547     } else {
1548         // Maybe we should use prepareClipRect_ and make the clipRegion in device coordinate, but it will be more
1549         // complex to calculate the intersect, and it will make app developers confused.
1550         auto rect = property.GetBoundsRect();
1551         // Context clip region is in the parent node coordinate, so we don't need to map it.
1552 #ifndef USE_ROSEN_DRAWING
1553         node.SetContextClipRegion(SkRect::MakeXYWH(rect.left_, rect.top_, rect.width_, rect.height_));
1554 #else
1555         node.SetContextClipRegion(Drawing::Rect(
1556             rect.GetLeft(), rect.GetTop(), rect.GetWidth() + rect.GetLeft(), rect.GetHeight() + rect.GetTop()));
1557 #endif
1558     }
1559 
1560     // prepare children
1561     PrepareChildren(node);
1562 }
1563 
PrepareRootRenderNode(RSRootRenderNode & node)1564 void RSUniRenderVisitor::PrepareRootRenderNode(RSRootRenderNode& node)
1565 {
1566     bool dirtyFlag = dirtyFlag_;
1567     auto parentSurfaceNodeMatrix = parentSurfaceNodeMatrix_;
1568     RectI prepareClipRect = prepareClipRect_;
1569 
1570     auto rsParent = (node.GetParent().lock());
1571     const auto& property = node.GetRenderProperties();
1572     bool geoDirty = property.IsGeoDirty();
1573     auto geoPtr = (property.GetBoundsGeometry());
1574 
1575     if (curSurfaceDirtyManager_ == nullptr) {
1576         RS_LOGE("RSUniRenderVisitor::PrepareRootRenderNode curSurfaceDirtyManager is nullptr");
1577         return;
1578     }
1579     dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, rsParent, dirtyFlag_, prepareClipRect_);
1580 #if defined(RS_ENABLE_DRIVEN_RENDER)
1581     if (drivenInfo_) {
1582         drivenInfo_->currentRootNode = node.shared_from_this();
1583         drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
1584             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || dirtyFlag_;
1585         if (drivenInfo_->drivenUniTreePrepareMode == DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_BEFORE) {
1586             drivenInfo_->prepareInfo.dirtyInfo.backgroundDirty = dirtyFlag_;
1587         } else if (drivenInfo_->drivenUniTreePrepareMode == DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_AFTER) {
1588             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
1589                 drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || node.GetRenderProperties().NeedFilter();
1590         }
1591     }
1592 #endif
1593     if (rsParent == curSurfaceNode_) {
1594         const float rootWidth = property.GetFrameWidth() * property.GetScaleX();
1595         const float rootHeight = property.GetFrameHeight() * property.GetScaleY();
1596 #ifndef USE_ROSEN_DRAWING
1597         SkMatrix gravityMatrix;
1598         (void)RSPropertiesPainter::GetGravityMatrix(frameGravity_,
1599             RectF { 0.0f, 0.0f, boundsRect_.width(), boundsRect_.height() }, rootWidth, rootHeight, gravityMatrix);
1600 #else
1601         Drawing::Matrix gravityMatrix;
1602         (void)RSPropertiesPainter::GetGravityMatrix(frameGravity_,
1603             RectF { 0.0f, 0.0f, boundsRect_.GetWidth(), boundsRect_.GetHeight() },
1604             rootWidth, rootHeight, gravityMatrix);
1605 #endif
1606         // Only Apply gravityMatrix when rootNode is dirty
1607         if (geoPtr != nullptr && (dirtyFlag || geoDirty)) {
1608             geoPtr->ConcatMatrix(gravityMatrix);
1609         }
1610     }
1611 
1612     if (geoPtr != nullptr) {
1613         parentSurfaceNodeMatrix_ = geoPtr->GetAbsMatrix();
1614     }
1615     node.UpdateChildrenOutOfRectFlag(false);
1616     PrepareChildren(node);
1617     node.UpdateParentChildrenRect(logicParentNode_.lock());
1618 
1619     parentSurfaceNodeMatrix_ = parentSurfaceNodeMatrix;
1620     dirtyFlag_ = dirtyFlag;
1621     prepareClipRect_ = prepareClipRect;
1622 }
1623 
PrepareCanvasRenderNode(RSCanvasRenderNode & node)1624 void RSUniRenderVisitor::PrepareCanvasRenderNode(RSCanvasRenderNode &node)
1625 {
1626     preparedCanvasNodeInCurrentSurface_++;
1627     curContentDirty_ = node.IsContentDirty();
1628     bool dirtyFlag = dirtyFlag_;
1629     RectI prepareClipRect = prepareClipRect_;
1630 
1631     auto nodeParent = node.GetParent().lock();
1632     while (nodeParent && nodeParent->ReinterpretCastTo<RSSurfaceRenderNode>() &&
1633         nodeParent->ReinterpretCastTo<RSSurfaceRenderNode>()->GetSurfaceNodeType() ==
1634         RSSurfaceNodeType::SELF_DRAWING_NODE) {
1635         nodeParent = nodeParent->GetParent().lock();
1636     }
1637     if (nodeParent) {
1638         node.SetIsAncestorDirty(nodeParent->IsDirty() || nodeParent->IsAncestorDirty());
1639         auto parentSurfaceNode = nodeParent->ReinterpretCastTo<RSSurfaceRenderNode>();
1640         if (parentSurfaceNode && parentSurfaceNode->IsLeashWindow()) {
1641             node.SetParentLeashWindow();
1642         }
1643         if (parentSurfaceNode && parentSurfaceNode->IsScbScreen()) {
1644             node.SetParentScbScreen();
1645         }
1646     }
1647     if (curSurfaceDirtyManager_ == nullptr || curDisplayDirtyManager_ == nullptr) {
1648         RS_LOGE("RSUniRenderVisitor::PrepareCanvasRenderNode curXDirtyManager is nullptr");
1649         return;
1650     }
1651     if (node.GetSharedTransitionParam().has_value()) {
1652         node.GetMutableRenderProperties().UpdateSandBoxMatrix(parentSurfaceNodeMatrix_);
1653     }
1654     if (isSubNodeOfSurfaceInPrepare_ && curSurfaceNode_ &&
1655         curSurfaceNode_->IsHardwareEnabledTopSurface() && node.ShouldPaint()) {
1656         curSurfaceNode_->SetSubNodeShouldPaint();
1657     }
1658     // if canvasNode is not sub node of surfaceNode, merge the dirtyRegion to curDisplayDirtyManager_
1659     auto dirtyManager = isSubNodeOfSurfaceInPrepare_ ? curSurfaceDirtyManager_ : curDisplayDirtyManager_;
1660     dirtyFlag_ = node.Update(*dirtyManager, nodeParent, dirtyFlag_, prepareClipRect_);
1661 
1662 #if defined(RS_ENABLE_DRIVEN_RENDER)
1663     // driven render
1664     bool isContentCanvasNode = false;
1665     bool isBeforeContentNodeDirty = false;
1666     if (drivenInfo_ && currentVisitDisplay_ == 0 && drivenInfo_->isPrepareLeashWinSubTree && node.IsMarkDriven()) {
1667         auto drivenCanvasNode = RSDrivenRenderManager::GetInstance().GetContentSurfaceNode()->GetDrivenCanvasNode();
1668         if (node.IsMarkDrivenRender() ||
1669             (!drivenInfo_->hasDrivenNodeMarkRender &&
1670             drivenCanvasNode != nullptr && node.GetId() == drivenCanvasNode->GetId())) {
1671             drivenInfo_->prepareInfo.backgroundNode = drivenInfo_->currentRootNode;
1672             drivenInfo_->prepareInfo.contentNode = node.shared_from_this();
1673             drivenInfo_->drivenUniTreePrepareMode = DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE;
1674             drivenInfo_->prepareInfo.dirtyInfo.contentDirty = false;
1675             drivenInfo_->surfaceDirtyManager = curSurfaceDirtyManager_;
1676             isContentCanvasNode = true;
1677             isBeforeContentNodeDirty = drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty;
1678             if (node.IsMarkDrivenRender()) {
1679                 drivenInfo_->prepareInfo.dirtyInfo.type = DrivenDirtyType::MARK_DRIVEN_RENDER;
1680             } else {
1681                 drivenInfo_->prepareInfo.dirtyInfo.type = DrivenDirtyType::MARK_DRIVEN;
1682             }
1683         }
1684     }
1685     if (drivenInfo_) {
1686         drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
1687             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || dirtyFlag_;
1688         if (drivenInfo_->drivenUniTreePrepareMode == DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_BEFORE) {
1689             drivenInfo_->prepareInfo.dirtyInfo.backgroundDirty =
1690                 drivenInfo_->prepareInfo.dirtyInfo.backgroundDirty || dirtyFlag_;
1691         } else if (drivenInfo_->drivenUniTreePrepareMode == DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_AFTER) {
1692             drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty =
1693                 drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty || node.GetRenderProperties().NeedFilter();
1694         } else {
1695             if (node.IsContentChanged()) {
1696                 drivenInfo_->prepareInfo.dirtyInfo.contentDirty = true;
1697             }
1698         }
1699         if (node.IsContentChanged()) {
1700             node.SetIsContentChanged(false);
1701         }
1702     }
1703 #endif
1704     const auto& property = node.GetRenderProperties();
1705     auto geoPtr = (property.GetBoundsGeometry());
1706     if (geoPtr == nullptr) {
1707         return;
1708     }
1709     // Dirty Region use abstract coordinate, property of node use relative coordinate
1710     // BoundsRect(if exists) is mapped to absRect_ of RSObjAbsGeometry.
1711     if (property.GetClipToBounds()) {
1712         prepareClipRect_ = prepareClipRect_.IntersectRect(geoPtr->GetAbsRect());
1713     }
1714     // FrameRect(if exists) is mapped to rect using abstract coordinate explicitly by calling MapAbsRect.
1715     if (property.GetClipToFrame()) {
1716         // MapAbsRect do not handle the translation of OffsetX and OffsetY
1717 #ifndef USE_ROSEN_DRAWING
1718         RectF frameRect{
1719             property.GetFrameOffsetX() * geoPtr->GetAbsMatrix().getScaleX(),
1720             property.GetFrameOffsetY() * geoPtr->GetAbsMatrix().getScaleY(),
1721             property.GetFrameWidth(), property.GetFrameHeight()};
1722 #else
1723         RectF frameRect{
1724             property.GetFrameOffsetX() * geoPtr->GetAbsMatrix().Get(Drawing::Matrix::SCALE_X),
1725             property.GetFrameOffsetY() * geoPtr->GetAbsMatrix().Get(Drawing::Matrix::SCALE_Y),
1726             property.GetFrameWidth(), property.GetFrameHeight()};
1727 #endif
1728         prepareClipRect_ = prepareClipRect_.IntersectRect(geoPtr->MapAbsRect(frameRect));
1729     }
1730 
1731     node.UpdateChildrenOutOfRectFlag(false);
1732 
1733     if (isSkipCanvasNodeOutOfScreen_ && !isSubNodeOfSurfaceInPrepare_ && !node.HasSubSurface() &&
1734         IsOutOfScreenRegion(geoPtr->GetAbsRect())) {
1735         return;
1736     }
1737 
1738     PrepareChildren(node);
1739     // attention: accumulate direct parent's childrenRect
1740     node.UpdateParentChildrenRect(logicParentNode_.lock());
1741     if (property.GetUseEffect()) {
1742         if (auto directParent = node.GetParent().lock()) {
1743             directParent->SetUseEffectNodes(true);
1744         }
1745     }
1746 
1747     node.UpdateEffectRegion(effectRegion_);
1748     if (property.NeedFilter()) {
1749         // filterRects_ is used in RSUniRenderVisitor::CalcDirtyFilterRegion
1750         // When oldDirtyRect of node with filter has intersect with any surfaceNode or displayNode dirtyRegion,
1751         // the whole oldDirtyRect should be render in this vsync.
1752         // Partial rendering of node with filter would cause display problem.
1753         if (auto directParent = node.GetParent().lock()) {
1754             directParent->SetChildHasFilter(true);
1755         }
1756         if (curSurfaceDirtyManager_->IsTargetForDfx()) {
1757             curSurfaceDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::CANVAS_NODE,
1758                 DirtyRegionType::FILTER_RECT, node.GetOldDirtyInSurface());
1759         }
1760         if (curSurfaceNode_) {
1761             curSurfaceNode_->UpdateChildrenFilterRects(node.shared_from_this(), node.GetOldDirtyInSurface(),
1762                 node.IsBackgroundFilterCacheValid());
1763             curSurfaceNode_->UpdateFilterNodes(node.shared_from_this());
1764         }
1765         UpdateForegroundFilterCacheWithDirty(node, *dirtyManager);
1766     }
1767     dirtyFlag_ = dirtyFlag;
1768     prepareClipRect_ = prepareClipRect;
1769 #if defined(RS_ENABLE_DRIVEN_RENDER)
1770     // skip content node and its children, calculate dirty contain background and foreground
1771     if (drivenInfo_ && isContentCanvasNode) {
1772         drivenInfo_->prepareInfo.dirtyInfo.nonContentDirty = isBeforeContentNodeDirty;
1773         drivenInfo_->drivenUniTreePrepareMode = DrivenUniTreePrepareMode::PREPARE_DRIVEN_NODE_AFTER;
1774     }
1775 #endif
1776 }
1777 
PrepareEffectRenderNode(RSEffectRenderNode & node)1778 void RSUniRenderVisitor::PrepareEffectRenderNode(RSEffectRenderNode& node)
1779 {
1780     bool dirtyFlag = dirtyFlag_;
1781     RectI prepareClipRect = prepareClipRect_;
1782     auto effectRegion = effectRegion_;
1783     effectRegion_ = node.InitializeEffectRegion();
1784 
1785     // set rotationChanged true when screen is rotating or folding/expanding screen.
1786     if (curDisplayNode_->IsRotationChanged() || (!curDisplayNode_->IsRotationChanged() && doAnimate_)) {
1787         node.SetRotationChanged(true);
1788         int invalidateTimes = 2; // node call invalidate cache 3 times in one frame.
1789         node.SetInvalidateTimesForRotation(invalidateTimes);
1790     } else {
1791         node.SetRotationChanged(false);
1792     }
1793     auto parentNode = node.GetParent().lock();
1794     node.SetVisitedFilterCacheStatus(curSurfaceDirtyManager_->IsCacheableFilterRectEmpty());
1795     dirtyFlag_ = node.Update(*curSurfaceDirtyManager_, parentNode, dirtyFlag_, prepareClipRect_);
1796 
1797     node.UpdateChildrenOutOfRectFlag(false);
1798     PrepareChildren(node);
1799     node.UpdateParentChildrenRect(logicParentNode_.lock());
1800     node.SetEffectRegion(effectRegion_);
1801 
1802     if (node.GetRenderProperties().NeedFilter()) {
1803         // filterRects_ is used in RSUniRenderVisitor::CalcDirtyFilterRegion
1804         // When oldDirtyRect of node with filter has intersect with any surfaceNode or displayNode dirtyRegion,
1805         // the whole oldDirtyRect should be render in this vsync.
1806         // Partial rendering of node with filter would cause display problem.
1807         if (parentNode) {
1808             parentNode->SetChildHasFilter(true);
1809         }
1810         if (curSurfaceDirtyManager_->IsTargetForDfx()) {
1811             curSurfaceDirtyManager_->UpdateDirtyRegionInfoForDfx(node.GetId(), RSRenderNodeType::CANVAS_NODE,
1812                 DirtyRegionType::FILTER_RECT, node.GetOldDirtyInSurface());
1813         }
1814 #ifndef USE_ROSEN_DRAWING
1815         if (curSurfaceNode_ && effectRegion_.has_value() && !effectRegion_->isEmpty()) {
1816             RectI filterRect(effectRegion_->left(), effectRegion_->top(),
1817                 effectRegion_->width(), effectRegion_->height());
1818 #else
1819         if (curSurfaceNode_ && effectRegion_.has_value() && !effectRegion_->IsEmpty()) {
1820             RectI filterRect(effectRegion_->GetLeft(), effectRegion_->GetTop(),
1821                 effectRegion_->GetWidth(), effectRegion_->GetHeight());
1822 #endif
1823             curSurfaceNode_->UpdateChildrenFilterRects(node.shared_from_this(), filterRect,
1824                 node.IsBackgroundFilterCacheValid());
1825             curSurfaceNode_->UpdateFilterNodes(node.shared_from_this());
1826         }
1827         UpdateForegroundFilterCacheWithDirty(node, *curSurfaceDirtyManager_);
1828     }
1829 
1830     effectRegion_ = effectRegion;
1831     dirtyFlag_ = dirtyFlag;
1832     prepareClipRect_ = prepareClipRect;
1833 }
1834 
1835 void RSUniRenderVisitor::CopyForParallelPrepare(std::shared_ptr<RSUniRenderVisitor> visitor)
1836 {
1837 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
1838     isPartialRenderEnabled_ = isPartialRenderEnabled_ && visitor->isPartialRenderEnabled_;
1839     isOpDropped_ = isOpDropped_ && visitor->isOpDropped_;
1840     needFilter_ = needFilter_ || visitor->needFilter_;
1841     for (const auto &u : visitor->displayHasSecSurface_) {
1842         displayHasSecSurface_[u.first] = displayHasSecSurface_[u.first] || u.second;
1843     }
1844     for (const auto &u : visitor->displayHasSkipSurface_) {
1845         displayHasSkipSurface_[u.first] = displayHasSkipSurface_[u.first] || u.second;
1846     }
1847     for (const auto &u : visitor->dirtySurfaceNodeMap_) {
1848         dirtySurfaceNodeMap_[u.first] = u.second;
1849     }
1850     for (const auto &u : visitor->hasCaptureWindow_) {
1851         hasCaptureWindow_[u.first] = u.second;
1852     }
1853 
1854 #endif
1855 }
1856 
1857 #ifndef USE_ROSEN_DRAWING
1858 void RSUniRenderVisitor::DrawDirtyRectForDFX(const RectI& dirtyRect, const SkColor color,
1859     const SkPaint::Style fillType, float alpha, int edgeWidth = 6)
1860 {
1861     if (dirtyRect.width_ <= 0 || dirtyRect.height_ <= 0) {
1862         ROSEN_LOGD("DrawDirtyRectForDFX dirty rect is invalid.");
1863         return;
1864     }
1865     ROSEN_LOGD("DrawDirtyRectForDFX current dirtyRect = %{public}s", dirtyRect.ToString().c_str());
1866     auto skRect = SkRect::MakeXYWH(dirtyRect.left_, dirtyRect.top_, dirtyRect.width_, dirtyRect.height_);
1867     std::string position = std::to_string(dirtyRect.left_) + ',' + std::to_string(dirtyRect.top_) + ',' +
1868         std::to_string(dirtyRect.width_) + ',' + std::to_string(dirtyRect.height_);
1869     const int defaultTextOffsetX = edgeWidth;
1870     const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the skRect
1871     SkPaint rectPaint;
1872     // font size: 24
1873     sk_sp<SkTypeface> typeface = SkTypeface::MakeFromName("HarmonyOS Sans SC", SkFontStyle::Normal());
1874     sk_sp<SkTextBlob> SkTextBlob = SkTextBlob::MakeFromString(position.c_str(), SkFont(typeface, 24.0f, 1.0f, 0.0f));
1875     rectPaint.setColor(color);
1876     rectPaint.setAntiAlias(true);
1877     rectPaint.setAlphaf(alpha);
1878     rectPaint.setStyle(fillType);
1879     rectPaint.setStrokeWidth(edgeWidth);
1880     if (fillType == SkPaint::kFill_Style) {
1881         rectPaint.setStrokeJoin(SkPaint::kRound_Join);
1882     }
1883     canvas_->drawRect(skRect, rectPaint);
1884     canvas_->drawTextBlob(SkTextBlob, dirtyRect.left_ + defaultTextOffsetX,
1885         dirtyRect.top_ + defaultTextOffsetY, SkPaint());
1886 }
1887 #else
1888 void RSUniRenderVisitor::DrawDirtyRectForDFX(const RectI& dirtyRect, const Drawing::Color color,
1889     const RSPaintStyle fillType, float alpha, int edgeWidth = 6)
1890 {
1891     if (dirtyRect.width_ <= 0 || dirtyRect.height_ <= 0) {
1892         ROSEN_LOGD("DrawDirtyRectForDFX dirty rect is invalid.");
1893         return;
1894     }
1895     ROSEN_LOGD("DrawDirtyRectForDFX current dirtyRect = %{public}s", dirtyRect.ToString().c_str());
1896     auto rect = Drawing::Rect(dirtyRect.left_, dirtyRect.top_,
1897         dirtyRect.left_ + dirtyRect.width_, dirtyRect.top_ + dirtyRect.height_);
1898     std::string position = std::to_string(dirtyRect.left_) + ',' + std::to_string(dirtyRect.top_) + ',' +
1899         std::to_string(dirtyRect.width_) + ',' + std::to_string(dirtyRect.height_);
1900     const int defaultTextOffsetX = edgeWidth;
1901     const int defaultTextOffsetY = 30; // text position has 30 pixelSize under the Rect
1902     Drawing::Pen rectPen;
1903     Drawing::Brush rectBrush;
1904     // font size: 24
1905     std::shared_ptr<Drawing::TextBlob> textBlob =
1906         Drawing::TextBlob::MakeFromString(position.c_str(), Drawing::Font(nullptr, 24.0f, 1.0f, 0.0f));
1907     if (fillType == RSPaintStyle::STROKE) {
1908         rectPen.SetColor(color);
1909         rectPen.SetAntiAlias(true);
1910         rectPen.SetAlphaF(alpha);
1911         rectPen.SetWidth(edgeWidth);
1912         rectPen.SetJoinStyle(Drawing::Pen::JoinStyle::ROUND_JOIN);
1913         canvas_->AttachPen(rectPen);
1914     } else {
1915         rectBrush.SetColor(color);
1916         rectBrush.SetAntiAlias(true);
1917         rectBrush.SetAlphaF(alpha);
1918         canvas_->AttachBrush(rectBrush);
1919     }
1920     canvas_->DrawRect(rect);
1921     canvas_->DetachPen();
1922     canvas_->DetachBrush();
1923     canvas_->AttachBrush(Drawing::Brush());
1924     canvas_->DrawTextBlob(textBlob.get(), dirtyRect.left_ + defaultTextOffsetX, dirtyRect.top_ + defaultTextOffsetY);
1925     canvas_->DetachBrush();
1926 }
1927 #endif
1928 
1929 void RSUniRenderVisitor::DrawDirtyRegionForDFX(std::vector<RectI> dirtyRects)
1930 {
1931     const float fillAlpha = 0.2;
1932     for (const auto& subRect : dirtyRects) {
1933 #ifndef USE_ROSEN_DRAWING
1934         DrawDirtyRectForDFX(subRect, SK_ColorBLUE, SkPaint::kStroke_Style, fillAlpha);
1935 #else
1936         DrawDirtyRectForDFX(subRect, Drawing::Color::COLOR_BLUE, RSPaintStyle::STROKE, fillAlpha);
1937 #endif
1938     }
1939 }
1940 
1941 void RSUniRenderVisitor::DrawCacheRegionForDFX(std::vector<RectI> cacheRects)
1942 {
1943     const float fillAlpha = 0.2;
1944     for (const auto& subRect : cacheRects) {
1945 #ifndef USE_ROSEN_DRAWING
1946         DrawDirtyRectForDFX(subRect, SK_ColorBLUE, SkPaint::kFill_Style, fillAlpha);
1947 #else
1948         DrawDirtyRectForDFX(subRect, Drawing::Color::COLOR_BLUE, RSPaintStyle::FILL, fillAlpha);
1949 #endif
1950     }
1951 }
1952 
1953 void RSUniRenderVisitor::DrawAllSurfaceDirtyRegionForDFX(RSDisplayRenderNode& node, const Occlusion::Region& region)
1954 {
1955     const auto& visibleDirtyRects = region.GetRegionRects();
1956     std::vector<RectI> rects;
1957     for (auto& rect : visibleDirtyRects) {
1958         rects.emplace_back(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
1959     }
1960     DrawDirtyRegionForDFX(rects);
1961 
1962     // draw display dirtyregion with red color
1963     RectI dirtySurfaceRect = node.GetDirtyManager()->GetDirtyRegion();
1964     const float fillAlpha = 0.2;
1965 #ifndef USE_ROSEN_DRAWING
1966     DrawDirtyRectForDFX(dirtySurfaceRect, SK_ColorRED, SkPaint::kStroke_Style, fillAlpha);
1967 #else
1968     DrawDirtyRectForDFX(dirtySurfaceRect, Drawing::Color::COLOR_RED, RSPaintStyle::STROKE, fillAlpha);
1969 #endif
1970 }
1971 
1972 void RSUniRenderVisitor::DrawAllSurfaceOpaqueRegionForDFX(RSDisplayRenderNode& node)
1973 {
1974     for (auto& it : node.GetCurAllSurfaces()) {
1975         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(it);
1976         if (surfaceNode->IsMainWindowType()) {
1977             DrawSurfaceOpaqueRegionForDFX(*surfaceNode);
1978         }
1979     }
1980 }
1981 
1982 void RSUniRenderVisitor::DrawTargetSurfaceDirtyRegionForDFX(RSDisplayRenderNode& node)
1983 {
1984     for (auto it = node.GetCurAllSurfaces().rbegin(); it != node.GetCurAllSurfaces().rend(); ++it) {
1985         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
1986         if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
1987             continue;
1988         }
1989         if (CheckIfSurfaceTargetedForDFX(surfaceNode->GetName())) {
1990             if (DrawDetailedTypesOfDirtyRegionForDFX(*surfaceNode)) {
1991                 continue;
1992             }
1993             const auto& visibleDirtyRegions = surfaceNode->GetVisibleDirtyRegion().GetRegionRects();
1994             std::vector<RectI> rects;
1995             for (auto& rect : visibleDirtyRegions) {
1996                 rects.emplace_back(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
1997             }
1998             const auto& visibleRegions = surfaceNode->GetVisibleRegion().GetRegionRects();
1999             auto displayDirtyRegion = node.GetDirtyManager()->GetDirtyRegion();
2000             for (auto& rect : visibleRegions) {
2001                 auto visibleRect = RectI(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
2002                 auto intersectRegion = displayDirtyRegion.IntersectRect(visibleRect);
2003                 rects.emplace_back(intersectRegion);
2004             }
2005             DrawDirtyRegionForDFX(rects);
2006         }
2007     }
2008 }
2009 
2010 void RSUniRenderVisitor::DrawTargetSurfaceVisibleRegionForDFX(RSDisplayRenderNode& node)
2011 {
2012     for (auto it = node.GetCurAllSurfaces().rbegin(); it != node.GetCurAllSurfaces().rend(); ++it) {
2013         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
2014         if (surfaceNode == nullptr || !surfaceNode->IsAppWindow()) {
2015             continue;
2016         }
2017         if (CheckIfSurfaceTargetedForDFX(surfaceNode->GetName())) {
2018             const auto& visibleRegions = surfaceNode->GetVisibleRegion().GetRegionRects();
2019             std::vector<RectI> rects;
2020             for (auto& rect : visibleRegions) {
2021                 rects.emplace_back(rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_);
2022             }
2023             DrawDirtyRegionForDFX(rects);
2024         }
2025     }
2026 }
2027 
2028 void RSUniRenderVisitor::DrawEffectRenderNodeForDFX()
2029 {
2030     if (effectNodeMapForDfx_.empty()) {
2031         return;
2032     }
2033     const float strokeAlpha = 0.8;
2034     const int strokeWidth = 12;
2035     const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
2036     for (const auto& effectNode : effectNodeMapForDfx_) {
2037         auto node = nodeMap.GetRenderNode<RSRenderNode>(effectNode.first);
2038         if (!node) {
2039             continue;
2040         }
2041         auto geoPtr = node->GetRenderProperties().GetBoundsGeometry();
2042         if (geoPtr == nullptr) {
2043             continue;
2044         }
2045         RectI absRect = geoPtr->GetAbsRect();
2046         // draw effectNode
2047 #ifndef USE_ROSEN_DRAWING
2048         DrawDirtyRectForDFX(absRect, SK_ColorBLUE, SkPaint::kStroke_Style, strokeAlpha, strokeWidth);
2049 #else
2050         DrawDirtyRectForDFX(absRect, Drawing::Color::COLOR_BLUE, RSPaintStyle::STROKE, strokeAlpha, strokeWidth);
2051 #endif
2052         // draw useEffect nodes
2053         const auto& useEffectRects = effectNode.second.first;
2054         for (const auto& rect : useEffectRects) {
2055 #ifndef USE_ROSEN_DRAWING
2056             DrawDirtyRectForDFX(rect, SK_ColorGREEN, SkPaint::kStroke_Style, strokeAlpha, strokeWidth);
2057 #else
2058             DrawDirtyRectForDFX(rect, Drawing::Color::COLOR_GREEN, RSPaintStyle::STROKE, strokeAlpha, strokeWidth);
2059 #endif
2060         }
2061 
2062         // draw fallback nodes
2063         const auto fallbackRects = effectNode.second.second;
2064         for (const auto& rect : fallbackRects) {
2065 #ifndef USE_ROSEN_DRAWING
2066             DrawDirtyRectForDFX(rect, SK_ColorRED, SkPaint::kStroke_Style, strokeAlpha, strokeWidth);
2067 #else
2068             DrawDirtyRectForDFX(rect, Drawing::Color::COLOR_RED, RSPaintStyle::STROKE, strokeAlpha, strokeWidth);
2069 #endif
2070         }
2071     }
2072 }
2073 
2074 void RSUniRenderVisitor::DrawCurrentRefreshRate(uint32_t currentRefreshRate, uint32_t realtimeRefreshRate)
2075 {
2076     std::string info = std::to_string(currentRefreshRate) + " " + std::to_string(realtimeRefreshRate);
2077     auto color = currentRefreshRate <= 60 ? SK_ColorRED : SK_ColorGREEN;
2078 #ifndef USE_ROSEN_DRAWING
2079     sk_sp<SkTypeface> tf = SkTypeface::MakeFromName("HarmonyOS Sans SC", SkFontStyle::Normal());
2080     SkFont font;
2081     font.setSize(100);  // 100:Scalar of setting font size
2082     font.setTypeface(tf);
2083     sk_sp<SkTextBlob> textBlob = SkTextBlob::MakeFromString(info.c_str(), font);
2084 
2085     SkPaint paint;
2086     paint.setColor(color);
2087     paint.setAntiAlias(true);
2088     canvas_->drawTextBlob(
2089         textBlob, 100.f, 200.f, paint);  // 100.f:Scalar x of drawing TextBlob; 200.f:Scalar y of drawing TextBlob
2090 #else
2091     std::shared_ptr<Drawing::Typeface> tf = Drawing::Typeface::MakeFromName("HarmonyOS Sans SC", Drawing::FontStyle());
2092     Drawing::Font font;
2093     font.SetSize(100);  // 100:Scalar of setting font size
2094     font.SetTypeface(tf);
2095     std::shared_ptr<Drawing::TextBlob> textBlob = Drawing::TextBlob::MakeFromString(info.c_str(), font);
2096 
2097     Drawing::Brush brush;
2098     brush.SetColor(color);
2099     brush.SetAntiAlias(true);
2100     canvas_->AttachBrush(brush);
2101     canvas_->DrawTextBlob(
2102         textBlob.get(), 100.f, 200.f);  // 100.f:Scalar x of drawing TextBlob; 200.f:Scalar y of drawing TextBlob
2103     canvas_->DetachBrush();
2104 #endif
2105 }
2106 
2107 void RSUniRenderVisitor::DrawAndTraceSingleDirtyRegionTypeForDFX(RSSurfaceRenderNode& node,
2108     DirtyRegionType dirtyType, bool isDrawn)
2109 {
2110     auto dirtyManager = node.GetDirtyManager();
2111     auto matchType = DIRTY_REGION_TYPE_MAP.find(dirtyType);
2112     if (dirtyManager == nullptr ||  matchType == DIRTY_REGION_TYPE_MAP.end()) {
2113         return;
2114     }
2115     std::map<NodeId, RectI> dirtyInfo;
2116     float fillAlpha = 0.2;
2117     std::map<RSRenderNodeType, std::pair<std::string, SkColor>> nodeConfig = {
2118         {RSRenderNodeType::CANVAS_NODE, std::make_pair("canvas", SK_ColorRED)},
2119         {RSRenderNodeType::SURFACE_NODE, std::make_pair("surface", SK_ColorGREEN)},
2120     };
2121 
2122     std::string subInfo;
2123     for (const auto& [nodeType, info] : nodeConfig) {
2124         dirtyManager->GetDirtyRegionInfo(dirtyInfo, nodeType, dirtyType);
2125         subInfo += (" " + info.first + "node amount: " + std::to_string(dirtyInfo.size()));
2126         for (const auto& [nid, rect] : dirtyInfo) {
2127             if (isDrawn) {
2128 #ifndef USE_ROSEN_DRAWING
2129                 DrawDirtyRectForDFX(rect, info.second, SkPaint::kStroke_Style, fillAlpha);
2130 #else
2131                 DrawDirtyRectForDFX(rect, info.second, RSPaintStyle::STROKE, fillAlpha);
2132 #endif
2133             }
2134         }
2135     }
2136     RS_TRACE_NAME("DrawAndTraceSingleDirtyRegionTypeForDFX target surface node " + node.GetName() + " - id[" +
2137         std::to_string(node.GetId()) + "] has dirtytype " + matchType->second + subInfo);
2138     ROSEN_LOGD("DrawAndTraceSingleDirtyRegionTypeForDFX target surface node %{public}s, id[%{public}" PRIu64 "]"
2139         "has dirtytype %{public}s%{public}s",
2140         node.GetName().c_str(), node.GetId(), matchType->second.c_str(), subInfo.c_str());
2141 }
2142 
2143 bool RSUniRenderVisitor::DrawDetailedTypesOfDirtyRegionForDFX(RSSurfaceRenderNode& node)
2144 {
2145     if (dirtyRegionDebugType_ < DirtyRegionDebugType::CUR_DIRTY_DETAIL_ONLY_TRACE) {
2146         return false;
2147     }
2148     if (dirtyRegionDebugType_ == DirtyRegionDebugType::CUR_DIRTY_DETAIL_ONLY_TRACE) {
2149         auto i = DirtyRegionType::UPDATE_DIRTY_REGION;
2150         for (; i < DirtyRegionType::TYPE_AMOUNT; i = (DirtyRegionType)(i + 1)) {
2151             DrawAndTraceSingleDirtyRegionTypeForDFX(node, i, false);
2152         }
2153         return true;
2154     }
2155     const std::map<DirtyRegionDebugType, DirtyRegionType> DIRTY_REGION_DEBUG_TYPE_MAP {
2156         { DirtyRegionDebugType::UPDATE_DIRTY_REGION, DirtyRegionType::UPDATE_DIRTY_REGION },
2157         { DirtyRegionDebugType::OVERLAY_RECT, DirtyRegionType::OVERLAY_RECT },
2158         { DirtyRegionDebugType::FILTER_RECT, DirtyRegionType::FILTER_RECT },
2159         { DirtyRegionDebugType::SHADOW_RECT, DirtyRegionType::SHADOW_RECT },
2160         { DirtyRegionDebugType::PREPARE_CLIP_RECT, DirtyRegionType::PREPARE_CLIP_RECT },
2161         { DirtyRegionDebugType::REMOVE_CHILD_RECT, DirtyRegionType::REMOVE_CHILD_RECT },
2162         { DirtyRegionDebugType::RENDER_PROPERTIES_RECT, DirtyRegionType::RENDER_PROPERTIES_RECT },
2163         { DirtyRegionDebugType::CANVAS_NODE_SKIP_RECT, DirtyRegionType::CANVAS_NODE_SKIP_RECT },
2164         { DirtyRegionDebugType::OUTLINE_RECT, DirtyRegionType::OUTLINE_RECT },
2165     };
2166     auto matchType = DIRTY_REGION_DEBUG_TYPE_MAP.find(dirtyRegionDebugType_);
2167     if (matchType != DIRTY_REGION_DEBUG_TYPE_MAP.end()) {
2168         DrawAndTraceSingleDirtyRegionTypeForDFX(node, matchType->second);
2169     }
2170     return true;
2171 }
2172 
2173 void RSUniRenderVisitor::DrawSurfaceOpaqueRegionForDFX(RSSurfaceRenderNode& node)
2174 {
2175     const auto& opaqueRegionRects = node.GetOpaqueRegion().GetRegionRects();
2176     for (const auto &subRect: opaqueRegionRects) {
2177 #ifndef USE_ROSEN_DRAWING
2178         DrawDirtyRectForDFX(subRect.ToRectI(), SK_ColorGREEN, SkPaint::kFill_Style, 0.2f, 0);
2179 #else
2180         DrawDirtyRectForDFX(subRect.ToRectI(), Drawing::Color::COLOR_GREEN,
2181             RSPaintStyle::FILL, 0.2f, 0);
2182 #endif
2183     }
2184 }
2185 
2186 void RSUniRenderVisitor::ProcessShadowFirst(RSRenderNode& node, bool inSubThread)
2187 {
2188     if (RSSystemProperties::GetUseShadowBatchingEnabled()
2189         && (node.GetRenderProperties().GetUseShadowBatching())) {
2190         auto children = node.GetSortedChildren();
2191         for (auto& child : *children) {
2192             if (auto node = child->ReinterpretCastTo<RSCanvasRenderNode>()) {
2193                 node->ProcessShadowBatching(*canvas_);
2194             }
2195         }
2196     }
2197 }
2198 
2199 void RSUniRenderVisitor::CheckSkipRepeatShadow(RSRenderNode& node, const bool resetStatus)
2200 {
2201     // In normal process, if shadow has drawn in drawCacheWithBlur, no need to draw again in children node
2202     // not comming from drawCacheWithBlur and updateCacheProcess, child has shadow,skip draw shadow child later
2203     if (!drawCacheWithBlur_ && !notRunCheckAndSetNodeCacheType_ && !allCacheFilterRects_[node.GetId()].empty() &&
2204         node.ChildHasFilter() && updateCacheProcessCnt_ == 0) {
2205         if (resetStatus) {
2206             RS_TRACE_NAME("status reset");
2207             noNeedTodrawShadowAgain_ = false;
2208             return;
2209         }
2210         noNeedTodrawShadowAgain_ = true;
2211     }
2212 }
2213 
2214 void RSUniRenderVisitor::SetNodeSkipShadow(std::shared_ptr<RSRenderNode> node, const bool resetStatus)
2215 {
2216     // skip shadow drawing in updateCacheProcess,it will draw in drawCacheWithBlur
2217     // and skip shadow repeat drawing in normal process
2218     if (!drawCacheWithBlur_ && node->GetRenderProperties().GetShadowColorStrategy() !=
2219         SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE &&
2220         (updateCacheProcessCnt_ != 0 || noNeedTodrawShadowAgain_)) {
2221         ROSEN_LOGD("skip draw shadow and text repeatly");
2222         if (resetStatus) {
2223             node->GetMutableRenderProperties().SetNeedSkipShadow(false);
2224             return;
2225         }
2226         node->GetMutableRenderProperties().SetNeedSkipShadow(true);
2227     }
2228 }
2229 
2230 void RSUniRenderVisitor::ProcessChildren(RSRenderNode& node)
2231 {
2232     if (DrawBlurInCache(node)) {
2233         return;
2234     }
2235 
2236     CheckSkipRepeatShadow(node, false);
2237     const auto children = node.GetSortedChildren();
2238 
2239     if (isSubThread_) {
2240         node.SetIsUsedBySubThread(true);
2241         ProcessShadowFirst(node, isSubThread_);
2242         for (auto child : *children) {
2243             ProcessChildInner(node, child);
2244         }
2245         node.SetIsUsedBySubThread(false);
2246     } else {
2247         ProcessShadowFirst(node, isSubThread_);
2248         for (auto child : *children) {
2249             SetNodeSkipShadow(child, false);
2250             ProcessChildInner(node, child);
2251             SetNodeSkipShadow(child, true);
2252         }
2253     }
2254 
2255     CheckSkipRepeatShadow(node, true);
2256 }
2257 
2258 void RSUniRenderVisitor::ProcessChildrenForScreenRecordingOptimization(
2259     RSDisplayRenderNode& node, NodeId rootIdOfCaptureWindow)
2260 {
2261     if (DrawBlurInCache(node)) {
2262         return;
2263     }
2264     // just process child above the root of capture window
2265     bool startVisit = false;
2266     for (auto child : *node.GetSortedChildren()) {
2267         if (child->GetId() == rootIdOfCaptureWindow) {
2268             startVisit = true;
2269         }
2270         if (startVisit) {
2271             ProcessChildInner(node, child);
2272         } else {
2273             RS_LOGD("RSUniRenderVisitor::ProcessChildrenForScreenRecordingOptimization "\
2274                 "skip process node %{public}s because of screen recording optimization",
2275                 std::to_string(child->GetId()).c_str());
2276         }
2277     }
2278 }
2279 
2280 void RSUniRenderVisitor::ProcessChildInner(RSRenderNode& node, const RSRenderNode::SharedPtr child)
2281 {
2282     if (child && ProcessSharedTransitionNode(*child)) {
2283         if (node.GetDrawingCacheRootId() != INVALID_NODEID) {
2284             child->SetDrawingCacheRootId(node.GetDrawingCacheRootId());
2285         }
2286         SaveCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
2287         UpdateVirtualScreenFilterAppRootId(child);
2288         child->Process(shared_from_this());
2289         UpdateVirtualScreenFilterAppRootId(child);
2290         RestoreCurSurface(curSurfaceDirtyManager_, curSurfaceNode_);
2291     }
2292 }
2293 
2294 void RSUniRenderVisitor::UpdateVirtualScreenFilterAppRootId(const RSRenderNode::SharedPtr& node)
2295 {
2296     if (node->GetType() == RSRenderNodeType::SURFACE_NODE && virtualScreenFilterAppRootId_ == INVALID_NODEID &&
2297         screenInfo_.filteredAppSet.find(node->GetId()) != screenInfo_.filteredAppSet.end()) {
2298         // limit surface node is to reduce filteredAppSet set times
2299         // don't update if node's parent is in filteredAppSet
2300         virtualScreenFilterAppRootId_ = node->GetId();
2301     } else if (virtualScreenFilterAppRootId_ == node->GetId()) {
2302         // restore virtualScreenFilterAppRootId_ only by itself
2303         virtualScreenFilterAppRootId_ = INVALID_NODEID;
2304     }
2305 }
2306 
2307 void RSUniRenderVisitor::ProcessParallelDisplayRenderNode(RSDisplayRenderNode& node)
2308 {
2309 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_VK)
2310     if (RSSystemProperties::GetGpuApiType() != GpuApiType::VULKAN &&
2311         RSSystemProperties::GetGpuApiType() != GpuApiType::DDGR) {
2312         return;
2313     }
2314     RS_TRACE_NAME("ProcessParallelDisplayRenderNode[" + std::to_string(node.GetId()));
2315     RS_LOGD("RSUniRenderVisitor::ProcessParallelDisplayRenderNode node: %{public}" PRIu64 ", child size:%{public}u",
2316         node.GetId(), node.GetChildrenCount());
2317     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
2318     if (!screenManager) {
2319         RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode ScreenManager is nullptr");
2320         return;
2321     }
2322     screenInfo_ = screenManager->QueryScreenInfo(node.GetScreenId());
2323     isSecurityDisplay_ = node.GetSecurityDisplay();
2324     switch (screenInfo_.state) {
2325         case ScreenState::HDI_OUTPUT_ENABLE:
2326             node.SetCompositeType(node.IsForceSoftComposite() ?
2327                 RSDisplayRenderNode::CompositeType::SOFTWARE_COMPOSITE :
2328                 RSDisplayRenderNode::CompositeType::UNI_RENDER_COMPOSITE);
2329             break;
2330         case ScreenState::PRODUCER_SURFACE_ENABLE:
2331         default:
2332             RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode ScreenState only support HDI_OUTPUT_ENABLE");
2333             return;
2334     }
2335     offsetX_ = node.GetDisplayOffsetX();
2336     offsetY_ = node.GetDisplayOffsetY();
2337     processor_ = RSProcessorFactory::CreateProcessor(node.GetCompositeType());
2338     if (processor_ == nullptr) {
2339         RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode: RSProcessor is null!");
2340         return;
2341     }
2342 
2343     // ParallelDisplayRenderNode cannot have mirror source.
2344     if (!processor_->Init(node, node.GetDisplayOffsetX(), node.GetDisplayOffsetY(),
2345         INVALID_SCREEN_ID, renderEngine_)) {
2346         RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode: processor init failed!");
2347         return;
2348     }
2349     std::shared_ptr<RSBaseRenderNode> nodePtr = node.shared_from_this();
2350     auto displayNodePtr = nodePtr->ReinterpretCastTo<RSDisplayRenderNode>();
2351     if (!displayNodePtr) {
2352         RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode ReinterpretCastTo fail");
2353         return;
2354     }
2355     if (renderFrame_ == nullptr) {
2356         RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode renderFrame_ nullptr");
2357         return;
2358     }
2359     std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
2360     AddOverDrawListener(renderFrame_, overdrawListener);
2361 
2362     if (canvas_ == nullptr) {
2363         RS_LOGE("RSUniRenderVisitor::ProcessParallelDisplayRenderNode: failed to create canvas");
2364         return;
2365     }
2366 #ifndef USE_ROSEN_DRAWING
2367     canvas_->clear(SK_ColorTRANSPARENT);
2368 #else
2369     canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
2370 #endif
2371     RSPropertiesPainter::SetBgAntiAlias(true);
2372 #ifndef USE_ROSEN_DRAWING
2373     int saveCount = canvas_->save();
2374 #else
2375     int saveCount = canvas_->Save();
2376 #endif
2377     canvas_->SetHighContrast(renderEngine_->IsHighContrastEnabled());
2378     auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
2379     if (geoPtr != nullptr) {
2380 #ifndef USE_ROSEN_DRAWING
2381         canvas_->concat(geoPtr->GetMatrix());
2382 #else
2383         canvas_->ConcatMatrix(geoPtr->GetMatrix());
2384 #endif
2385     }
2386     for (auto& childNode : *node.GetChildren()) {
2387         RSParallelRenderManager::Instance()->StartTiming(parallelRenderVisitorIndex_);
2388         childNode->Process(shared_from_this());
2389         RSParallelRenderManager::Instance()->StopTimingAndSetRenderTaskCost(
2390             parallelRenderVisitorIndex_, childNode->GetId(), TaskType::PROCESS_TASK);
2391     }
2392 #ifndef USE_ROSEN_DRAWING
2393     canvas_->restoreToCount(saveCount);
2394 #else
2395     canvas_->RestoreToCount(saveCount);
2396 #endif
2397 
2398     if (overdrawListener != nullptr) {
2399         overdrawListener->Draw();
2400     }
2401     DrawWatermarkIfNeed(node);
2402     RS_TRACE_BEGIN("ProcessParallelDisplayRenderNode:FlushFrame");
2403     renderFrame_->Flush();
2404     RS_TRACE_END();
2405     RS_LOGD("RSUniRenderVisitor::ProcessParallelDisplayRenderNode end");
2406 #endif
2407 }
2408 
2409 #ifndef USE_ROSEN_DRAWING
2410 sk_sp<SkImage> RSUniRenderVisitor::GetCacheImageFromMirrorNode(std::shared_ptr<RSDisplayRenderNode> mirrorNode)
2411 {
2412     sk_sp<SkImage> image = nullptr;
2413     auto cacheImage = mirrorNode->GetCacheImgForCapture();
2414 
2415     bool parallelComposition = RSMainThread::Instance()->GetParallelCompositionEnabled();
2416     if (!parallelComposition) {
2417         return cacheImage;
2418     }
2419 
2420     if (cacheImage != nullptr) {
2421         auto renderContext = renderEngine_->GetRenderContext();
2422         if (renderContext != nullptr) {
2423             auto grContext = renderContext->GetGrContext();
2424             auto imageBackendTexure = cacheImage->getBackendTexture(false);
2425             if (grContext != nullptr && imageBackendTexure.isValid()) {
2426                 image = SkImage::MakeFromTexture(grContext, imageBackendTexure,
2427                     kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
2428             }
2429         }
2430     }
2431     return image;
2432 }
2433 #else
2434 std::shared_ptr<Drawing::Image> RSUniRenderVisitor::GetCacheImageFromMirrorNode(
2435     std::shared_ptr<RSDisplayRenderNode> mirrorNode)
2436 {
2437     auto image = std::make_shared<Drawing::Image>();
2438     auto cacheImage = mirrorNode->GetCacheImgForCapture();
2439 
2440     bool parallelComposition = RSMainThread::Instance()->GetParallelCompositionEnabled();
2441     if (!parallelComposition) {
2442         return cacheImage;
2443     }
2444 
2445     if (cacheImage != nullptr) {
2446         auto renderContext = renderEngine_->GetRenderContext();
2447         if (renderContext != nullptr) {
2448             auto grContext = renderContext->GetDrGPUContext();
2449             auto imageBackendTexure = cacheImage->GetBackendTexture(false, nullptr);
2450             if (grContext != nullptr && imageBackendTexure.IsValid()) {
2451                 Drawing::BitmapFormat bitmapFormat = {Drawing::ColorType::COLORTYPE_RGBA_8888,
2452                     Drawing::AlphaType::ALPHATYPE_PREMUL};
2453                 image->BuildFromTexture(*grContext, imageBackendTexure.GetTextureInfo(),
2454                     Drawing::TextureOrigin::BOTTOM_LEFT, bitmapFormat, nullptr);
2455             }
2456         }
2457     }
2458     return image;
2459 }
2460 #endif
2461 
2462 void RSUniRenderVisitor::ProcessDisplayRenderNode(RSDisplayRenderNode& node)
2463 {
2464     if (mirroredDisplays_.size() == 0) {
2465         node.SetCacheImgForCapture(nullptr);
2466     }
2467 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_VK)
2468     if ((RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
2469         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) && (node.IsParallelDisplayNode())) {
2470         ProcessParallelDisplayRenderNode(node);
2471         return;
2472     }
2473 #endif
2474     RS_TRACE_NAME("ProcessDisplayRenderNode[" + std::to_string(node.GetScreenId()) + "]" +
2475         node.GetDirtyManager()->GetDirtyRegion().ToString().c_str());
2476     RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode node: %{public}" PRIu64 ", child size:%{public}u",
2477         node.GetId(), node.GetChildrenCount());
2478 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_GL)
2479     bool isNeedCalcCost = false;
2480     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
2481         isNeedCalcCost = node.GetSurfaceChangedRects().size() > 0;
2482     }
2483 #endif
2484     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
2485     if (!screenManager) {
2486         RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode ScreenManager is nullptr");
2487         return;
2488     }
2489     constexpr int ROTATION_NUM = 4;
2490     auto screenRotation = node.GetScreenRotation();
2491     if (RSSystemProperties::IsFoldScreenFlag() && node.GetScreenId() == 0) {
2492         screenRotation = static_cast<ScreenRotation>((static_cast<int>(screenRotation) + 1) % ROTATION_NUM);
2493     }
2494     RSPointLightManager::Instance()->SetScreenRotation(screenRotation);
2495     screenInfo_ = screenManager->QueryScreenInfo(node.GetScreenId());
2496     isSecurityDisplay_ = node.GetSecurityDisplay();
2497     auto mirrorNode = node.GetMirrorSource().lock();
2498     switch (screenInfo_.state) {
2499         case ScreenState::PRODUCER_SURFACE_ENABLE:
2500             node.SetCompositeType(mirrorNode ?
2501                 RSDisplayRenderNode::CompositeType::UNI_RENDER_MIRROR_COMPOSITE :
2502                 RSDisplayRenderNode::CompositeType::UNI_RENDER_EXPAND_COMPOSITE);
2503             break;
2504         case ScreenState::HDI_OUTPUT_ENABLE:
2505             node.SetCompositeType(node.IsForceSoftComposite() ?
2506                 RSDisplayRenderNode::CompositeType::SOFTWARE_COMPOSITE :
2507                 RSDisplayRenderNode::CompositeType::UNI_RENDER_COMPOSITE);
2508             break;
2509         default:
2510             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode ScreenState unsupported");
2511             return;
2512     }
2513     offsetX_ = node.GetDisplayOffsetX();
2514     offsetY_ = node.GetDisplayOffsetY();
2515     // in multidisplay scenario, curDisplayDirtyManager_ will be reset in another display's prepare stage
2516     curDisplayDirtyManager_ = node.GetDirtyManager();
2517     processor_ = RSProcessorFactory::CreateProcessor(node.GetCompositeType());
2518     if (processor_ == nullptr) {
2519         RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: RSProcessor is null!");
2520         return;
2521     }
2522 
2523     if (renderEngine_ == nullptr) {
2524         RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: renderEngine is null!");
2525         return;
2526     }
2527     if (!processor_->Init(node, node.GetDisplayOffsetX(), node.GetDisplayOffsetY(),
2528         mirrorNode ? mirrorNode->GetScreenId() : INVALID_SCREEN_ID, renderEngine_)) {
2529         RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: processor init failed!");
2530         return;
2531     }
2532     std::shared_ptr<RSBaseRenderNode> nodePtr = node.shared_from_this();
2533     auto displayNodePtr = nodePtr->ReinterpretCastTo<RSDisplayRenderNode>();
2534     if (!displayNodePtr) {
2535         RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode ReinterpretCastTo fail");
2536         return;
2537     }
2538     if (!node.IsSurfaceCreated()) {
2539         sptr<IBufferConsumerListener> listener = new RSUniRenderListener(displayNodePtr);
2540         if (!node.CreateSurface(listener)) {
2541             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode CreateSurface failed");
2542             return;
2543         }
2544     }
2545 
2546 #if defined(RS_ENABLE_DRIVEN_RENDER)
2547     // [PLANNING]: processing of layers z-order to be implemented
2548     if (drivenInfo_ && !drivenInfo_->prepareInfo.hasInvalidScene) {
2549         drivenInfo_->currDrivenRenderMode = RSDrivenRenderManager::GetInstance().GetUniDrivenRenderMode();
2550         globalZOrder_ = RSDrivenRenderManager::GetInstance().GetUniRenderGlobalZOrder();
2551     }
2552 #endif
2553 
2554     // Wired screen projection
2555     if (node.GetCompositeType() == RSDisplayRenderNode::CompositeType::UNI_RENDER_COMPOSITE && mirrorNode) {
2556         RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode wired screen projection");
2557         auto rsSurface = node.GetRSSurface();
2558         if (!rsSurface) {
2559             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode No RSSurface found");
2560             return;
2561         }
2562         // we should request a framebuffer whose size is equals to the physical screen size.
2563         RS_TRACE_BEGIN("RSUniRender:RequestFrame");
2564         BufferRequestConfig bufferConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo_, true);
2565         RS_OPTIONAL_TRACE_BEGIN("RSUniRender::wait for bufferRequest cond");
2566         if (!RSMainThread::Instance()->WaitUntilDisplayNodeBufferReleased(node)) {
2567             RS_TRACE_NAME("RSUniRenderVisitor no released buffer");
2568         }
2569         RS_OPTIONAL_TRACE_END();
2570 #ifdef NEW_RENDER_CONTEXT
2571         renderFrame_ = renderEngine_->RequestFrame(std::static_pointer_cast<RSRenderSurfaceOhos>(rsSurface),
2572             bufferConfig);
2573 #else
2574         renderFrame_ = renderEngine_->RequestFrame(std::static_pointer_cast<RSSurfaceOhos>(rsSurface), bufferConfig);
2575 #endif
2576         RS_TRACE_END();
2577 
2578         if (!renderFrame_) {
2579             RS_LOGE("RSUniRenderVisitor Request Frame Failed");
2580             return;
2581         }
2582         std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
2583         AddOverDrawListener(renderFrame_, overdrawListener);
2584 
2585         if (!canvas_) {
2586             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: failed to create canvas");
2587             return;
2588         }
2589         if (mirrorNode->GetScreenRotation() == ScreenRotation::ROTATION_90 ||
2590             mirrorNode->GetScreenRotation() == ScreenRotation::ROTATION_270) {
2591             mirrorAutoRotate_ = true;
2592         }
2593 #ifndef USE_ROSEN_DRAWING
2594         canvas_->save();
2595 #else
2596         canvas_->Save();
2597 #endif
2598         ScaleMirrorIfNeed(node);
2599         RotateMirrorCanvasIfNeed(node);
2600         bool forceCPU = false;
2601         auto params = RSUniRenderUtil::CreateBufferDrawParam(*mirrorNode, forceCPU);
2602         params.isMirror = true;
2603         renderEngine_->DrawDisplayNodeWithParams(*canvas_, *mirrorNode, params);
2604 #ifndef USE_ROSEN_DRAWING
2605         canvas_->restore();
2606 #else
2607         canvas_->Restore();
2608 #endif
2609         mirrorAutoRotate_ = false;
2610         renderFrame_->Flush();
2611         processor_->ProcessDisplaySurface(node);
2612         processor_->PostProcess(&node);
2613         return;
2614     }
2615 
2616     if (mirrorNode) {
2617         auto processor = std::static_pointer_cast<RSUniRenderVirtualProcessor>(processor_);
2618         if (mirrorNode->GetSecurityDisplay() != isSecurityDisplay_ && processor &&
2619             (hasCaptureWindow_[mirrorNode->GetScreenId()] || displayHasSecSurface_[mirrorNode->GetScreenId()] ||
2620             displayHasSkipSurface_[mirrorNode->GetScreenId()] || !screenInfo_.filteredAppSet.empty())) {
2621             if (isPc_&& hasCaptureWindow_[mirrorNode->GetScreenId()]) {
2622                 processor->MirrorScenePerf();
2623             }
2624             canvas_ = processor->GetCanvas();
2625             if (canvas_ == nullptr) {
2626                 RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode failed to get canvas.");
2627                 return;
2628             }
2629             if (displayHasSecSurface_[mirrorNode->GetScreenId()]) {
2630 #ifndef USE_ROSEN_DRAWING
2631                 canvas_->clear(SK_ColorBLACK);
2632 #else
2633                 canvas_->Clear(Drawing::Color::COLOR_BLACK);
2634 #endif
2635                 processor_->PostProcess();
2636                 RS_LOGI("RSUniRenderVisitor::ProcessDisplayRenderNode, set canvas to black because of security layer.");
2637                 return;
2638             }
2639 #ifndef USE_ROSEN_DRAWING
2640             sk_sp<SkImage> cacheImageProcessed = GetCacheImageFromMirrorNode(mirrorNode);
2641             bool canvasRotation = screenManager->GetCanvasRotation(node.GetScreenId());
2642             if (cacheImageProcessed && !displayHasSkipSurface_[mirrorNode->GetScreenId()] &&
2643                 !displayHasSecSurface_[mirrorNode->GetScreenId()] && screenInfo_.filteredAppSet.empty()) {
2644                 RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode screen recording optimization is enable");
2645                 ScaleMirrorIfNeed(node, canvasRotation);
2646                 if (canvasRotation && !(RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0)) {
2647                     RotateMirrorCanvasIfNeed(node);
2648                 }
2649                 canvas_->save();
2650                 // If both canvas and skImage have rotated, we need to reset the canvas
2651                 if (resetRotate_) {
2652                     SkMatrix invertMatrix;
2653                     if (processor->GetScreenTransformMatrix().invert(&invertMatrix)) {
2654                         canvas_->concat(invertMatrix);
2655                     }
2656                 }
2657                 SkPaint paint;
2658                 paint.setAntiAlias(true);
2659                 canvas_->drawImage(cacheImageProcessed, 0, 0,
2660                     SkSamplingOptions(SkCubicResampler { 1 / 3.0f, 1 / 3.0f }), &paint); // 1/3.0f is Mitchell sampling
2661                 canvas_->restore();
2662                 bool parallelComposition = RSMainThread::Instance()->GetParallelCompositionEnabled();
2663                 if (!parallelComposition) {
2664                     int saveCount = canvas_->save();
2665                     ProcessChildrenForScreenRecordingOptimization(
2666                         *mirrorNode, mirrorNode->GetRootIdOfCaptureWindow());
2667                     canvas_->restoreToCount(saveCount);
2668                 }
2669                 DrawWatermarkIfNeed(*mirrorNode, true);
2670             } else {
2671                 RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode screen recording optimization is disable");
2672                 mirrorNode->SetCacheImgForCapture(nullptr);
2673                 int saveCount = canvas_->save();
2674                 ScaleMirrorIfNeed(node, canvasRotation);
2675                 if (canvasRotation && !(RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0)) {
2676                     RotateMirrorCanvasIfNeed(node);
2677                 }
2678                 PrepareOffscreenRender(*mirrorNode);
2679                 canvas_->SetDisableFilterCache(true);
2680                 ProcessChildren(*mirrorNode);
2681                 FinishOffscreenRender(true);
2682                 DrawWatermarkIfNeed(*mirrorNode, true);
2683                 canvas_->restoreToCount(saveCount);
2684             }
2685 #else
2686             std::shared_ptr<Drawing::Image> cacheImageProcessed = GetCacheImageFromMirrorNode(mirrorNode);
2687             bool canvasRotation = screenManager->GetCanvasRotation(node.GetScreenId());
2688             if (cacheImageProcessed && !displayHasSkipSurface_[mirrorNode->GetScreenId()] &&
2689                 !displayHasSecSurface_[mirrorNode->GetScreenId()] && screenInfo_.filteredAppSet.empty()) {
2690                 RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode screen recording optimization is enable");
2691                 ScaleMirrorIfNeed(node, canvasRotation);
2692                 if (canvasRotation && !(RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0)) {
2693                     RotateMirrorCanvasIfNeed(node);
2694                 }
2695                 canvas_->Save();
2696                 // If both canvas and skImage have rotated, we need to reset the canvas
2697                 if (resetRotate_) {
2698                     Drawing::Matrix invertMatrix;
2699                     if (processor->GetScreenTransformMatrix().Invert(invertMatrix)) {
2700                         canvas_->ConcatMatrix(invertMatrix);
2701                     }
2702                 }
2703                 Drawing::Brush brush;
2704                 brush.SetAntiAlias(true);
2705                 canvas_->AttachBrush(brush);
2706                 canvas_->DrawImage(*cacheImageProcessed, 0, 0,
2707                     Drawing::SamplingOptions(Drawing::CubicResampler::Mitchell()));
2708                 canvas_->DetachBrush();
2709                 canvas_->Restore();
2710                 bool parallelComposition = RSMainThread::Instance()->GetParallelCompositionEnabled();
2711                 if (!parallelComposition) {
2712                     auto saveCount = canvas_->Save();
2713                     ProcessChildrenForScreenRecordingOptimization(
2714                         *mirrorNode, mirrorNode->GetRootIdOfCaptureWindow());
2715                     canvas_->RestoreToCount(saveCount);
2716                 }
2717                 canvas_->Restore();
2718                 DrawWatermarkIfNeed(*mirrorNode, true);
2719             } else {
2720                 RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode screen recording optimization is disable");
2721                 mirrorNode->SetCacheImgForCapture(nullptr);
2722                 auto saveCount = canvas_->Save();
2723                 ScaleMirrorIfNeed(node, canvasRotation);
2724                 if (canvasRotation && !(RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0)) {
2725                     RotateMirrorCanvasIfNeed(node);
2726                 }
2727                 PrepareOffscreenRender(*mirrorNode);
2728                 canvas_->SetDisableFilterCache(true);
2729                 ProcessChildren(*mirrorNode);
2730                 FinishOffscreenRender(true);
2731                 DrawWatermarkIfNeed(*mirrorNode, true);
2732                 canvas_->RestoreToCount(saveCount);
2733             }
2734 #endif
2735         } else {
2736             mirrorNode->SetOriginScreenRotation(node.GetOriginScreenRotation());
2737             processor_->ProcessDisplaySurface(*mirrorNode);
2738         }
2739     } else if (node.GetCompositeType() == RSDisplayRenderNode::CompositeType::UNI_RENDER_EXPAND_COMPOSITE) {
2740         auto processor = std::static_pointer_cast<RSUniRenderVirtualProcessor>(processor_);
2741         canvas_ = processor->GetCanvas();
2742         if (canvas_ == nullptr) {
2743             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode failed to get canvas.");
2744             return;
2745         }
2746         ProcessChildren(node);
2747         DrawWatermarkIfNeed(node);
2748 #if defined(RS_ENABLE_DRIVEN_RENDER)
2749     } else if (drivenInfo_ && drivenInfo_->currDrivenRenderMode == DrivenUniRenderMode::REUSE_WITH_CLIP_HOLE) {
2750         RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode DrivenUniRenderMode is REUSE_WITH_CLIP_HOLE");
2751         node.SetGlobalZOrder(globalZOrder_);
2752         processor_->ProcessDisplaySurface(node);
2753 #endif
2754     } else {
2755 #ifdef RS_ENABLE_EGLQUERYSURFACE
2756         curDisplayDirtyManager_->SetSurfaceSize(screenInfo_.width, screenInfo_.height);
2757         if (isSurfaceRotationChanged_) {
2758             curDisplayDirtyManager_->MergeSurfaceRect();
2759             isOpDropped_ = false;
2760             isSurfaceRotationChanged_ = false;
2761         }
2762         if (isPartialRenderEnabled_) {
2763             CalcDirtyDisplayRegion(displayNodePtr);
2764             AddContainerDirtyToGlobalDirty(displayNodePtr);
2765             // Aligning displayRenderNode and surfaceRenderNode dirty region before merge dirty filter region
2766             if (isDirtyRegionAlignedEnable_) {
2767                 AlignGlobalAndSurfaceDirtyRegions(displayNodePtr);
2768             }
2769             CalcDirtyFilterRegion(displayNodePtr);
2770             displayNodePtr->ClearCurrentSurfacePos();
2771         } else {
2772             // if isPartialRenderEnabled_ is disabled for some reason (i.e. screen rotation),
2773             // we should keep a fullscreen dirtyregion history to avoid dirtyregion losses.
2774             // isPartialRenderEnabled_ should not be disabled after current position.
2775             curDisplayDirtyManager_->MergeSurfaceRect();
2776             curDisplayDirtyManager_->UpdateDirty(isDirtyRegionAlignedEnable_);
2777             UpdateHardwareNodeStatusBasedOnFilterRegion(node);
2778         }
2779         if (isOpDropped_ && dirtySurfaceNodeMap_.empty()
2780             && !curDisplayDirtyManager_->IsCurrentFrameDirty()) {
2781             RS_LOGD("DisplayNode skip");
2782             RS_TRACE_NAME("DisplayNode skip");
2783 #ifdef OHOS_PLATFORM
2784             RSJankStats::GetInstance().SetSkipDisplayNode();
2785 #endif
2786             resetRotate_ = CheckIfNeedResetRotate();
2787             if (!IsHardwareComposerEnabled()) {
2788                 return;
2789             }
2790             if (!RSMainThread::Instance()->WaitHardwareThreadTaskExcute()) {
2791                 RS_LOGW("RSUniRenderVisitor::ProcessDisplayRenderNode: hardwareThread task has too many to excute");
2792             }
2793             if (!RSMainThread::Instance()->CheckIsHardwareEnabledBufferUpdated() && !forceUpdateFlag_) {
2794                 for (auto& surfaceNode: hardwareEnabledNodes_) {
2795                     if (!surfaceNode->IsHardwareForcedDisabled()) {
2796                         surfaceNode->MarkCurrentFrameHardwareEnabled();
2797                     }
2798                 }
2799                 RS_TRACE_NAME("DisplayNodeSkip skip commit");
2800                 return;
2801             }
2802             bool needCreateDisplayNodeLayer = false;
2803             for (auto& surfaceNode: hardwareEnabledNodes_) {
2804                 if (!surfaceNode->IsHardwareForcedDisabled()) {
2805                     needCreateDisplayNodeLayer = true;
2806                     processor_->ProcessSurface(*surfaceNode);
2807                 }
2808             }
2809             if (needCreateDisplayNodeLayer || forceUpdateFlag_) {
2810                 processor_->ProcessDisplaySurface(node);
2811                 DoScreenRcdTask(processor_, rcdInfo_, screenInfo_);
2812                 processor_->PostProcess(&node);
2813             }
2814             return;
2815         }
2816 #endif
2817 
2818 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_OLD_VK)
2819         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
2820             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
2821             if (isParallel_ &&!isPartialRenderEnabled_) {
2822                 auto parallelRenderManager = RSParallelRenderManager::Instance();
2823                 vulkan::VulkanWindow::InitializeVulkan(
2824                     parallelRenderManager->GetParallelThreadNumber());
2825                 RS_OPTIONAL_TRACE_BEGIN("RSUniRender::VK::WaitFence");
2826                 vulkan::VulkanWindow::WaitForSharedFence();
2827                 vulkan::VulkanWindow::ResetSharedFence();
2828                 RS_OPTIONAL_TRACE_END();
2829                 parallelRenderManager->CopyVisitorAndPackTask(*this, node);
2830                 parallelRenderManager->InitDisplayNodeAndRequestFrame(renderEngine_, screenInfo_);
2831                 parallelRenderManager->LoadBalanceAndNotify(TaskType::PROCESS_TASK);
2832                 parallelRenderManager->WaitProcessEnd();
2833                 parallelRenderManager->CommitSurfaceNum(node.GetChildrenCount());
2834                 vulkan::VulkanWindow::PresentAll();
2835 
2836                 RS_OPTIONAL_TRACE_BEGIN("RSUniRender:WaitUtilUniRenderFinished");
2837                 RSMainThread::Instance()->WaitUtilUniRenderFinished();
2838                 RS_OPTIONAL_TRACE_END();
2839 
2840                 parallelRenderManager->ProcessParallelDisplaySurface(*this);
2841                 processor_->PostProcess();
2842 
2843                 parallelRenderManager->ReleaseBuffer();
2844 
2845                 isParallel_ = false;
2846                 return;
2847             }
2848         }
2849 #endif
2850 
2851         auto rsSurface = node.GetRSSurface();
2852         if (rsSurface == nullptr) {
2853             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode No RSSurface found");
2854             return;
2855         }
2856         // we should request a framebuffer whose size is equals to the physical screen size.
2857         RS_TRACE_BEGIN("RSUniRender:RequestFrame");
2858         BufferRequestConfig bufferConfig = RSBaseRenderUtil::GetFrameBufferRequestConfig(screenInfo_, true,
2859             newColorSpace_, newPixelFormat_);
2860         RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode, colorspace is %{public}d, pixelformat is %{public}d in "\
2861                 "RequestFrame.", newColorSpace_, newPixelFormat_);
2862         node.SetFingerprint(hasFingerprint_);
2863         RS_OPTIONAL_TRACE_BEGIN("RSUniRender::wait for bufferRequest cond");
2864         if (!RSMainThread::Instance()->WaitUntilDisplayNodeBufferReleased(node)) {
2865             RS_TRACE_NAME("RSUniRenderVisitor no released buffer");
2866         }
2867         RS_OPTIONAL_TRACE_END();
2868 #ifdef NEW_RENDER_CONTEXT
2869         renderFrame_ = renderEngine_->RequestFrame(std::static_pointer_cast<RSRenderSurfaceOhos>(rsSurface),
2870             bufferConfig);
2871 #else
2872         renderFrame_ = renderEngine_->RequestFrame(std::static_pointer_cast<RSSurfaceOhos>(rsSurface), bufferConfig);
2873 #endif
2874         RS_TRACE_END();
2875 
2876         if (renderFrame_ == nullptr) {
2877             RS_LOGE("RSUniRenderVisitor Request Frame Failed");
2878             return;
2879         }
2880         std::shared_ptr<RSCanvasListener> overdrawListener = nullptr;
2881         AddOverDrawListener(renderFrame_, overdrawListener);
2882 
2883         if (canvas_ == nullptr) {
2884             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode: failed to create canvas");
2885             return;
2886         }
2887 
2888 #ifdef ENABLE_RECORDING_DCL
2889         tryCapture(node.GetRenderProperties().GetBoundsWidth(), node.GetRenderProperties().GetBoundsHeight());
2890 #endif
2891 
2892         int saveLayerCnt = 0;
2893 #ifndef USE_ROSEN_DRAWING
2894         SkRegion region;
2895 #else
2896         Drawing::Region region;
2897 #endif
2898         Occlusion::Region dirtyRegionTest;
2899         std::vector<RectI> rects;
2900         bool clipPath = false;
2901 #ifdef RS_ENABLE_VK
2902         int saveCountBeforeClip = 0;
2903         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
2904             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
2905 #ifndef USE_ROSEN_DRAWING
2906             saveCountBeforeClip = canvas_->save();
2907 #else
2908             saveCountBeforeClip = canvas_->Save();
2909 #endif
2910         }
2911 #endif
2912 #ifdef RS_ENABLE_EGLQUERYSURFACE
2913         // Get displayNode buffer age in order to merge visible dirty region for displayNode.
2914         // And then set egl damage region to improve uni_render efficiency.
2915         if (isPartialRenderEnabled_) {
2916             // Early history buffer Merging will have impact on Overdraw display, so we need to
2917             // set the full screen dirty to avoid this impact.
2918             if (RSOverdrawController::GetInstance().IsEnabled()) {
2919                 node.GetDirtyManager()->ResetDirtyAsSurfaceSize();
2920             }
2921             RS_OPTIONAL_TRACE_BEGIN("RSUniRender::GetBufferAge");
2922             int bufferAge = renderFrame_->GetBufferAge();
2923             RS_OPTIONAL_TRACE_END();
2924             RSUniRenderUtil::MergeDirtyHistory(displayNodePtr, bufferAge, isDirtyRegionAlignedEnable_);
2925             Occlusion::Region dirtyRegion = RSUniRenderUtil::MergeVisibleDirtyRegion(
2926                 displayNodePtr, RSMainThread::Instance()->GetDrawStatusVec(), isDirtyRegionAlignedEnable_);
2927             dirtyRegionTest = dirtyRegion;
2928             if (isDirtyRegionAlignedEnable_) {
2929                 SetSurfaceGlobalAlignedDirtyRegion(displayNodePtr, dirtyRegion);
2930             } else {
2931                 SetSurfaceGlobalDirtyRegion(displayNodePtr);
2932             }
2933             rects = GetDirtyRects(dirtyRegion);
2934             RectI rect = node.GetDirtyManager()->GetDirtyRegionFlipWithinSurface();
2935             if (!rect.IsEmpty()) {
2936                 rects.emplace_back(rect);
2937             }
2938             if (!isDirtyRegionAlignedEnable_) {
2939                 for (auto& r : rects) {
2940                     int32_t topAfterFlip = 0;
2941 #ifdef RS_ENABLE_VK
2942                     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
2943                         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
2944                         topAfterFlip = r.top_;
2945                     } else {
2946                         topAfterFlip = static_cast<int32_t>(screenInfo_.GetRotatedHeight()) - r.GetBottom();
2947                     }
2948 #else
2949                     topAfterFlip = static_cast<int32_t>(screenInfo_.GetRotatedHeight()) - r.GetBottom();
2950 #endif
2951 #ifndef USE_ROSEN_DRAWING
2952                     region.op(SkIRect::MakeXYWH(r.left_, topAfterFlip, r.width_, r.height_), SkRegion::kUnion_Op);
2953 #else
2954                     Drawing::Region tmpRegion;
2955                     tmpRegion.SetRect(Drawing::RectI(r.left_, topAfterFlip,
2956                         r.left_ + r.width_, topAfterFlip + r.height_));
2957                     region.Op(tmpRegion, Drawing::RegionOp::UNION);
2958 #endif
2959                 }
2960             }
2961             // SetDamageRegion and opDrop will be disabled for dirty region DFX visualization
2962             if (!isRegionDebugEnabled_) {
2963                 renderFrame_->SetDamageRegion(rects);
2964             }
2965         }
2966         if (isOpDropped_ && !isDirtyRegionAlignedEnable_) {
2967 #ifndef USE_ROSEN_DRAWING
2968             if (region.isEmpty()) {
2969                 // [planning] Remove this after frame buffer can cancel
2970                 canvas_->clipRect(SkRect::MakeEmpty());
2971             } else if (region.isRect()) {
2972                 canvas_->clipRegion(region);
2973                 canvas_->clear(SK_ColorTRANSPARENT);
2974             } else {
2975                 RS_TRACE_NAME("RSUniRenderVisitor: clipPath");
2976                 clipPath = true;
2977 #ifdef RS_ENABLE_VK
2978                 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
2979                     RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
2980                     canvas_->clipRegion(region);
2981                 } else {
2982                     SkPath dirtyPath;
2983                     region.getBoundaryPath(&dirtyPath);
2984                     canvas_->clipPath(dirtyPath, true);
2985                 }
2986 #else
2987                 SkPath dirtyPath;
2988                 region.getBoundaryPath(&dirtyPath);
2989                 canvas_->clipPath(dirtyPath, true);
2990 #endif
2991             }
2992 #else
2993             if (region.IsEmpty()) {
2994                 // [planning] Remove this after frame buffer can cancel
2995                 canvas_->ClipRect(Drawing::Rect());
2996             } else if (region.IsRect()) {
2997                 canvas_->ClipRegion(region);
2998                 canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
2999             } else {
3000                 RS_TRACE_NAME("RSUniRenderVisitor: clipPath");
3001                 clipPath = true;
3002 #ifdef RS_ENABLE_VK
3003                 if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
3004                     RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
3005                     canvas_->ClipRegion(region);
3006                 } else {
3007                     Drawing::Path dirtyPath;
3008                     region.GetBoundaryPath(&dirtyPath);
3009                     canvas_->ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true);
3010                 }
3011 #else
3012                 Drawing::Path dirtyPath;
3013                 region.GetBoundaryPath(&dirtyPath);
3014                 canvas_->ClipPath(dirtyPath, Drawing::ClipOp::INTERSECT, true);
3015 #endif
3016             }
3017 #endif
3018         } else {
3019 #ifndef USE_ROSEN_DRAWING
3020             canvas_->clear(SK_ColorTRANSPARENT);
3021 #else
3022             canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
3023 #endif
3024         }
3025 #endif
3026 
3027         RSPropertiesPainter::SetBgAntiAlias(true);
3028         if (!isParallel_ || isUIFirst_) {
3029 #ifndef USE_ROSEN_DRAWING
3030             int saveCount = canvas_->save();
3031             canvas_->SetHighContrast(renderEngine_->IsHighContrastEnabled());
3032 
3033             bool displayNodeRotationChanged = node.IsRotationChanged();
3034             // enable cache if screen rotation
3035             canvas_->SetCacheType((isScreenRotationAnimating_ || displayNodeRotationChanged)
3036                 ? RSPaintFilterCanvas::CacheType::ENABLED
3037                 : RSPaintFilterCanvas::CacheType::DISABLED);
3038             bool needOffscreen = clipPath || displayNodeRotationChanged;
3039 
3040             if (needOffscreen) {
3041                 ClearTransparentBeforeSaveLayer(); // clear transparent before concat display node's matrix
3042             }
3043             auto geoPtr = node.GetRenderProperties().GetBoundsGeometry();
3044             if (geoPtr != nullptr) {
3045                 canvas_->concat(geoPtr->GetMatrix());
3046             }
3047             if (needOffscreen) {
3048                 // we are doing rotation animation, try offscreen render if capable
3049                 displayNodeMatrix_ = canvas_->getTotalMatrix();
3050                 PrepareOffscreenRender(node);
3051                 ProcessChildren(node);
3052                 FinishOffscreenRender();
3053             } else {
3054                 // render directly
3055                 ProcessChildren(node);
3056             }
3057             SwitchColorFilterDrawing(saveCount);
3058             canvas_->restoreToCount(saveCount);
3059 #else
3060             int saveCount = canvas_->Save();
3061             canvas_->SetHighContrast(renderEngine_->IsHighContrastEnabled());
3062 
3063             bool displayNodeRotationChanged = node.IsRotationChanged();
3064             // enable cache if screen rotation
3065             canvas_->SetCacheType((isScreenRotationAnimating_ || displayNodeRotationChanged)
3066                 ? RSPaintFilterCanvas::CacheType::ENABLED
3067                 : RSPaintFilterCanvas::CacheType::DISABLED);
3068             bool needOffscreen = clipPath || displayNodeRotationChanged;
3069 
3070             if (needOffscreen) {
3071                 ClearTransparentBeforeSaveLayer(); // clear transparent before concat display node's matrix
3072             }
3073             auto geoPtr = node.GetRenderProperties().GetBoundsGeometry();
3074             if (geoPtr != nullptr) {
3075                 canvas_->ConcatMatrix(geoPtr->GetMatrix());
3076             }
3077             if (needOffscreen) {
3078                 // we are doing rotation animation, try offscreen render if capable
3079                 displayNodeMatrix_ = canvas_->GetTotalMatrix();
3080                 PrepareOffscreenRender(node);
3081                 ProcessChildren(node);
3082                 FinishOffscreenRender();
3083             } else {
3084                 // render directly
3085                 ProcessChildren(node);
3086             }
3087             SwitchColorFilterDrawing(saveCount);
3088             canvas_->RestoreToCount(saveCount);
3089 #endif
3090         }
3091 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_GL)
3092         if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
3093             if ((isParallel_ && !isUIFirst_ && ((rects.size() > 0) || !isPartialRenderEnabled_)) && isCalcCostEnable_) {
3094                 auto parallelRenderManager = RSParallelRenderManager::Instance();
3095                 parallelRenderManager->CopyCalcCostVisitorAndPackTask(*this, node, isNeedCalcCost,
3096                     doAnimate_, isOpDropped_);
3097                 if (parallelRenderManager->IsNeedCalcCost()) {
3098                     parallelRenderManager->LoadBalanceAndNotify(TaskType::CALC_COST_TASK);
3099                     parallelRenderManager->WaitCalcCostEnd();
3100                     parallelRenderManager->UpdateNodeCost(node);
3101                 }
3102             }
3103             if (isParallel_ && !isUIFirst_ && ((rects.size() > 0) || !isPartialRenderEnabled_)) {
3104                 ClearTransparentBeforeSaveLayer();
3105                 auto parallelRenderManager = RSParallelRenderManager::Instance();
3106                 parallelRenderManager->SetFrameSize(screenInfo_.width, screenInfo_.height);
3107                 parallelRenderManager->CopyVisitorAndPackTask(*this, node);
3108                 parallelRenderManager->LoadBalanceAndNotify(TaskType::PROCESS_TASK);
3109                 parallelRenderManager->MergeRenderResult(*canvas_);
3110                 parallelRenderManager->CommitSurfaceNum(node.GetChildrenCount());
3111                 parallelRenderManager->ProcessFilterSurfaceRenderNode();
3112             }
3113         }
3114 #endif
3115         if (saveLayerCnt > 0) {
3116 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
3117 #ifdef NEW_RENDER_CONTEXT
3118             RSTagTracker tagTracker(
3119                 renderEngine_->GetDrawingContext()->GetDrawingContext(),
3120                 RSTagTracker::TAGTYPE::TAG_RESTORELAYER_DRAW_NODE);
3121 #else
3122 #ifndef USE_ROSEN_DRAWING
3123             RSTagTracker tagTracker(
3124                 renderEngine_->GetRenderContext()->GetGrContext(), RSTagTracker::TAGTYPE::TAG_RESTORELAYER_DRAW_NODE);
3125             RS_TRACE_NAME("RSUniRender:RestoreLayer");
3126             canvas_->restoreToCount(saveLayerCnt);
3127 #else
3128             RSTagTracker tagTracker(renderEngine_->GetRenderContext()->GetDrGPUContext(),
3129                 RSTagTracker::TAGTYPE::TAG_RESTORELAYER_DRAW_NODE);
3130             RS_TRACE_NAME("RSUniRender:RestoreLayer");
3131             canvas_->RestoreToCount(saveLayerCnt);
3132 #endif
3133 #endif
3134 #endif
3135         }
3136         if (UNLIKELY(!unpairedTransitionNodes_.empty())) {
3137             RS_LOGE("RSUniRenderVisitor::ProcessDisplayRenderNode  unpairedTransitionNodes_ is not empty.");
3138             ProcessUnpairedSharedTransitionNode();
3139         }
3140         if (overdrawListener != nullptr) {
3141             overdrawListener->Draw();
3142         }
3143         DrawWatermarkIfNeed(node);
3144         // the following code makes DirtyRegion visible, enable this method by turning on the dirtyregiondebug property
3145         if (isPartialRenderEnabled_) {
3146             if (isDirtyRegionDfxEnabled_) {
3147                 DrawAllSurfaceDirtyRegionForDFX(node, dirtyRegionTest);
3148             }
3149             if (isTargetDirtyRegionDfxEnabled_) {
3150                 DrawTargetSurfaceDirtyRegionForDFX(node);
3151             }
3152             if (isDisplayDirtyDfxEnabled_) {
3153                 DrawDirtyRegionForDFX(node.GetDirtyManager()->GetMergedDirtyRegions());
3154             }
3155         }
3156 
3157         if (isOpaqueRegionDfxEnabled_) {
3158             DrawAllSurfaceOpaqueRegionForDFX(node);
3159         }
3160         if (isVisibleRegionDfxEnabled_) {
3161             DrawTargetSurfaceVisibleRegionForDFX(node);
3162         }
3163 
3164         if (isDrawingCacheEnabled_ && RSSystemParameters::GetDrawingCacheEnabledDfx()) {
3165             DrawCacheRegionForDFX(cacheRenderNodeMapRects_);
3166         }
3167 
3168         if (RSSystemParameters::GetDrawingEffectRegionEnabledDfx()) {
3169             DrawEffectRenderNodeForDFX();
3170         }
3171 
3172         if (RSRealtimeRefreshRateManager::Instance().GetShowRefreshRateEnabled()) {
3173             RS_TRACE_BEGIN("RSUniRender::DrawCurrentRefreshRate");
3174             uint32_t currentRefreshRate =
3175                 OHOS::Rosen::HgmCore::Instance().GetScreenCurrentRefreshRate(node.GetScreenId());
3176             uint32_t realtimeRefreshRate = RSRealtimeRefreshRateManager::Instance().GetRealtimeRefreshRate();
3177             if (realtimeRefreshRate > currentRefreshRate) {
3178                 realtimeRefreshRate = currentRefreshRate;
3179             }
3180             DrawCurrentRefreshRate(currentRefreshRate, realtimeRefreshRate);
3181             RS_TRACE_END();
3182         }
3183 
3184 #ifdef ENABLE_RECORDING_DCL
3185         endCapture();
3186 #endif
3187         if ((screenInfo_.state == ScreenState::HDI_OUTPUT_ENABLE) &&
3188             RSSingleton<RoundCornerDisplay>::GetInstance().GetRcdEnable() &&
3189             (!RSSingleton<RoundCornerDisplay>::GetInstance().IsSupportHardware())) {
3190             RSSingleton<RoundCornerDisplay>::GetInstance().DrawRoundCorner(canvas_.get());
3191         }
3192         auto mainThread = RSMainThread::Instance();
3193         if (!mainThread->GetClearMemoryFinished()) {
3194             mainThread->RemoveTask(CLEAR_GPU_CACHE);
3195         }
3196 #ifdef RS_ENABLE_VK
3197         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
3198             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
3199 #ifndef USE_ROSEN_DRAWING
3200             canvas_->restoreToCount(saveCountBeforeClip);
3201 #else
3202             canvas_->RestoreToCount(saveCountBeforeClip);
3203 #endif
3204         }
3205 #endif
3206         RS_TRACE_BEGIN("RSUniRender:FlushFrame");
3207         renderFrame_->Flush();
3208         RS_TRACE_END();
3209         RS_OPTIONAL_TRACE_BEGIN("RSUniRender:WaitUtilUniRenderFinished");
3210         mainThread->WaitUtilUniRenderFinished();
3211         RS_OPTIONAL_TRACE_END();
3212         if (cacheImgForCapture_ != nullptr) {
3213             node.SetCacheImgForCapture(cacheImgForCapture_);
3214         }
3215         UpdateHardwareEnabledInfoBeforeCreateLayer();
3216         AssignGlobalZOrderAndCreateLayer(appWindowNodesInZOrder_);
3217         node.SetGlobalZOrder(globalZOrder_++);
3218         processor_->ProcessDisplaySurface(node);
3219         auto& surfaceHandler = static_cast<RSSurfaceHandler&>(node);
3220         auto& fence = surfaceHandler.GetAcquireFence();
3221         auto subThreadManager = RSSubThreadManager::Instance();
3222         subThreadManager->SetFenceSubThread(fence);
3223         AssignGlobalZOrderAndCreateLayer(hardwareEnabledTopNodes_);
3224     }
3225 
3226 #if defined(RS_ENABLE_DRIVEN_RENDER)
3227     if (drivenInfo_ && !drivenInfo_->prepareInfo.hasInvalidScene) {
3228         RS_TRACE_NAME("RSUniRender:DrivenRenderProcess");
3229         // process driven render tree
3230         drivenInfo_->processInfo = { processor_, newColorSpace_, node.GetGlobalZOrder() };
3231         RSDrivenRenderManager::GetInstance().DoProcessRenderTask(drivenInfo_->processInfo);
3232     }
3233 #endif
3234 
3235     DoScreenRcdTask(processor_, rcdInfo_, screenInfo_);
3236 
3237     if (!RSMainThread::Instance()->WaitHardwareThreadTaskExcute()) {
3238         RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode: hardwareThread task has too many to excute");
3239     }
3240     processor_->PostProcess(&node);
3241     {
3242         std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
3243         EraseIf(groupedTransitionNodes, [](auto& iter) -> bool {
3244             auto& [id, pair] = iter;
3245             if (pair.second.empty()) {
3246                 return true;
3247             }
3248             const auto& nodeMap = RSMainThread::Instance()->GetContext().GetNodeMap();
3249             auto node = nodeMap.GetRenderNode<RSRenderNode>(iter.first);
3250             return node ? (!node->IsOnTheTree()) : true;
3251         });
3252     }
3253     auto mainThread = RSMainThread::Instance();
3254     if (!mainThread->GetClearMemoryFinished()) {
3255         mainThread->ClearMemoryCache(mainThread->GetClearMoment(), mainThread->GetClearMemDeeply());
3256     }
3257     RS_LOGD("RSUniRenderVisitor::ProcessDisplayRenderNode end");
3258 #ifdef RS_ENABLE_VK
3259         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN) {
3260 #ifdef USE_ROSEN_DRAWING
3261             renderEngine_->GetRenderContext()->GetDrGPUContext()->StoreVkPipelineCacheData();
3262 #endif
3263         }
3264 #endif
3265 }
3266 
3267 void RSUniRenderVisitor::DrawSurfaceLayer(const std::shared_ptr<RSDisplayRenderNode>& displayNode,
3268     const std::list<std::shared_ptr<RSSurfaceRenderNode>>& subThreadNodes) const
3269 {
3270     auto subThreadManager = RSSubThreadManager::Instance();
3271     if (RSSingleton<RoundCornerDisplay>::GetInstance().GetRcdEnable()) {
3272         subThreadManager->StartRCDThread(renderEngine_->GetRenderContext().get());
3273     }
3274 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
3275     subThreadManager->StartFilterThread(renderEngine_->GetRenderContext().get());
3276     subThreadManager->StartColorPickerThread(renderEngine_->GetRenderContext().get());
3277     subThreadManager->SubmitSubThreadTask(displayNode, subThreadNodes);
3278 #endif
3279 }
3280 
3281 #ifndef USE_ROSEN_DRAWING
3282 void RSUniRenderVisitor::SwitchColorFilterDrawing(int currentSaveCount)
3283 {
3284     ColorFilterMode colorFilterMode = renderEngine_->GetColorFilterMode();
3285     if (colorFilterMode >= ColorFilterMode::INVERT_COLOR_ENABLE_MODE &&
3286         colorFilterMode <= ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE) {
3287         RS_LOGD("RsDebug RSBaseRenderEngine::SetColorFilterModeToPaint mode:%{public}d",
3288             static_cast<int32_t>(colorFilterMode));
3289         SkPaint paint;
3290         RSBaseRenderUtil::SetColorFilterModeToPaint(colorFilterMode, paint);
3291 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
3292 #ifdef NEW_RENDER_CONTEXT
3293         RSTagTracker tagTracker(
3294             renderEngine_->GetDrawingContext()->GetDrawingContext(),
3295             RSTagTracker::TAG_SAVELAYER_COLOR_FILTER);
3296 #else
3297         RSTagTracker tagTracker(
3298             renderEngine_->GetRenderContext()->GetGrContext(),
3299             RSTagTracker::TAG_SAVELAYER_COLOR_FILTER);
3300 #endif
3301 #endif
3302         SkCanvas::SaveLayerRec rec;
3303         rec.fSaveLayerFlags = SkCanvas::kInitWithPrevious_SaveLayerFlag;
3304         rec.fPaint = &paint;
3305         canvas_->saveLayer(rec);
3306         canvas_->restoreToCount(currentSaveCount);
3307     }
3308 }
3309 #else
3310 void RSUniRenderVisitor::SwitchColorFilterDrawing(int currentSaveCount)
3311 {
3312     ColorFilterMode colorFilterMode = renderEngine_->GetColorFilterMode();
3313     if (colorFilterMode >= ColorFilterMode::INVERT_COLOR_ENABLE_MODE &&
3314         colorFilterMode <= ColorFilterMode::INVERT_DALTONIZATION_TRITANOMALY_MODE) {
3315         RS_LOGD("RsDebug RSBaseRenderEngine::SetColorFilterModeToPaint mode:%{public}d",
3316             static_cast<int32_t>(colorFilterMode));
3317         Drawing::Brush brush;
3318         RSBaseRenderUtil::SetColorFilterModeToPaint(colorFilterMode, brush);
3319 #if defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)
3320 #ifdef NEW_RENDER_CONTEXT
3321         RSTagTracker tagTracker(
3322             renderEngine_->GetDrawingContext()->GetDrawingContext(),
3323             RSTagTracker::TAG_SAVELAYER_COLOR_FILTER);
3324 #else
3325         RSTagTracker tagTracker(
3326             renderEngine_->GetRenderContext()->GetDrGPUContext(),
3327             RSTagTracker::TAG_SAVELAYER_COLOR_FILTER);
3328 #endif
3329 #endif
3330         Drawing::SaveLayerOps slr(nullptr, &brush, Drawing::SaveLayerOps::INIT_WITH_PREVIOUS);
3331         canvas_->SaveLayer(slr);
3332         canvas_->RestoreToCount(currentSaveCount);
3333     }
3334 }
3335 #endif
3336 
3337 void RSUniRenderVisitor::UpdateHardwareEnabledInfoBeforeCreateLayer()
3338 {
3339     if (!IsHardwareComposerEnabled()) {
3340         return;
3341     }
3342     if (hardwareEnabledNodes_.empty()) {
3343         return;
3344     }
3345     if (isParallel_ && !isUIFirst_) {
3346 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined(RS_ENABLE_GL)
3347         if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
3348             std::vector<std::shared_ptr<RSSurfaceRenderNode>>().swap(appWindowNodesInZOrder_);
3349             auto subThreadNum = RSParallelRenderManager::Instance()->GetParallelThreadNumber();
3350             auto appWindowNodesMap = RSParallelRenderManager::Instance()->GetAppWindowNodes();
3351             std::vector<std::shared_ptr<RSSurfaceRenderNode>> appWindowNodes;
3352             for (uint32_t i = 0; i < subThreadNum; i++) {
3353                 appWindowNodes = appWindowNodesMap[i];
3354                 appWindowNodesInZOrder_.insert(appWindowNodesInZOrder_.end(),
3355                     appWindowNodes.begin(), appWindowNodes.end());
3356             }
3357         }
3358 #endif
3359     }
3360     globalZOrder_ = 0.0f;
3361 }
3362 
3363 void RSUniRenderVisitor::AssignGlobalZOrderAndCreateLayer(
3364     std::vector<std::shared_ptr<RSSurfaceRenderNode>>& nodesInZOrder)
3365 {
3366     if (!IsHardwareComposerEnabled()) {
3367         return;
3368     }
3369     if (hardwareEnabledNodes_.empty()) {
3370         return;
3371     }
3372     for (auto& appWindowNode : nodesInZOrder) {
3373         // first, sort app window node's child surfaceView by local zOrder
3374         auto childHardwareEnabledNodes = appWindowNode->GetChildHardwareEnabledNodes();
3375         for (auto iter = childHardwareEnabledNodes.begin(); iter != childHardwareEnabledNodes.end();) {
3376             auto childNode = iter->lock();
3377             if (!childNode || !childNode->IsOnTheTree()) {
3378                 iter = childHardwareEnabledNodes.erase(iter);
3379                 continue;
3380             }
3381             if (childNode->GetBuffer() != nullptr && !childNode->IsHardwareForcedDisabled()) {
3382                 // SetGlobalZOrder here to ensure zOrder committed to composer is continuous
3383                 childNode->SetGlobalZOrder(globalZOrder_++);
3384                 RS_LOGD("createLayer: %{public}" PRIu64 "", childNode->GetId());
3385                 processor_->ProcessSurface(*childNode);
3386             }
3387             ++iter;
3388         }
3389     }
3390 }
3391 
3392 void RSUniRenderVisitor::AddOverDrawListener(std::unique_ptr<RSRenderFrame>& renderFrame,
3393     std::shared_ptr<RSCanvasListener>& overdrawListener)
3394 {
3395 #if defined(NEW_RENDER_CONTEXT)
3396     if (renderFrame == nullptr) {
3397         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: renderFrame is nullptr");
3398         return;
3399     }
3400     auto renderSurface = renderFrame->GetSurface();
3401     if (renderSurface == nullptr) {
3402         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: renderSurface is nullptr");
3403         return;
3404     }
3405 #if !defined(USE_ROSEN_DRAWING)
3406     RS_OPTIONAL_TRACE_BEGIN("RSUniRender::GetSurface");
3407     auto skSurface = renderSurface->GetSurface();
3408     RS_OPTIONAL_TRACE_END();
3409     if (skSurface == nullptr) {
3410         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: skSurface is null");
3411         return;
3412     }
3413     if (skSurface->getCanvas() == nullptr) {
3414         ROSEN_LOGE("skSurface.getCanvas is null.");
3415         return;
3416     }
3417 #else
3418     RS_OPTIONAL_TRACE_BEGIN("RSUniRender::GetSurface");
3419     auto drSurface = renderSurface->GetSurface();
3420     RS_OPTIONAL_TRACE_END();
3421     if (drSurface == nullptr) {
3422         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: drSurface is null");
3423         return;
3424     }
3425     if (drSurface->GetCanvas() == nullptr) {
3426         ROSEN_LOGE("drSurface.getCanvas is null.");
3427         return;
3428     }
3429 #endif
3430 #else
3431     if (renderFrame->GetFrame() == nullptr) {
3432         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: RSSurfaceFrame is nullptr");
3433         return;
3434     }
3435 #if !defined(USE_ROSEN_DRAWING)
3436     RS_TRACE_BEGIN("RSUniRender::GetSurface");
3437     auto skSurface = renderFrame->GetFrame()->GetSurface();
3438     RS_TRACE_END();
3439     if (skSurface == nullptr) {
3440         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: skSurface is null");
3441         return;
3442     }
3443     if (skSurface->getCanvas() == nullptr) {
3444         ROSEN_LOGE("skSurface.getCanvas is null.");
3445         return;
3446     }
3447 #else
3448     RS_OPTIONAL_TRACE_BEGIN("RSUniRender::GetSurface");
3449     auto drSurface = renderFrame->GetFrame()->GetSurface();
3450     RS_OPTIONAL_TRACE_END();
3451     if (drSurface == nullptr) {
3452         RS_LOGE("RSUniRenderVisitor::AddOverDrawListener: drSurface is null");
3453         return;
3454     }
3455     if (drSurface->GetCanvas() == nullptr) {
3456         ROSEN_LOGE("drSurface.getCanvas is null.");
3457         return;
3458     }
3459 #endif
3460 #endif
3461     // if listenedCanvas is nullptr, that means disabled or listen failed
3462     std::shared_ptr<RSListenedCanvas> listenedCanvas = nullptr;
3463 
3464     if (RSOverdrawController::GetInstance().IsEnabled()) {
3465         auto &oc = RSOverdrawController::GetInstance();
3466 #ifndef USE_ROSEN_DRAWING
3467         listenedCanvas = std::make_shared<RSListenedCanvas>(skSurface.get());
3468 #else
3469         listenedCanvas = std::make_shared<RSListenedCanvas>(*drSurface.get());
3470 #endif
3471         overdrawListener = oc.CreateListener<RSGPUOverdrawCanvasListener>(listenedCanvas.get());
3472         if (overdrawListener == nullptr) {
3473             overdrawListener = oc.CreateListener<RSCPUOverdrawCanvasListener>(listenedCanvas.get());
3474         }
3475 
3476         if (overdrawListener != nullptr) {
3477             listenedCanvas->SetListener(overdrawListener);
3478         } else {
3479             // create listener failed
3480             listenedCanvas = nullptr;
3481         }
3482     }
3483 
3484     if (listenedCanvas != nullptr) {
3485         canvas_ = listenedCanvas;
3486     } else {
3487 #ifndef USE_ROSEN_DRAWING
3488         canvas_ = std::make_shared<RSPaintFilterCanvas>(skSurface.get());
3489 #else
3490         canvas_ = std::make_shared<RSPaintFilterCanvas>(drSurface.get());
3491 #endif
3492     }
3493 }
3494 
3495 bool RSUniRenderVisitor::IsNotDirtyHardwareEnabledTopSurface(std::shared_ptr<RSSurfaceRenderNode>& node) const
3496 {
3497     if (!node->IsHardwareEnabledTopSurface()) {
3498         return false;
3499     }
3500     // If the pointer is dirty in last frame but not in current, when gpu -> hardware composer.
3501     // It should also calc global dirty in current frame.
3502     node->SetNodeDirty(isHardwareForcedDisabled_ || node->HasSubNodeShouldPaint() ||
3503         !node->IsLastFrameHardwareEnabled());
3504     return !node->IsNodeDirty();
3505 }
3506 
3507 void RSUniRenderVisitor::CalcDirtyDisplayRegion(std::shared_ptr<RSDisplayRenderNode>& node)
3508 {
3509     RS_OPTIONAL_TRACE_FUNC();
3510     auto displayDirtyManager = node->GetDirtyManager();
3511     for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
3512         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
3513         if (surfaceNode == nullptr) {
3514             continue;
3515         }
3516         if (IsNotDirtyHardwareEnabledTopSurface(surfaceNode)) {
3517             continue;
3518         }
3519         auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
3520         if (isUIFirst_ && surfaceDirtyManager->IsCurrentFrameDirty()) {
3521             dirtySurfaceNodeMap_.emplace(surfaceNode->GetId(), surfaceNode->ReinterpretCastTo<RSSurfaceRenderNode>());
3522         }
3523         RectI surfaceDirtyRect = surfaceDirtyManager->GetCurrentFrameDirtyRegion();
3524         if (surfaceNode->IsTransparent()) {
3525             // Handles the case of transparent surface, merge transparent dirty rect
3526             RectI transparentDirtyRect = surfaceNode->GetDstRect().IntersectRect(surfaceDirtyRect);
3527             if (!transparentDirtyRect.IsEmpty()) {
3528                 RS_OPTIONAL_TRACE_NAME_FMT("CalcDirtyDisplayRegion merge transparent dirty rect %s rect %s",
3529                     surfaceNode->GetName().c_str(), transparentDirtyRect.ToString().c_str());
3530                 displayDirtyManager->MergeDirtyRect(transparentDirtyRect);
3531             }
3532         }
3533 
3534         if (surfaceNode->GetZorderChanged()) {
3535             // Zorder changed case, merge surface dest Rect
3536             RS_LOGD("CalcDirtyDisplayRegion merge GetZorderChanged %{public}s rect %{public}s",
3537                 surfaceNode->GetName().c_str(), surfaceNode->GetDstRect().ToString().c_str());
3538             displayDirtyManager->MergeDirtyRect(surfaceNode->GetDstRect());
3539         }
3540 
3541         RectI lastFrameSurfacePos = node->GetLastFrameSurfacePos(surfaceNode->GetId());
3542         RectI currentFrameSurfacePos = node->GetCurrentFrameSurfacePos(surfaceNode->GetId());
3543         if (surfaceNode->GetAnimateState() || lastFrameSurfacePos != currentFrameSurfacePos) {
3544             RS_LOGD("CalcDirtyDisplayRegion merge surface pos changed %{public}s lastFrameRect %{public}s"
3545                 " currentFrameRect %{public}s", surfaceNode->GetName().c_str(), lastFrameSurfacePos.ToString().c_str(),
3546                 currentFrameSurfacePos.ToString().c_str());
3547             if (!lastFrameSurfacePos.IsEmpty()) {
3548                 displayDirtyManager->MergeDirtyRect(lastFrameSurfacePos);
3549             }
3550             if (!currentFrameSurfacePos.IsEmpty()) {
3551                 displayDirtyManager->MergeDirtyRect(currentFrameSurfacePos);
3552             }
3553         }
3554 
3555         bool isShadowDisappear = !surfaceNode->GetRenderProperties().IsShadowValid() && surfaceNode->IsShadowValidLastFrame();
3556         if (surfaceNode->GetRenderProperties().IsShadowValid() || isShadowDisappear) {
3557             RectI shadowDirtyRect = surfaceNode->GetOldDirtyInSurface().IntersectRect(surfaceDirtyRect);
3558             // There are two situation here:
3559             // 1. SurfaceNode first has shadow or shadow radius is larger than the last frame,
3560             // surfaceDirtyRect == surfaceNode->GetOldDirtyInSurface()
3561             // 2. SurfaceNode remove shadow or shadow radius is smaller than the last frame,
3562             // surfaceDirtyRect > surfaceNode->GetOldDirtyInSurface()
3563             // So we should always merge surfaceDirtyRect here.
3564             if (!shadowDirtyRect.IsEmpty()) {
3565                 displayDirtyManager->MergeDirtyRect(surfaceDirtyRect);
3566                 RS_LOGD("CalcDirtyDisplayRegion merge ShadowValid %{public}s rect %{public}s",
3567                     surfaceNode->GetName().c_str(), surfaceDirtyRect.ToString().c_str());
3568             }
3569             if (isShadowDisappear) {
3570                 surfaceNode->SetShadowValidLastFrame(false);
3571             }
3572         }
3573     }
3574     std::vector<RectI> surfaceChangedRects = node->GetSurfaceChangedRects();
3575     for (auto& surfaceChangedRect : surfaceChangedRects) {
3576         RS_LOGD("CalcDirtyDisplayRegion merge Surface closed %{public}s", surfaceChangedRect.ToString().c_str());
3577         if (!surfaceChangedRect.IsEmpty()) {
3578             displayDirtyManager->MergeDirtyRect(surfaceChangedRect);
3579         }
3580     }
3581     if (RSRealtimeRefreshRateManager::Instance().GetShowRefreshRateEnabled()) {
3582         RectI tempRect = {100, 100, 500, 200};   // setDirtyRegion for RealtimeRefreshRate
3583         displayDirtyManager->MergeDirtyRect(tempRect);
3584     }
3585 }
3586 
3587 void RSUniRenderVisitor::MergeDirtyRectIfNeed(std::shared_ptr<RSSurfaceRenderNode> appNode,
3588     std::shared_ptr<RSSurfaceRenderNode> hwcNode)
3589 {
3590     if ((hwcNode->IsLastFrameHardwareEnabled() || hwcNode->IsCurrentFrameBufferConsumed()) &&
3591         appNode && appNode->GetDirtyManager()) {
3592         appNode->GetDirtyManager()->MergeDirtyRect(hwcNode->GetDstRect());
3593         dirtySurfaceNodeMap_.emplace(appNode->GetId(), appNode);
3594     }
3595 }
3596 
3597 RectI RSUniRenderVisitor::UpdateHardwareEnableList(std::vector<RectI>& filterRects,
3598     std::vector<SurfaceDirtyMgrPair>& validHwcNodes)
3599 {
3600     if (validHwcNodes.empty() || filterRects.empty()) {
3601         return RectI();
3602     }
3603     // remove invisible surface since occlusion
3604     // check intersected parts
3605     RectI filterDirty;
3606     for (auto iter = validHwcNodes.begin(); iter != validHwcNodes.end(); ++iter) {
3607         auto childNode = iter->first;
3608         auto childDirtyRect = childNode->GetDstRect();
3609         bool isIntersected = false;
3610         // remove invisible surface since occlusion
3611         for (auto& filterRect : filterRects) {
3612             if (!childDirtyRect.IntersectRect(filterRect).IsEmpty()) {
3613                 filterDirty = filterDirty.JoinRect(filterRect);
3614                 isIntersected = true;
3615             }
3616         }
3617         if (isIntersected) {
3618             childNode->SetHardwareForcedDisabledStateByFilter(true);
3619             auto node = iter->second;
3620             MergeDirtyRectIfNeed(iter->second, childNode);
3621             iter = validHwcNodes.erase(iter);
3622             iter--;
3623         }
3624     }
3625     return filterDirty;
3626 }
3627 
3628 void RSUniRenderVisitor::UpdateHardwareNodeStatusBasedOnFilter(std::shared_ptr<RSSurfaceRenderNode>& node,
3629     std::vector<SurfaceDirtyMgrPair>& prevHwcEnabledNodes,
3630     std::shared_ptr<RSDirtyRegionManager>& displayDirtyManager)
3631 {
3632     if (!IsHardwareComposerEnabled()) {
3633         return;
3634     }
3635     if (node == nullptr || !node->IsAppWindow() || node->GetDirtyManager() == nullptr ||
3636         displayDirtyManager == nullptr) {
3637         return;
3638     }
3639     auto dirtyManager = node->GetDirtyManager();
3640     auto filterRects = node->GetChildrenNeedFilterRects();
3641     // collect valid hwc surface which is not intersected with filterRects
3642     std::vector<SurfaceDirtyMgrPair> curHwcEnabledNodes;
3643     // remove invisible surface since occlusion
3644     auto visibleRegion = node->GetVisibleRegion();
3645     for (auto subNode : node->GetChildHardwareEnabledNodes()) {
3646         auto childNode = subNode.lock();
3647         if (!childNode) {
3648             continue;
3649         }
3650         // recover disabled state before update
3651         childNode->SetHardwareForcedDisabledStateByFilter(false);
3652         if (!visibleRegion.IsIntersectWith(Occlusion::Rect(childNode->GetOldDirtyInSurface()))) {
3653             continue;
3654         }
3655         bool isIntersected = false;
3656         if (isPhone_) {
3657             for (auto &hwcNode: curHwcEnabledNodes) {
3658                 if (childNode->GetDstRect().Intersect(hwcNode.first->GetDstRect())) {
3659                     childNode->SetHardwareForcedDisabledStateByFilter(true);
3660                     isIntersected = true;
3661                     break;
3662                 }
3663             }
3664         }
3665         if (!isPhone_ || !isIntersected) {
3666             curHwcEnabledNodes.emplace_back(std::make_pair(subNode, node));
3667         }
3668     }
3669     // Within App: disable hwc if intersect with filterRects
3670     dirtyManager->MergeDirtyRect(UpdateHardwareEnableList(filterRects, curHwcEnabledNodes));
3671     // Among App: disable lower hwc layers if intersect with upper transparent appWindow
3672     if (node->IsTransparent()) {
3673         if (node->GetRenderProperties().NeedFilter()) {
3674             // Attention: if transparent appwindow needs filter, only need to check itself
3675             filterRects = {node->GetDstRect()};
3676         }
3677         // In case of transparent window, filterRects need hwc surface's content
3678         RectI globalTransDirty = UpdateHardwareEnableList(filterRects, prevHwcEnabledNodes);
3679         displayDirtyManager->MergeDirtyRect(globalTransDirty);
3680         dirtyManager->MergeDirtyRect(globalTransDirty);
3681     }
3682     // erase from curHwcEnabledNodes if app node has no container window and its hwc node intersects with hwc below
3683     if (!node->HasContainerWindow() && !curHwcEnabledNodes.empty() && !prevHwcEnabledNodes.empty()) {
3684         for (auto iter = curHwcEnabledNodes.begin(); iter != curHwcEnabledNodes.end(); ++iter) {
3685             for (auto& prevNode : prevHwcEnabledNodes) {
3686                 if (!iter->first->GetDstRect().IntersectRect(prevNode.first->GetDstRect()).IsEmpty()) {
3687                     iter->first->SetHardwareForcedDisabledStateByFilter(true);
3688                     MergeDirtyRectIfNeed(iter->second, iter->first);
3689                     iter = curHwcEnabledNodes.erase(iter);
3690                     iter--;
3691                     break;
3692                 }
3693             }
3694         }
3695     }
3696     if (!curHwcEnabledNodes.empty()) {
3697         prevHwcEnabledNodes.insert(prevHwcEnabledNodes.end(), curHwcEnabledNodes.begin(), curHwcEnabledNodes.end());
3698     }
3699 }
3700 
3701 void RSUniRenderVisitor::CalcDirtyRegionForFilterNode(const RectI& filterRect,
3702     std::shared_ptr<RSSurfaceRenderNode>& currentSurfaceNode,
3703     std::shared_ptr<RSDisplayRenderNode>& displayNode)
3704 {
3705     auto displayDirtyManager = displayNode->GetDirtyManager();
3706     auto currentSurfaceDirtyManager = currentSurfaceNode->GetDirtyManager();
3707     if (displayDirtyManager == nullptr || currentSurfaceDirtyManager == nullptr) {
3708         return;
3709     }
3710 
3711     RectI displayDirtyRect = displayDirtyManager->GetCurrentFrameDirtyRegion();
3712     RectI currentSurfaceDirtyRect = currentSurfaceDirtyManager->GetCurrentFrameDirtyRegion();
3713     bool displayDirtyIntersectRectFilter = !displayDirtyRect.IntersectRect(filterRect).IsEmpty();
3714     bool surfaceDirtyIntersectRectFilter = !currentSurfaceDirtyRect.IntersectRect(filterRect).IsEmpty();
3715     if (displayDirtyIntersectRectFilter || surfaceDirtyIntersectRectFilter) {
3716         currentSurfaceDirtyManager->MergeDirtyRect(filterRect);
3717         if (!currentSurfaceNode->IsTransparent()) {
3718             Occlusion::Region filterRegion(Occlusion::Rect(filterRect.GetLeft(), filterRect.GetTop(),
3719                 filterRect.GetRight(), filterRect.GetBottom()));
3720             if (!filterRegion.Sub(currentSurfaceNode->GetOpaqueRegion()).IsEmpty()) {
3721                 displayDirtyManager->MergeDirtyRect(filterRect);
3722                 return;
3723             }
3724         }
3725     }
3726 
3727     if (currentSurfaceNode->IsTransparent()) {
3728         if (displayDirtyIntersectRectFilter) {
3729             displayDirtyManager->MergeDirtyRect(filterRect);
3730             return;
3731         }
3732         // If currentSurfaceNode is transparent and displayDirtyRect is not intersect with filterRect,
3733         // We should check whether window below currentSurfaceNode has dirtyRect intersect with filterRect.
3734         for (auto belowSurface = displayNode->GetCurAllSurfaces().begin();
3735             belowSurface != displayNode->GetCurAllSurfaces().end(); ++belowSurface) {
3736             auto belowSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*belowSurface);
3737             if (belowSurfaceNode == currentSurfaceNode) {
3738                 break;
3739             }
3740             if (belowSurfaceNode == nullptr || !belowSurfaceNode->IsAppWindow()) {
3741                 continue;
3742             }
3743             auto belowSurfaceDirtyManager = belowSurfaceNode->GetDirtyManager();
3744             RectI belowDirtyRect =
3745                 belowSurfaceDirtyManager ? belowSurfaceDirtyManager->GetCurrentFrameDirtyRegion() : RectI{0, 0, 0, 0};
3746             if (belowDirtyRect.IsEmpty()) {
3747                 continue;
3748             }
3749             // To minimize dirtyRect, only filterRect has intersect with both visibleRegion and dirtyRect
3750             // of window below, we add filterRect to displayDirtyRect and currentSurfaceDirtyRect.
3751             if (belowSurfaceNode->GetVisibleRegion().IsIntersectWith(filterRect) &&
3752                 !belowDirtyRect.IntersectRect(filterRect).IsEmpty()) {
3753                 displayDirtyManager->MergeDirtyRect(filterRect);
3754                 currentSurfaceDirtyManager->MergeDirtyRect(filterRect);
3755                 break;
3756             }
3757         }
3758     }
3759 }
3760 
3761 void RSUniRenderVisitor::CalcChildFilterNodeDirtyRegion(std::shared_ptr<RSSurfaceRenderNode>& currentSurfaceNode,
3762     std::shared_ptr<RSDisplayRenderNode>& displayNode)
3763 {
3764     if (currentSurfaceNode == nullptr || displayNode == nullptr) {
3765         return;
3766     }
3767     auto filterRects = currentSurfaceNode->GetChildrenNeedFilterRects();
3768     auto filterNodes = currentSurfaceNode->GetChildrenFilterNodes();
3769     if (currentSurfaceNode->IsAppWindow() && !filterRects.empty()) {
3770         needFilter_ = needFilter_ || !currentSurfaceNode->IsStaticCached();
3771         for (size_t i = 0; i < filterNodes.size(); i++) {
3772             auto filterRectsCacheValidNow = filterNodes[i]->IsBackgroundFilterCacheValid();
3773             // if child filter node has filter cache, no need to be added into dirtyregion
3774             // only support background filter cache valid and no pixelstretch node now
3775             if (isCacheBlurPartialRenderEnabled_ && filterRectsCacheValidNow &&
3776                 !filterNodes[i]->GetRenderProperties().GetPixelStretch().has_value()) {
3777                 continue;
3778             }
3779             CalcDirtyRegionForFilterNode(filterRects[i], currentSurfaceNode, displayNode);
3780         }
3781     }
3782 }
3783 
3784 void RSUniRenderVisitor::CalcSurfaceFilterNodeDirtyRegion(std::shared_ptr<RSSurfaceRenderNode>& currentSurfaceNode,
3785     std::shared_ptr<RSDisplayRenderNode>& displayNode)
3786 {
3787     if (currentSurfaceNode == nullptr || displayNode == nullptr) {
3788         return;
3789     }
3790     if (currentSurfaceNode->GetRenderProperties().NeedFilter()) {
3791         needFilter_ = needFilter_ || !currentSurfaceNode->IsStaticCached();
3792         CalcDirtyRegionForFilterNode(
3793             currentSurfaceNode->GetOldDirtyInSurface(), currentSurfaceNode, displayNode);
3794     }
3795 }
3796 
3797 void RSUniRenderVisitor::UpdateHardwareNodeStatusBasedOnFilterRegion(RSDisplayRenderNode& displayNode)
3798 {
3799     std::vector<std::shared_ptr<RSSurfaceRenderNode>> prevHwcEnabledNodes;
3800     for (auto it = displayNode.GetCurAllSurfaces().begin(); it != displayNode.GetCurAllSurfaces().end(); ++it) {
3801         auto currentSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
3802         if (currentSurfaceNode != nullptr) {
3803             UpdateHardwareNodeStatusBasedOnFilter(currentSurfaceNode, prevHwcEnabledNodes);
3804         }
3805     }
3806 }
3807 
3808 void RSUniRenderVisitor::UpdateHardwareNodeStatusBasedOnFilter(std::shared_ptr<RSSurfaceRenderNode>& node,
3809     std::vector<std::shared_ptr<RSSurfaceRenderNode>>& prevHwcEnabledNodes)
3810 {
3811     if (!IsHardwareComposerEnabled()) {
3812         return;
3813     }
3814     if (node == nullptr || !node->IsAppWindow()) {
3815         return;
3816     }
3817     auto filterRects = node->GetChildrenNeedFilterRects();
3818     // collect valid hwc surface which is not intersected with filterRects
3819     std::vector<std::shared_ptr<RSSurfaceRenderNode>> curHwcEnabledNodes;
3820     for (auto subNode : node->GetChildHardwareEnabledNodes()) {
3821         auto childNode = subNode.lock();
3822         if (!childNode) {
3823             continue;
3824         }
3825         childNode->SetHardwareForcedDisabledStateByFilter(false);
3826         bool isIntersected = false;
3827         if (isPhone_) {
3828             for (auto &hwcNode: curHwcEnabledNodes) {
3829                 if (childNode->GetDstRect().Intersect(hwcNode->GetDstRect())) {
3830                     childNode->SetHardwareForcedDisabledStateByFilter(true);
3831                     isIntersected = true;
3832                     break;
3833                 }
3834             }
3835         }
3836         if (!isPhone_ || !isIntersected) {
3837             curHwcEnabledNodes.emplace_back(childNode);
3838         }
3839     }
3840     // Within App: disable hwc if intersect with filterRects
3841     UpdateHardwareEnableList(filterRects, curHwcEnabledNodes);
3842     // Among App: disable lower hwc layers if intersect with upper transparent appWindow
3843     if (node->IsTransparent()) {
3844         if (node->GetRenderProperties().NeedFilter()) {
3845             // Attention: if transparent appwindow needs filter, only need to check itself
3846             filterRects = {node->GetDstRect()};
3847         }
3848         // In case of transparent window, filterRects need hwc surface's content
3849         UpdateHardwareEnableList(filterRects, prevHwcEnabledNodes);
3850     }
3851     if (!curHwcEnabledNodes.empty()) {
3852         prevHwcEnabledNodes.insert(prevHwcEnabledNodes.end(), curHwcEnabledNodes.begin(), curHwcEnabledNodes.end());
3853     }
3854 }
3855 
3856 void RSUniRenderVisitor::UpdateHardwareEnableList(std::vector<RectI>& filterRects,
3857     std::vector<std::shared_ptr<RSSurfaceRenderNode>>& validHwcNodes)
3858 {
3859     if (validHwcNodes.empty() || filterRects.empty()) {
3860         return;
3861     }
3862     for (auto iter = validHwcNodes.begin(); iter != validHwcNodes.end(); ++iter) {
3863         auto childDirtyRect = (*iter)->GetDstRect();
3864         bool isIntersected = false;
3865         for (auto& filterRect : filterRects) {
3866             if (!childDirtyRect.IntersectRect(filterRect).IsEmpty()) {
3867                 isIntersected = true;
3868             }
3869         }
3870         if (isIntersected) {
3871             (*iter)->SetHardwareForcedDisabledStateByFilter(true);
3872             iter = validHwcNodes.erase(iter);
3873             iter--;
3874         }
3875     }
3876 }
3877 
3878 void RSUniRenderVisitor::CalcDirtyFilterRegion(std::shared_ptr<RSDisplayRenderNode>& displayNode)
3879 {
3880     if (displayNode == nullptr || displayNode->GetDirtyManager() == nullptr) {
3881         return;
3882     }
3883     auto displayDirtyManager = displayNode->GetDirtyManager();
3884     std::vector<SurfaceDirtyMgrPair> prevHwcEnabledNodes;
3885     for (auto it = displayNode->GetCurAllSurfaces().begin(); it != displayNode->GetCurAllSurfaces().end(); ++it) {
3886         auto currentSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
3887         if (currentSurfaceNode) {
3888             // [planning] Update hwc surface dirty status at the same time
3889             UpdateHardwareNodeStatusBasedOnFilter(currentSurfaceNode, prevHwcEnabledNodes, displayDirtyManager);
3890         }
3891     }
3892 
3893     for (auto it = displayNode->GetCurAllSurfaces().begin(); it != displayNode->GetCurAllSurfaces().end();) {
3894         auto currentSurfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
3895         if (currentSurfaceNode == nullptr) {
3896             ++it;
3897             continue;
3898         }
3899         if (currentSurfaceNode->GetVisibleRegion().IsEmpty()) {
3900             ++it;
3901             continue;
3902         }
3903         auto lastDisplayDirtyRegion = displayDirtyManager->GetCurrentFrameDirtyRegion();
3904         // child node (component) has filter
3905         CalcChildFilterNodeDirtyRegion(currentSurfaceNode, displayNode);
3906         // surfaceNode self has filter
3907         CalcSurfaceFilterNodeDirtyRegion(currentSurfaceNode, displayNode);
3908         if (lastDisplayDirtyRegion != displayDirtyManager->GetCurrentFrameDirtyRegion()) {
3909             // When DisplayDirtyRegion is changed, collect dirty filter region from begin.
3910             // After all filter region is added, the cycle will definitely stop. there is no risk of a dead cycle.
3911             it = displayNode->GetCurAllSurfaces().begin();
3912         } else {
3913             ++it;
3914         }
3915     }
3916 }
3917 
3918 void RSUniRenderVisitor::AddContainerDirtyToGlobalDirty(std::shared_ptr<RSDisplayRenderNode>& node) const
3919 {
3920     RS_OPTIONAL_TRACE_FUNC();
3921     auto displayDirtyManager = node->GetDirtyManager();
3922     for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
3923         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
3924         if (surfaceNode == nullptr) {
3925             continue;
3926         }
3927         auto surfaceDirtyManager = surfaceNode->GetDirtyManager();
3928         if (surfaceDirtyManager == nullptr) {
3929             continue;
3930         }
3931         RectI surfaceDirtyRect = surfaceDirtyManager->GetCurrentFrameDirtyRegion();
3932 
3933         if (surfaceNode->HasContainerWindow()) {
3934             // If a surface's dirty is intersect with container region (which can be considered transparent)
3935             // should be added to display dirty region.
3936             // Note: we use containerRegion rather transparentRegion to bypass inner corner dirty problem.
3937             auto containerRegion = surfaceNode->GetContainerRegion();
3938             auto surfaceDirtyRegion = Occlusion::Region{Occlusion::Rect{surfaceDirtyRect}};
3939             auto containerDirtyRegion = containerRegion.And(surfaceDirtyRegion);
3940             if (!containerDirtyRegion.IsEmpty()) {
3941                 RS_LOGD("CalcDirtyDisplayRegion merge containerDirtyRegion %{public}s region %{public}s",
3942                     surfaceNode->GetName().c_str(), containerDirtyRegion.GetRegionInfo().c_str());
3943                 // plan: we can use surfacenode's absrect as containerRegion's bound
3944                 const auto& rect = containerRegion.GetBoundRef();
3945                 displayDirtyManager->MergeDirtyRect(
3946                     RectI{ rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_ });
3947             }
3948         } else {
3949             // warning: if a surfacenode has transparent region and opaque region, and its dirty pattern appears in
3950             // transparent region and opaque region in adjacent frame, may cause displaydirty region incomplete after
3951             // merge history (as surfacenode's dirty region merging opaque region will enlarge surface dirty region
3952             // which include transparent region but not counted in display dirtyregion)
3953             if (!surfaceNode->IsNodeDirty()) {
3954                 continue;
3955             }
3956             auto transparentRegion = surfaceNode->GetTransparentRegion();
3957             Occlusion::Rect tmpRect = Occlusion::Rect { surfaceDirtyRect.left_, surfaceDirtyRect.top_,
3958                 surfaceDirtyRect.GetRight(), surfaceDirtyRect.GetBottom() };
3959             Occlusion::Region surfaceDirtyRegion { tmpRect };
3960             Occlusion::Region transparentDirtyRegion = transparentRegion.And(surfaceDirtyRegion);
3961             if (!transparentDirtyRegion.IsEmpty()) {
3962                 RS_LOGD("CalcDirtyDisplayRegion merge TransparentDirtyRegion %{public}s region %{public}s",
3963                     surfaceNode->GetName().c_str(), transparentDirtyRegion.GetRegionInfo().c_str());
3964                 const std::vector<Occlusion::Rect>& rects = transparentDirtyRegion.GetRegionRects();
3965                 for (const auto& rect : rects) {
3966                     displayDirtyManager->MergeDirtyRect(
3967                         RectI{ rect.left_, rect.top_, rect.right_ - rect.left_, rect.bottom_ - rect.top_ });
3968                 }
3969             }
3970         }
3971     }
3972 }
3973 
3974 void RSUniRenderVisitor::SetSurfaceGlobalDirtyRegion(std::shared_ptr<RSDisplayRenderNode>& node)
3975 {
3976     RS_OPTIONAL_TRACE_FUNC();
3977     for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
3978         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
3979         if (surfaceNode == nullptr || !surfaceNode->IsMainWindowType()) {
3980             continue;
3981         }
3982         // set display dirty region to surfaceNode
3983         surfaceNode->SetGlobalDirtyRegion(node->GetDirtyManager()->GetDirtyRegion());
3984         surfaceNode->SetDirtyRegionAlignedEnable(false);
3985     }
3986     Occlusion::Region curVisibleDirtyRegion;
3987     for (auto& it : node->GetCurAllSurfaces()) {
3988         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(it);
3989         if (surfaceNode == nullptr || !surfaceNode->IsMainWindowType()) {
3990             continue;
3991         }
3992         // set display dirty region to surfaceNode
3993         surfaceNode->SetDirtyRegionBelowCurrentLayer(curVisibleDirtyRegion);
3994         auto visibleDirtyRegion = surfaceNode->GetVisibleDirtyRegion();
3995         curVisibleDirtyRegion = curVisibleDirtyRegion.Or(visibleDirtyRegion);
3996     }
3997 }
3998 
3999 void RSUniRenderVisitor::SetSurfaceGlobalAlignedDirtyRegion(std::shared_ptr<RSDisplayRenderNode>& node,
4000     const Occlusion::Region alignedDirtyRegion)
4001 {
4002     RS_TRACE_FUNC();
4003     if (!isDirtyRegionAlignedEnable_) {
4004         return;
4005     }
4006     // calculate extra dirty region after 32 bits alignment
4007     Occlusion::Region dirtyRegion = alignedDirtyRegion;
4008     auto globalRectI = node->GetDirtyManager()->GetDirtyRegion();
4009     Occlusion::Rect globalRect {globalRectI.left_, globalRectI.top_, globalRectI.GetRight(), globalRectI.GetBottom()};
4010     Occlusion::Region globalRegion{globalRect};
4011     dirtyRegion.SubSelf(globalRegion);
4012     for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
4013         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
4014         if (surfaceNode == nullptr || !surfaceNode->IsMainWindowType()) {
4015             continue;
4016         }
4017         surfaceNode->SetGlobalDirtyRegion(node->GetDirtyManager()->GetDirtyRegion());
4018         Occlusion::Region visibleRegion = surfaceNode->GetVisibleRegion();
4019         Occlusion::Region surfaceAlignedDirtyRegion = surfaceNode->GetAlignedVisibleDirtyRegion();
4020         if (dirtyRegion.IsEmpty()) {
4021             surfaceNode->SetExtraDirtyRegionAfterAlignment(dirtyRegion);
4022         } else {
4023             auto extraDirtyRegion = (dirtyRegion.Sub(surfaceAlignedDirtyRegion)).And(visibleRegion);
4024             surfaceNode->SetExtraDirtyRegionAfterAlignment(extraDirtyRegion);
4025         }
4026         surfaceNode->SetDirtyRegionAlignedEnable(true);
4027     }
4028     Occlusion::Region curVisibleDirtyRegion;
4029     for (auto& it : node->GetCurAllSurfaces()) {
4030         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(it);
4031         if (surfaceNode == nullptr || !surfaceNode->IsMainWindowType()) {
4032             continue;
4033         }
4034         surfaceNode->SetDirtyRegionBelowCurrentLayer(curVisibleDirtyRegion);
4035         auto alignedVisibleDirtyRegion = surfaceNode->GetAlignedVisibleDirtyRegion();
4036         curVisibleDirtyRegion.OrSelf(alignedVisibleDirtyRegion);
4037     }
4038 }
4039 
4040 void RSUniRenderVisitor::AlignGlobalAndSurfaceDirtyRegions(std::shared_ptr<RSDisplayRenderNode>& node)
4041 {
4042     node->GetDirtyManager()->UpdateDirtyByAligned();
4043     for (auto it = node->GetCurAllSurfaces().rbegin(); it != node->GetCurAllSurfaces().rend(); ++it) {
4044         auto surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(*it);
4045         if (surfaceNode == nullptr || !surfaceNode->IsMainWindowType()) {
4046             continue;
4047         }
4048         surfaceNode->GetDirtyManager()->UpdateDirtyByAligned();
4049     }
4050 }
4051 
4052 #ifdef RS_ENABLE_EGLQUERYSURFACE
4053 std::vector<RectI> RSUniRenderVisitor::GetDirtyRects(const Occlusion::Region &region)
4054 {
4055     const std::vector<Occlusion::Rect>& rects = region.GetRegionRects();
4056     std::vector<RectI> retRects;
4057     for (const Occlusion::Rect& rect : rects) {
4058         // origin transformation
4059 #ifdef RS_ENABLE_VK
4060         if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
4061             RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
4062             retRects.emplace_back(RectI(rect.left_, rect.top_,
4063                 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
4064         } else {
4065             retRects.emplace_back(RectI(rect.left_, screenInfo_.GetRotatedHeight() - rect.bottom_,
4066                 rect.right_ - rect.left_, rect.bottom_ - rect.top_));
4067         }
4068 #else
4069         retRects.emplace_back(RectI(rect.left_, screenInfo_.GetRotatedHeight() - rect.bottom_,
4070             rect.right_ - rect.left_, rect.bottom_ - rect.top_));
4071 #endif
4072     }
4073     RS_LOGD("GetDirtyRects size %{public}d %{public}s", region.GetSize(), region.GetRegionInfo().c_str());
4074     return retRects;
4075 }
4076 #endif
4077 
4078 void RSUniRenderVisitor::CheckAndSetNodeCacheType(RSRenderNode& node)
4079 {
4080     if (node.IsStaticCached()) {
4081         if (node.GetCacheType() != CacheType::CONTENT) {
4082             node.SetCacheType(CacheType::CONTENT);
4083             RSUniRenderUtil::ClearCacheSurface(node, threadIndex_);
4084         }
4085 
4086         if (!node.GetCompletedCacheSurface(threadIndex_, true) && UpdateCacheSurface(node)) {
4087             node.UpdateCompletedCacheSurface();
4088         }
4089     } else if (isDrawingCacheEnabled_ && GenerateNodeContentCache(node)) {
4090         UpdateCacheRenderNodeMapWithBlur(node);
4091     } else {
4092         if (node.GetCacheType() != CacheType::NONE) {
4093             node.SetCacheType(CacheType::NONE);
4094             if (node.GetCompletedCacheSurface(threadIndex_, false)) {
4095                 RSUniRenderUtil::ClearCacheSurface(node, threadIndex_);
4096             }
4097         }
4098         // label this frame not run CheckAndSetNodeCacheType, means not run drawCacheWithBlur
4099         notRunCheckAndSetNodeCacheType_ = true;
4100     }
4101 }
4102 
4103 bool RSUniRenderVisitor::UpdateCacheSurface(RSRenderNode& node)
4104 {
4105     RS_TRACE_NAME_FMT("UpdateCacheSurface: [%llu]", node.GetId());
4106     CacheType cacheType = node.GetCacheType();
4107     if (cacheType == CacheType::NONE) {
4108         return false;
4109     }
4110 
4111     if (!node.GetCacheSurface(threadIndex_, true)) {
4112         RSRenderNode::ClearCacheSurfaceFunc func = std::bind(&RSUniRenderUtil::ClearNodeCacheSurface,
4113             std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
4114 #ifndef USE_ROSEN_DRAWING
4115 #ifdef NEW_SKIA
4116         node.InitCacheSurface(canvas_ ? canvas_->recordingContext() : nullptr, func, threadIndex_);
4117 #else
4118         node.InitCacheSurface(canvas_ ? canvas_->getGrContext() : nullptr, func, threadIndex_);
4119 #endif
4120 #else
4121         node.InitCacheSurface(canvas_ ? canvas_->GetGPUContext().get() : nullptr, func, threadIndex_);
4122 #endif
4123     }
4124     auto surface = node.GetCacheSurface(threadIndex_, true);
4125     if (!surface) {
4126         RS_LOGE("Get CacheSurface failed");
4127         return false;
4128     }
4129     auto cacheCanvas = std::make_shared<RSPaintFilterCanvas>(surface.get());
4130     if (!cacheCanvas) {
4131         return false;
4132     }
4133 
4134     // copy current canvas properties into cacheCanvas
4135     if (renderEngine_) {
4136         cacheCanvas->SetHighContrast(renderEngine_->IsHighContrastEnabled());
4137     }
4138     if (canvas_) {
4139         cacheCanvas->CopyConfiguration(*canvas_);
4140     }
4141     // Using filter cache in multi-thread environment may cause GPU memory leak or invalid textures, so we explicitly
4142     // disable it in sub-thread.
4143     cacheCanvas->SetDisableFilterCache(isSubThread_);
4144 
4145     // When drawing CacheSurface, all child node should be drawn.
4146     // So set isOpDropped_ = false here.
4147     bool isOpDropped = isOpDropped_;
4148     isOpDropped_ = false;
4149     isUpdateCachedSurface_ = true;
4150 
4151 #ifndef USE_ROSEN_DRAWING
4152     cacheCanvas->clear(SK_ColorTRANSPARENT);
4153 #else
4154     cacheCanvas->Clear(Drawing::Color::COLOR_TRANSPARENT);
4155 #endif
4156 
4157     swap(cacheCanvas, canvas_);
4158     // When cacheType == CacheType::ANIMATE_PROPERTY,
4159     // we should draw AnimateProperty on cacheCanvas
4160     if (cacheType == CacheType::ANIMATE_PROPERTY) {
4161         if (node.GetRenderProperties().IsShadowValid()
4162             && !node.GetRenderProperties().IsSpherizeValid()) {
4163 #ifndef USE_ROSEN_DRAWING
4164             canvas_->save();
4165             canvas_->translate(node.GetShadowRectOffsetX(), node.GetShadowRectOffsetY());
4166 #else
4167             canvas_->Save();
4168             canvas_->Translate(node.GetShadowRectOffsetX(), node.GetShadowRectOffsetY());
4169 #endif
4170         }
4171         node.ProcessAnimatePropertyBeforeChildren(*canvas_);
4172     }
4173     if (node.IsNodeGroupIncludeProperty()) {
4174         node.ProcessAnimatePropertyBeforeChildren(*canvas_);
4175     }
4176     if (node.GetDrawingCacheType() != RSDrawingCacheType::DISABLED_CACHE) {
4177         node.SetDrawingCacheRootId(node.GetId());
4178     }
4179     node.ProcessRenderContents(*canvas_);
4180     // Set a count to label the ProcessChildren in updateCacheProcess
4181     updateCacheProcessCnt_++;
4182     ProcessChildren(node);
4183     updateCacheProcessCnt_--;
4184 
4185     if (cacheType == CacheType::ANIMATE_PROPERTY) {
4186         if (node.GetRenderProperties().IsShadowValid()
4187             && !node.GetRenderProperties().IsSpherizeValid()) {
4188 #ifndef USE_ROSEN_DRAWING
4189             canvas_->restore();
4190 #else
4191             canvas_->Restore();
4192 #endif
4193         }
4194         node.ProcessAnimatePropertyAfterChildren(*canvas_);
4195     }
4196     swap(cacheCanvas, canvas_);
4197 
4198     isUpdateCachedSurface_ = false;
4199     isOpDropped_ = isOpDropped;
4200 
4201     // To get all FreezeNode
4202     // execute: "param set rosen.dumpsurfacetype.enabled 2 && setenforce 0"
4203     // To get specific FreezeNode
4204     // execute: "param set rosen.dumpsurfacetype.enabled 1 && setenforce 0 && "
4205     // "param set rosen.dumpsurfaceid "NodeId" "
4206     // Png file could be found in /data
4207     RSBaseRenderUtil::WriteCacheRenderNodeToPng(node);
4208     return true;
4209 }
4210 
4211 void RSUniRenderVisitor::DrawSpherize(RSRenderNode& node)
4212 {
4213     if (node.GetCacheType() != CacheType::ANIMATE_PROPERTY) {
4214         node.SetCacheType(CacheType::ANIMATE_PROPERTY);
4215         RSUniRenderUtil::ClearCacheSurface(node, threadIndex_);
4216     }
4217     if (!node.GetCompletedCacheSurface(threadIndex_, true) && UpdateCacheSurface(node)) {
4218         node.UpdateCompletedCacheSurface();
4219     }
4220     node.ProcessTransitionBeforeChildren(*canvas_);
4221     RSPropertiesPainter::DrawSpherize(
4222         node.GetRenderProperties(), *canvas_, node.GetCompletedCacheSurface(threadIndex_, true));
4223     node.ProcessTransitionAfterChildren(*canvas_);
4224 }
4225 
4226 bool RSUniRenderVisitor::DrawBlurInCache(RSRenderNode& node)
4227 {
4228     if (LIKELY(curCacheFilterRects_.empty())) {
4229         return false;
4230     }
4231     if (curCacheFilterRects_.top().count(node.GetId())) {
4232         if (curGroupedNodes_.empty()) {
4233             // draw filter before drawing cached surface
4234             curCacheFilterRects_.top().erase(node.GetId());
4235             if (curCacheFilterRects_.empty() || !node.ChildHasFilter()) {
4236                 // no filter to draw, return
4237                 return true;
4238             }
4239         } else if (node.GetRenderProperties().GetShadowColorStrategy() !=
4240             SHADOW_COLOR_STRATEGY::COLOR_STRATEGY_NONE) {
4241             // clear hole while generating cache surface
4242 #ifndef USE_ROSEN_DRAWING
4243             SkAutoCanvasRestore arc(canvas_.get(), true);
4244             RectI shadowRect;
4245             auto rrect = node.GetRenderProperties().GetRRect();
4246             RSPropertiesPainter::GetShadowDirtyRect(shadowRect, node.GetRenderProperties(), &rrect, false, false);
4247             SkCanvasPriv::ResetClip(canvas_.get());
4248             canvas_->clipRect(SkRect::MakeXYWH(shadowRect.left_, shadowRect.top_,
4249                 shadowRect.width_, shadowRect.height_));
4250             canvas_->clear(SK_ColorTRANSPARENT);
4251 #else
4252             Drawing::AutoCanvasRestore arc(*canvas_.get(), true);
4253             RectI shadowRect;
4254             auto rrect = node.GetRenderProperties().GetRRect();
4255             RSPropertiesPainter::GetShadowDirtyRect(shadowRect, node.GetRenderProperties(), &rrect, false, false);
4256             std::shared_ptr<Drawing::CoreCanvasImpl> coreCanvas = canvas_->GetCanvasData();
4257             auto skiaCanvas = static_cast<Drawing::SkiaCanvas *>(coreCanvas.get());
4258             SkCanvasPriv::ResetClip(skiaCanvas->ExportSkCanvas());
4259             canvas_->ClipRect(Drawing::Rect(shadowRect.left_, shadowRect.top_,
4260                 shadowRect.width_ + shadowRect.left_, shadowRect.height_ + shadowRect.top_));
4261             canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
4262 #endif
4263         } else if (node.GetRenderProperties().GetBackgroundFilter() || node.GetRenderProperties().GetUseEffect()) {
4264             // clear hole while generating cache surface
4265 #ifndef USE_ROSEN_DRAWING
4266             SkAutoCanvasRestore arc(canvas_.get(), true);
4267             if (node.GetRenderProperties().GetClipBounds() != nullptr) {
4268                 canvas_->clipRect(RSPropertiesPainter::Rect2SkRect(node.GetRenderProperties().GetBoundsRect()));
4269             } else {
4270                 canvas_->clipRRect(RSPropertiesPainter::RRect2SkRRect(node.GetRenderProperties().GetRRect()));
4271             }
4272             canvas_->clear(SK_ColorTRANSPARENT);
4273 #else
4274             Drawing::AutoCanvasRestore arc(*canvas_, true);
4275             if (node.GetRenderProperties().GetClipBounds() != nullptr) {
4276                 canvas_->ClipRect(RSPropertiesPainter::Rect2DrawingRect(node.GetRenderProperties().GetBoundsRect()),
4277                     Drawing::ClipOp::INTERSECT, false);
4278             } else {
4279                 canvas_->ClipRoundRect(RSPropertiesPainter::RRect2DrawingRRect(node.GetRenderProperties().GetRRect()),
4280                     Drawing::ClipOp::INTERSECT, false);
4281             }
4282             canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
4283 #endif
4284         }
4285     } else if (curGroupedNodes_.empty() && !node.ChildHasFilter()) {
4286         // no filter to draw, return
4287         return true;
4288     }
4289     return false;
4290 }
4291 
4292 void RSUniRenderVisitor::DrawChildCanvasRenderNode(RSRenderNode& node)
4293 {
4294      if (node.GetCacheType() == CacheType::NONE) {
4295          if (node.IsPureContainer()) {
4296              processedPureContainerNode_++;
4297              node.ApplyBoundsGeometry(*canvas_);
4298              ProcessChildren(node);
4299              node.RSRenderNode::ProcessTransitionAfterChildren(*canvas_);
4300              return;
4301          } else if (node.IsContentNode()) {
4302              node.ApplyBoundsGeometry(*canvas_);
4303              node.ApplyAlpha(*canvas_);
4304              node.ProcessRenderContents(*canvas_);
4305              ProcessChildren(node);
4306              node.RSRenderNode::ProcessTransitionAfterChildren(*canvas_);
4307              return;
4308          }
4309     }
4310     DrawChildRenderNode(node);
4311 }
4312 
4313 void RSUniRenderVisitor::DrawChildRenderNode(RSRenderNode& node)
4314 {
4315     CacheType cacheType = node.GetCacheType();
4316     node.ProcessTransitionBeforeChildren(*canvas_);
4317     switch (cacheType) {
4318         case CacheType::NONE: {
4319             auto preCache = canvas_->GetCacheType();
4320             if (node.HasCacheableAnim() && isDrawingCacheEnabled_) {
4321                 canvas_->SetCacheType(RSPaintFilterCanvas::CacheType::ENABLED);
4322             }
4323             node.ProcessAnimatePropertyBeforeChildren(*canvas_);
4324             node.ProcessRenderContents(*canvas_);
4325             ProcessChildren(node);
4326             node.ProcessAnimatePropertyAfterChildren(*canvas_);
4327             if (node.HasCacheableAnim() && isDrawingCacheEnabled_) {
4328                 canvas_->SetCacheType(preCache);
4329             }
4330             break;
4331         }
4332         case CacheType::CONTENT: {
4333             if (node.IsNodeGroupIncludeProperty()) {
4334                 node.ProcessAnimatePropertyBeforeChildren(*canvas_, false);
4335             } else {
4336                 node.ProcessAnimatePropertyBeforeChildren(*canvas_);
4337             }
4338             node.DrawCacheSurface(*canvas_, threadIndex_, false);
4339             node.ProcessAnimatePropertyAfterChildren(*canvas_);
4340             cacheRenderNodeMapRects_.push_back(node.GetOldDirtyInSurface());
4341             break;
4342         }
4343         case CacheType::ANIMATE_PROPERTY: {
4344             node.DrawCacheSurface(*canvas_, threadIndex_, false);
4345             break;
4346         }
4347         default:
4348             break;
4349     }
4350     node.ProcessTransitionAfterChildren(*canvas_);
4351 }
4352 
4353 bool RSUniRenderVisitor::CheckIfSurfaceRenderNodeNeedProcess(RSSurfaceRenderNode& node, bool& keepFilterCache)
4354 {
4355     if (isSubThread_) {
4356         return true;
4357     }
4358     if (RSMainThread::Instance()->GetCacheCmdSkippedNodes().count(node.GetId()) != 0) {
4359         return true;
4360     }
4361     if (isSecurityDisplay_ && node.GetSkipLayer()) {
4362         RS_PROCESS_TRACE(isPhone_, node.GetName() + " SkipLayer Skip");
4363         return false;
4364     }
4365     if (!node.ShouldPaint()) {
4366         MarkSubHardwareEnableNodeState(node);
4367         RS_OPTIONAL_TRACE_NAME(node.GetName() + " Node should not paint Skip");
4368         RS_LOGD("RSUniRenderVisitor::IfSurfaceRenderNodeNeedProcess node: %{public}" PRIu64 " invisible",
4369             node.GetId());
4370         return false;
4371     }
4372     if (!node.GetOcclusionVisible() && isOcclusionEnabled_ && !isSecurityDisplay_) {
4373         MarkSubHardwareEnableNodeState(node);
4374         if (!node.GetVisibleRegionForCallBack().IsEmpty()) {
4375             keepFilterCache = true;
4376         }
4377         RS_PROCESS_TRACE(isPhone_, node.GetName() + " Occlusion Skip");
4378         return false;
4379     }
4380     if (node.IsAbilityComponent() && node.GetDstRect().IsEmpty() && curGroupedNodes_.empty()) {
4381         RS_PROCESS_TRACE(isPhone_, node.GetName() + " Empty AbilityComponent Skip");
4382         return false;
4383     }
4384     std::shared_ptr<RSSurfaceRenderNode> appNode;
4385     if (node.LeashWindowRelatedAppWindowOccluded(appNode)) {
4386         if (appNode != nullptr) {
4387             MarkSubHardwareEnableNodeState(*appNode);
4388         }
4389         RS_PROCESS_TRACE(isPhone_, node.GetName() + " App Occluded Leashwindow Skip");
4390         return false;
4391     }
4392     if (!screenInfo_.filteredAppSet.empty() && virtualScreenFilterAppRootId_ == INVALID_NODEID) {
4393         RS_PROCESS_TRACE(isPhone_, node.GetName() + " skip because it isn't filtered App");
4394         RS_LOGD("RSUniRenderVisitor::CheckIfSurfaceRenderNodeNeedProcess:\
4395             %{public}s skip because it isn't filtered App", node.GetName().c_str());
4396         return false;
4397     }
4398     return true;
4399 }
4400 
4401 bool RSUniRenderVisitor::IsRosenWebHardwareDisabled(RSSurfaceRenderNode& node, int rotation) const
4402 {
4403     if (node.IsRosenWeb()) {
4404         return rotation == ROTATION_90 || rotation == ROTATION_270 ||
4405             RSUniRenderUtil::Is3DRotation(node.GetTotalMatrix()) ||
4406             node.GetDstRect().width_ > node.GetBuffer()->GetWidth() ||
4407             node.GetDstRect().height_ > node.GetBuffer()->GetHeight();
4408     }
4409     return false;
4410 }
4411 
4412 bool RSUniRenderVisitor::ForceHardwareComposer(RSSurfaceRenderNode& node) const
4413 {
4414     auto bufferPixelFormat = node.GetBuffer()->GetFormat();
4415     return (bufferPixelFormat == GRAPHIC_PIXEL_FMT_RGBA_1010102 ||
4416          bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCBCR_P010 ||
4417          bufferPixelFormat == GRAPHIC_PIXEL_FMT_YCRCB_P010) && !node.IsHardwareForcedDisabledByFilter() &&
4418          !isUpdateCachedSurface_;
4419 }
4420 
4421 bool RSUniRenderVisitor::UpdateSrcRectForHwcNode(RSSurfaceRenderNode& node)
4422 {
4423 #ifndef USE_ROSEN_DRAWING
4424     SkAutoCanvasRestore acr(canvas_.get(), true);
4425 
4426     if (displayNodeMatrix_.has_value()) {
4427         auto& displayNodeMatrix = displayNodeMatrix_.value();
4428         canvas_->concat(displayNodeMatrix);
4429     }
4430     node.SetTotalMatrix(canvas_->getTotalMatrix());
4431 
4432     auto dstRect = node.GetDstRect();
4433     SkIRect dst = { dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(), dstRect.GetBottom() };
4434 #else
4435     Drawing::AutoCanvasRestore acr(*canvas_.get(), true);
4436 
4437     if (displayNodeMatrix_.has_value()) {
4438         auto& displayNodeMatrix = displayNodeMatrix_.value();
4439         canvas_->ConcatMatrix(displayNodeMatrix);
4440     }
4441     node.SetTotalMatrix(canvas_->GetTotalMatrix());
4442 
4443     auto dstRect = node.GetDstRect();
4444     Drawing::RectI dst = { dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetRight(),
4445                            dstRect.GetBottom() };
4446 #endif
4447     bool hasRotation = false;
4448     if (node.GetConsumer() != nullptr) {
4449         auto rotation = RSBaseRenderUtil::GetRotateTransform(node.GetConsumer()->GetTransform());
4450         hasRotation = rotation == GRAPHIC_ROTATE_90 || rotation == GRAPHIC_ROTATE_270;
4451     }
4452     node.UpdateSrcRect(*canvas_, dst, hasRotation);
4453     return !node.IsHardwareDisabledBySrcRect();
4454 }
4455 
4456 void RSUniRenderVisitor::ProcessSurfaceRenderNode(RSSurfaceRenderNode& node)
4457 {
4458     if (isUIFirst_ && isSubThread_) {
4459         bool isFirstLevelSurface = !RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.GetParent().lock());
4460         if (isSubSurfaceEnabled_) {
4461             isFirstLevelSurface = node.IsFirstLevelSurfaceNode();
4462         }
4463         if (auto parentNode = RSBaseRenderNode::ReinterpretCast<RSDisplayRenderNode>(node.GetParent().lock()) ||
4464             (SceneBoardJudgement::IsSceneBoardEnabled() && (node.IsLeashWindow() || (node.IsAppWindow() &&
4465             isFirstLevelSurface)))) {
4466             UpdateCacheSurface(node);
4467             return;
4468         }
4469     }
4470     if (RSSystemProperties::GetProxyNodeDebugEnabled() && node.contextClipRect_.has_value() && canvas_ != nullptr) {
4471         // draw transparent red rect to indicate valid clip area
4472         {
4473             RSAutoCanvasRestore acr(canvas_);
4474 #ifndef USE_ROSEN_DRAWING
4475             canvas_->concat(node.contextMatrix_.value_or(SkMatrix::I()));
4476             SkPaint paint;
4477             paint.setARGB(0x80, 0xFF, 0, 0); // transparent red
4478             canvas_->drawRect(node.contextClipRect_.value(), paint);
4479 #else
4480             canvas_->ConcatMatrix(node.contextMatrix_.value_or(Drawing::Matrix()));
4481             Drawing::Brush brush;
4482             brush.SetARGB(0x80, 0xFF, 0, 0); // transparent red
4483             canvas_->AttachBrush(brush);
4484             canvas_->DrawRect(node.contextClipRect_.value());
4485             canvas_->DetachBrush();
4486 #endif
4487         }
4488         // make this node context transparent
4489         canvas_->MultiplyAlpha(0.5);
4490     }
4491     RS_PROCESS_TRACE(isPhone_ || (!isSubThread_ && node.IsMainThreadNode()),
4492         "RSUniRender::Process:[" + node.GetName() + "] " +
4493         node.GetDstRect().ToString() + " Alpha: " + std::to_string(node.GetGlobalAlpha()));
4494     RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode node:%{public}" PRIu64 ",child size:%{public}u,"
4495         "name:%{public}s,OcclusionVisible:%{public}d",
4496         node.GetId(), node.GetChildrenCount(), node.GetName().c_str(), node.GetOcclusionVisible());
4497 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
4498 #ifndef USE_ROSEN_DRAWING
4499 #ifdef NEW_RENDER_CONTEXT
4500     auto grContext = renderEngine_->GetDrawingContext()->GetDrawingContext();
4501 #else
4502     auto grContext = canvas_ != nullptr ? static_cast<GrDirectContext*>(canvas_->recordingContext()) : nullptr;
4503 #endif
4504     RSTagTracker tagTracker(grContext, node.GetId(), RSTagTracker::TAGTYPE::TAG_DRAW_SURFACENODE);
4505     node.SetGrContext(grContext);
4506 #else
4507 #ifdef NEW_RENDER_CONTEXT
4508     Drawing::GPUContext* gpuContext = renderEngine_->GetRenderContext()->GetDrGPUContext();
4509     RSTagTracker tagTracker(gpuContext, node.GetId(), RSTagTracker::TAGTYPE::TAG_DRAW_SURFACENODE);
4510     node.SetDrawingGPUContext(gpuContext);
4511 #else
4512     std::shared_ptr<Drawing::GPUContext> gpuContext = canvas_ != nullptr ? canvas_->GetGPUContext() : nullptr;
4513     RSTagTracker tagTracker(gpuContext.get(), node.GetId(), RSTagTracker::TAGTYPE::TAG_DRAW_SURFACENODE);
4514     node.SetDrawingGPUContext(gpuContext.get());
4515 #endif
4516 #endif
4517 #endif
4518 #ifdef RS_ENABLE_VK
4519     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
4520         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
4521 #ifndef USE_ROSEN_DRAWING
4522         node.SetGrContext(renderEngine_->GetSkContext().get());
4523 #else
4524         node.SetDrawingGPUContext(renderEngine_->GetSkContext().get());
4525 #endif
4526     }
4527 #endif
4528     bool keepFilterCache = false;
4529     if (!CheckIfSurfaceRenderNodeNeedProcess(node, keepFilterCache)) {
4530         if (!keepFilterCache) {
4531             node.UpdateFilterCacheStatusWithVisible(false);
4532         }
4533         ProcessSubSurfaceNodes(node);
4534         return;
4535     } else {
4536         node.UpdateFilterCacheStatusWithVisible(true);
4537     }
4538 #ifdef RS_ENABLE_EGLQUERYSURFACE
4539     if (node.IsMainWindowType()) {
4540         curSurfaceNode_ = node.ReinterpretCastTo<RSSurfaceRenderNode>();
4541         CollectAppNodeForHwc(curSurfaceNode_);
4542     }
4543     // skip clean surface node
4544     if (isOpDropped_ && node.IsAppWindow() &&
4545         !node.SubNodeNeedDraw(node.GetOldDirtyInSurface(), partialRenderType_)) {
4546         RS_PROCESS_TRACE(isPhone_, node.GetName() + " QuickReject Skip");
4547         RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode skip: %{public}s", node.GetName().c_str());
4548         ProcessSubSurfaceNodes(node);
4549         return;
4550     }
4551 #endif
4552     if (!canvas_) {
4553         RS_LOGE("RSUniRenderVisitor::ProcessSurfaceRenderNode, canvas is nullptr");
4554         return;
4555     }
4556     const auto& property = node.GetRenderProperties();
4557     auto geoPtr = (property.GetBoundsGeometry());
4558     if (!geoPtr) {
4559         RS_LOGE("RSUniRenderVisitor::ProcessSurfaceRenderNode node:%{public}" PRIu64 ", get geoPtr failed",
4560             node.GetId());
4561         return;
4562     }
4563 
4564 #ifdef RS_ENABLE_EGLQUERYSURFACE
4565     // when display is in rotation state, occlusion relationship will be ruined,
4566     // hence visibleRegions cannot be used.
4567     if (isOpDropped_ && node.IsAppWindow()) {
4568         const auto& visibleRegions = node.GetVisibleRegion().GetRegionRects();
4569         if (visibleRegions.size() == 1) {
4570 #ifndef USE_ROSEN_DRAWING
4571             canvas_->SetVisibleRect(SkRect::MakeLTRB(
4572                 visibleRegions[0].left_, visibleRegions[0].top_, visibleRegions[0].right_, visibleRegions[0].bottom_));
4573 #else
4574             canvas_->SetVisibleRect(Drawing::Rect(
4575                 visibleRegions[0].left_, visibleRegions[0].top_, visibleRegions[0].right_, visibleRegions[0].bottom_));
4576 #endif
4577         }
4578     }
4579 #endif
4580 
4581     // when surfacenode named "CapsuleWindow", cache the current canvas as SkImage for screen recording
4582     if (!isSecurityDisplay_ && canvas_->GetSurface() != nullptr &&
4583         node.GetName().find(CAPTURE_WINDOW_NAME) != std::string::npos) {
4584 #ifndef USE_ROSEN_DRAWING
4585         resetRotate_ = CheckIfNeedResetRotate();
4586         cacheImgForCapture_ = canvas_->GetSurface()->makeImageSnapshot();
4587 #else
4588         resetRotate_ = CheckIfNeedResetRotate();
4589         cacheImgForCapture_ = canvas_->GetSurface()->GetImageSnapshot();
4590 #endif
4591         auto mirrorNode = curDisplayNode_->GetMirrorSource().lock() ?
4592             curDisplayNode_->GetMirrorSource().lock() : curDisplayNode_;
4593         mirrorNode->SetRootIdOfCaptureWindow(FindInstanceChildOfDisplay(node.GetParent().lock()));
4594     }
4595 
4596     RSAutoCanvasRestore acr(canvas_);
4597     auto bgAntiAliasState = RSPropertiesPainter::GetBgAntiAlias();
4598     if (doAnimate_ && (!ROSEN_EQ(geoPtr->GetScaleX(), 1.f) || !ROSEN_EQ(geoPtr->GetScaleY(), 1.f))) {
4599         // disable background antialias when surfacenode has scale animation
4600         RSPropertiesPainter::SetBgAntiAlias(false);
4601     }
4602 
4603     canvas_->MultiplyAlpha(property.GetAlpha());
4604 
4605     bool isSelfDrawingSurface = node.GetSurfaceNodeType() == RSSurfaceNodeType::SELF_DRAWING_NODE;
4606     // [planning] surfaceNode use frame instead
4607     // This is for SELF_DRAWING_NODE like RosenRenderTexture
4608     // BoundsRect of RosenRenderTexture is the size of video, not the size of the component.
4609     // The size of RosenRenderTexture is the paintRect (always be set to FrameRect) which is not passed to RenderNode
4610     // because RSSurfaceRenderNode is designed only affected by BoundsRect.
4611     // When RosenRenderTexture has child node, child node is layouted
4612     // according to paintRect of RosenRenderTexture, not the BoundsRect.
4613     // So when draw SELF_DRAWING_NODE, we should save canvas
4614     // to avoid child node being layout according to the BoundsRect of RosenRenderTexture.
4615     // Temporarily, we use parent of SELF_DRAWING_NODE which has the same paintRect with its child instead.
4616     // to draw child node of SELF_DRAWING_NODE
4617 #ifndef USE_ROSEN_DRAWING
4618     if (isSelfDrawingSurface && !property.IsSpherizeValid()) {
4619         canvas_->save();
4620     }
4621 
4622     canvas_->concat(geoPtr->GetMatrix());
4623 #else
4624     if (isSelfDrawingSurface && !property.IsSpherizeValid()) {
4625         canvas_->Save();
4626     }
4627 
4628     canvas_->ConcatMatrix(geoPtr->GetMatrix());
4629 #endif
4630     isNodeSingleFrameComposer_ = node.GetNodeIsSingleFrameComposer();
4631     bool isSubNodeOfSurfaceInProcess = isSubNodeOfSurfaceInProcess_;
4632     if (node.IsMainWindowType() || node.IsLeashWindow()) {
4633         isSubNodeOfSurfaceInProcess_ = true;
4634     }
4635     if (property.IsSpherizeValid()) {
4636         DrawSpherize(node);
4637     } else {
4638         if (isSelfDrawingSurface) {
4639             RSUniRenderUtil::FloorTransXYInCanvasMatrix(*canvas_);
4640         }
4641         if (isUIFirst_ && node.GetCacheType() == CacheType::ANIMATE_PROPERTY) {
4642             RSUniRenderUtil::HandleSubThreadNode(node, *canvas_);
4643             if (node.IsMainWindowType() || node.IsLeashWindow()) {
4644                 isSubNodeOfSurfaceInProcess_ = isSubNodeOfSurfaceInProcess;
4645             }
4646             return;
4647         }
4648         node.ProcessRenderBeforeChildren(*canvas_);
4649         if (isUIFirst_ && RSUniRenderUtil::HandleSubThreadNode(node, *canvas_)) {
4650             node.ProcessRenderAfterChildren(*canvas_);
4651             if (node.IsMainWindowType() || node.IsLeashWindow()) {
4652                 isSubNodeOfSurfaceInProcess_ = isSubNodeOfSurfaceInProcess;
4653             }
4654             return;
4655         }
4656         if (node.GetBuffer() != nullptr) {
4657             int rotation = RSUniRenderUtil::GetRotationFromMatrix(node.GetTotalMatrix());
4658             if (node.IsHardwareEnabledType()) {
4659                 // since node has buffer, hwc disabledState could be reset by filter or surface cached
4660                 bool backgroundTransparent =
4661                     static_cast<uint8_t>(node.GetRenderProperties().GetBackgroundColor().GetAlpha()) < UINT8_MAX;
4662                 node.SetHardwareForcedDisabledState(
4663                     (node.IsHardwareForcedDisabledByFilter() || canvas_->GetAlpha() < 1.f ||
4664                     backgroundTransparent || IsRosenWebHardwareDisabled(node, rotation) ||
4665                     RSUniRenderUtil::GetRotationDegreeFromMatrix(node.GetTotalMatrix()) % ROTATION_90 != 0) &&
4666                     (!node.IsHardwareEnabledTopSurface() || node.HasSubNodeShouldPaint()));
4667                 node.SetHardwareDisabledByCache(isUpdateCachedSurface_);
4668                 node.ResetHardwareForcedDisabledBySrcRect();
4669                 RS_OPTIONAL_TRACE_NAME_FMT("hwc debug: IsHardwareEnabledType:%d backgroundTransparent:%d "
4670                     "DisabledByFilter:%d alpha:%.2f RosenWebHardwareDisabled:%d rotation:%d "
4671                     "isUpdateCachedSurface_:%d IsHardwareComposerEnabled:%d node.IsHardwareForcedDisabled():%d",
4672                     node.IsHardwareEnabledType(), backgroundTransparent,
4673                     node.IsHardwareForcedDisabledByFilter(), canvas_->GetAlpha(),
4674                     IsRosenWebHardwareDisabled(node, rotation),
4675                     RSUniRenderUtil::GetRotationDegreeFromMatrix(node.GetTotalMatrix()), isUpdateCachedSurface_,
4676                     IsHardwareComposerEnabled(), node.IsHardwareForcedDisabled());
4677             }
4678             // if this window is in freeze state, disable hardware composer for its child surfaceView
4679             if (IsHardwareComposerEnabled() && node.IsHardwareEnabledType() && (!node.IsHardwareForcedDisabled() ||
4680                 ForceHardwareComposer(node)) && UpdateSrcRectForHwcNode(node)) {
4681 #ifndef USE_ROSEN_DRAWING
4682                 if (!node.IsHardwareEnabledTopSurface()) {
4683                     canvas_->clear(SK_ColorTRANSPARENT);
4684                 }
4685 #else
4686                 if (!node.IsHardwareEnabledTopSurface()) {
4687                     canvas_->Clear(Drawing::Color::COLOR_TRANSPARENT);
4688                 }
4689 #endif
4690                 node.SetGlobalAlpha(canvas_->GetAlpha());
4691                 ParallelRenderEnableHardwareComposer(node);
4692                 RS_LOGD("RSUniRenderVisitor::ProcessSurfaceRenderNode src:%{public}s, dst:%{public}s name:%{public}s"
4693                     " id:%{public}" PRIu64 "", node.GetSrcRect().ToString().c_str(),
4694                     node.GetDstRect().ToString().c_str(), node.GetName().c_str(), node.GetId());
4695             } else {
4696                 node.SetGlobalAlpha(1.0f);
4697                 auto params = RSUniRenderUtil::CreateBufferDrawParam(node, false, threadIndex_);
4698                 params.targetColorGamut = newColorSpace_;
4699 #ifdef USE_VIDEO_PROCESSING_ENGINE
4700                 auto screenManager = CreateOrGetScreenManager();
4701                 auto ancestor = node.GetAncestorDisplayNode().lock()->ReinterpretCastTo<RSDisplayRenderNode>();
4702                 params.screenBrightnessNits = screenManager->GetScreenBrightnessNits(ancestor->GetScreenId());
4703 #endif
4704                 auto bgColor = property.GetBackgroundColor();
4705                 if ((node.GetSelfDrawingNodeType() != SelfDrawingNodeType::VIDEO) &&
4706                     (bgColor != RgbPalette::Transparent())) {
4707                     auto bounds = RSPropertiesPainter::Rect2DrawingRect(property.GetBoundsRect());
4708                     Drawing::SaveLayerOps layerOps(&bounds, nullptr);
4709                     canvas_->SaveLayer(layerOps);
4710                     canvas_->SaveAlpha();
4711                     canvas_->SetAlpha(1.0f);
4712                     Drawing::Brush brush;
4713                     brush.SetColor(Drawing::Color(bgColor.AsArgbInt()));
4714                     canvas_->AttachBrush(brush);
4715                     canvas_->DrawRoundRect(RSPropertiesPainter::RRect2DrawingRRect(property.GetRRect()));
4716                     canvas_->DetachBrush();
4717                     renderEngine_->DrawSurfaceNodeWithParams(*canvas_, node, params);
4718                     canvas_->RestoreAlpha();
4719                     canvas_->Restore();
4720                 } else {
4721                     renderEngine_->DrawSurfaceNodeWithParams(*canvas_, node, params);
4722                 }
4723             }
4724         }
4725 
4726         if (isSelfDrawingSurface) {
4727 #ifndef USE_ROSEN_DRAWING
4728             canvas_->restore();
4729 #else
4730             canvas_->Restore();
4731 #endif
4732         }
4733 
4734         if (node.IsAppWindow()) {
4735             if (!node.IsNotifyUIBufferAvailable() && IsFirstFrameReadyToDraw(node)) {
4736                 node.NotifyUIBufferAvailable();
4737             }
4738             CheckAndSetNodeCacheType(node);
4739             DrawChildRenderNode(node);
4740         } else if (node.IsScbScreen() && !node.IsNotifyUIBufferAvailable() && IsFirstFrameReadyToDraw(node)) {
4741             node.NotifyUIBufferAvailable();
4742             ProcessChildren(node);
4743         } else {
4744             ProcessChildren(node);
4745         }
4746         node.ProcessRenderAfterChildren(*canvas_);
4747     }
4748 
4749     RSPropertiesPainter::SetBgAntiAlias(bgAntiAliasState);
4750     if (node.IsAppWindow()) {
4751 #ifndef USE_ROSEN_DRAWING
4752         canvas_->SetVisibleRect(SkRect::MakeLTRB(0, 0, 0, 0));
4753 #else
4754         canvas_->SetVisibleRect(Drawing::Rect(0, 0, 0, 0));
4755 #endif
4756 
4757         // count processed canvas node
4758         RS_TRACE_NAME_FMT("%s PureContainerNode/ProcessedNodes: %u/%u", node.GetName().c_str(),
4759             processedPureContainerNode_, processedCanvasNodeInCurrentSurface_);
4760         processedCanvasNodeInCurrentSurface_ = 0; // reset
4761         processedPureContainerNode_ = 0;
4762     }
4763     if (node.IsMainWindowType() || node.IsLeashWindow()) {
4764         isSubNodeOfSurfaceInProcess_ = isSubNodeOfSurfaceInProcess;
4765         // release full children list used by sub thread
4766     }
4767 }
4768 
4769 void RSUniRenderVisitor::ProcessProxyRenderNode(RSProxyRenderNode& node)
4770 {
4771     if (RSSystemProperties::GetProxyNodeDebugEnabled() && node.contextClipRect_.has_value() &&
4772         node.target_.lock() != nullptr) {
4773         // draw transparent green rect to indicate clip area of proxy node
4774 #ifndef USE_ROSEN_DRAWING
4775         SkPaint paint;
4776         paint.setARGB(0x80, 0, 0xFF, 0); // transparent green
4777         canvas_->drawRect(node.contextClipRect_.value(), paint);
4778 #else
4779         Drawing::Brush brush;
4780         brush.SetARGB(0x80, 0, 0xFF, 0); // transparent green
4781         canvas_->AttachBrush(brush);
4782         canvas_->DrawRect(node.contextClipRect_.value());
4783         canvas_->DetachBrush();
4784 #endif
4785     }
4786     ProcessChildren(node);
4787 }
4788 
4789 void RSUniRenderVisitor::ProcessRootRenderNode(RSRootRenderNode& node)
4790 {
4791     RS_LOGD("RSUniRenderVisitor::ProcessRootRenderNode node: %{public}" PRIu64 ", child size:%{public}u", node.GetId(),
4792         node.GetChildrenCount());
4793     if (!node.ShouldPaint()) {
4794         RS_LOGD("RSUniRenderVisitor::ProcessRootRenderNode, no need process");
4795         return;
4796     }
4797     if (!canvas_) {
4798         RS_LOGE("RSUniRenderVisitor::ProcessRootRenderNode, canvas is nullptr");
4799         return;
4800     }
4801 #ifndef USE_ROSEN_DRAWING
4802     int saveCount = canvas_->save();
4803     ProcessCanvasRenderNode(node);
4804     canvas_->restoreToCount(saveCount);
4805 #else
4806     int saveCount = canvas_->Save();
4807     ProcessCanvasRenderNode(node);
4808     canvas_->RestoreToCount(saveCount);
4809 #endif
4810 }
4811 
4812 bool RSUniRenderVisitor::GenerateNodeContentCache(RSRenderNode& node)
4813 {
4814     // Node cannot have cache.
4815     uint32_t cacheRenderNodeMapCnt;
4816     if (node.GetDrawingCacheType() == RSDrawingCacheType::DISABLED_CACHE) {
4817         {
4818             std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4819             cacheRenderNodeMapCnt = cacheRenderNodeMap.count(node.GetId());
4820         }
4821         if (cacheRenderNodeMapCnt > 0) {
4822             node.SetCacheType(CacheType::NONE);
4823             RSUniRenderUtil::ClearCacheSurface(node, threadIndex_);
4824             {
4825                 std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4826                 cacheRenderNodeMap.erase(node.GetId());
4827             }
4828             {
4829                 std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
4830                 groupedTransitionNodes.erase(node.GetId());
4831             }
4832         }
4833         return false;
4834     }
4835 
4836     // The node goes down the tree to clear the cache.
4837     {
4838         std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4839         cacheRenderNodeMapCnt = cacheRenderNodeMap.count(node.GetId());
4840     }
4841     if (node.GetCacheType() == CacheType::NONE && cacheRenderNodeMapCnt > 0) {
4842         {
4843             std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4844             cacheRenderNodeMap.erase(node.GetId());
4845         }
4846         {
4847             std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
4848             groupedTransitionNodes.erase(node.GetId());
4849         }
4850     }
4851     return true;
4852 }
4853 
4854 void RSUniRenderVisitor::ClearRenderGroupCache()
4855 {
4856     std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4857     cacheRenderNodeMap.clear();
4858 }
4859 
4860 bool RSUniRenderVisitor::InitNodeCache(RSRenderNode& node)
4861 {
4862     if (node.GetDrawingCacheType() == RSDrawingCacheType::FORCED_CACHE ||
4863         node.GetDrawingCacheType() == RSDrawingCacheType::TARGETED_CACHE) {
4864         uint32_t cacheRenderNodeMapCnt;
4865         {
4866             std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4867             cacheRenderNodeMapCnt = cacheRenderNodeMap.count(node.GetId());
4868         }
4869         if (cacheRenderNodeMapCnt == 0 || (!node.IsStaticCached() && node.NeedInitCacheCompletedSurface())) {
4870             RenderParam val { node.shared_from_this(), canvas_->GetCanvasStatus() };
4871             curGroupedNodes_.push(val);
4872             {
4873                 std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
4874                 groupedTransitionNodes[node.GetId()] = { val, {} };
4875             }
4876             node.SetCacheType(CacheType::CONTENT);
4877             RSUniRenderUtil::ClearCacheSurface(node, threadIndex_);
4878             if (UpdateCacheSurface(node)) {
4879                 node.UpdateCompletedCacheSurface();
4880                 ChangeCacheRenderNodeMap(node);
4881                 cacheReuseTimes = 0;
4882                 node.ResetDrawingCacheNeedUpdate();
4883             }
4884             curGroupedNodes_.pop();
4885             return true;
4886         }
4887     }
4888     return false;
4889 }
4890 
4891 void RSUniRenderVisitor::ChangeCacheRenderNodeMap(RSRenderNode& node, const uint32_t count)
4892 {
4893     std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4894     cacheRenderNodeMap[node.GetId()] = count;
4895 }
4896 
4897 void RSUniRenderVisitor::UpdateCacheRenderNodeMapWithBlur(RSRenderNode& node)
4898 {
4899     curCacheFilterRects_.push(allCacheFilterRects_[node.GetId()]);
4900     auto canvasType = canvas_->GetCacheType();
4901     canvas_->SetCacheType(RSPaintFilterCanvas::CacheType::OFFSCREEN);
4902     UpdateCacheRenderNodeMap(node);
4903     canvas_->SetCacheType(canvasType);
4904     RS_TRACE_NAME_FMT("Draw cache with blur [%llu]", node.GetId());
4905 #ifndef USE_ROSEN_DRAWING
4906     SkAutoCanvasRestore arc(canvas_.get(), true);
4907 #else
4908     Drawing::AutoCanvasRestore arc(*canvas_, true);
4909 #endif
4910     auto nodeType = node.GetCacheType();
4911     node.SetCacheType(CacheType::NONE);
4912     bool isOpDropped = isOpDropped_;
4913     isOpDropped_ = false;
4914     // Label the ProcessChildren in drawCacheWithBlur
4915     drawCacheWithBlur_ = true;
4916     DrawChildRenderNode(node);
4917     isOpDropped_ = isOpDropped;
4918     drawCacheWithBlur_ = false;
4919     node.SetCacheType(nodeType);
4920     curCacheFilterRects_.pop();
4921 }
4922 
4923 void RSUniRenderVisitor::UpdateCacheRenderNodeMap(RSRenderNode& node)
4924 {
4925     if (InitNodeCache(node)) {
4926         RS_OPTIONAL_TRACE_NAME_FMT("RSUniRenderVisitor::UpdateCacheRenderNodeMap, generate the node cache for the first"
4927             "time, NodeId: %" PRIu64 " ", node.GetId());
4928         return;
4929     }
4930     uint32_t updateTimes = 0;
4931     if (node.GetDrawingCacheType() == RSDrawingCacheType::FORCED_CACHE) {
4932         // Regardless of the number of consecutive refreshes, the current cache is forced to be updated.
4933         if (node.GetDrawingCacheChanged()) {
4934             RenderParam val { node.shared_from_this(), canvas_->GetCanvasStatus() };
4935             curGroupedNodes_.push(val);
4936             {
4937                 std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
4938                 groupedTransitionNodes[node.GetId()] = { val, {} };
4939             }
4940             {
4941                 std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4942                 updateTimes = cacheRenderNodeMap[node.GetId()] + 1;
4943             }
4944             node.SetCacheType(CacheType::CONTENT);
4945             if (UpdateCacheSurface(node)) {
4946                 node.UpdateCompletedCacheSurface();
4947                 ChangeCacheRenderNodeMap(node, updateTimes);
4948                 cacheReuseTimes = 0;
4949                 node.ResetDrawingCacheNeedUpdate();
4950             }
4951             curGroupedNodes_.pop();
4952             return;
4953         }
4954     }
4955     if (node.GetDrawingCacheType() == RSDrawingCacheType::TARGETED_CACHE) {
4956         // If the number of consecutive refreshes exceeds CACHE_MAX_UPDATE_TIME times, the cache is cleaned,
4957         // otherwise the cache is updated.
4958         if (node.GetDrawingCacheChanged()) {
4959             {
4960                 std::lock_guard<std::mutex> lock(cacheRenderNodeMapMutex);
4961                 updateTimes = cacheRenderNodeMap[node.GetId()] + 1;
4962             }
4963             if (updateTimes >= CACHE_MAX_UPDATE_TIME) {
4964                 node.SetCacheType(CacheType::NONE);
4965                 node.MarkNodeGroup(RSRenderNode::GROUPED_BY_UI, false, false);
4966                 node.MarkNodeGroup(RSRenderNode::GROUPED_BY_ANIM, false, false);
4967                 RSUniRenderUtil::ClearCacheSurface(node, threadIndex_);
4968                 cacheRenderNodeMap.erase(node.GetId());
4969                 groupedTransitionNodes.erase(node.GetId());
4970                 cacheReuseTimes = 0;
4971                 return;
4972             }
4973             RenderParam val { node.shared_from_this(), canvas_->GetCanvasStatus() };
4974             curGroupedNodes_.push(val);
4975             {
4976                 std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
4977                 groupedTransitionNodes[node.GetId()] = { val, {} };
4978             }
4979             node.SetCacheType(CacheType::CONTENT);
4980             if (UpdateCacheSurface(node)) {
4981                 node.UpdateCompletedCacheSurface();
4982                 ChangeCacheRenderNodeMap(node, updateTimes);
4983                 cacheReuseTimes = 0;
4984                 node.ResetDrawingCacheNeedUpdate();
4985             }
4986             curGroupedNodes_.pop();
4987             return;
4988         }
4989     }
4990     // The cache is not refreshed continuously.
4991     ChangeCacheRenderNodeMap(node);
4992     cacheReuseTimes++;
4993     RS_OPTIONAL_TRACE_NAME("RSUniRenderVisitor::UpdateCacheRenderNodeMap ,NodeId: " + std::to_string(node.GetId()) +
4994         " ,CacheRenderNodeMapCnt: " + std::to_string(cacheReuseTimes));
4995 }
4996 
4997 void RSUniRenderVisitor::ProcessCanvasRenderNode(RSCanvasRenderNode& node)
4998 {
4999     processedCanvasNodeInCurrentSurface_++;
5000     if (!node.ShouldPaint() ||
5001 #ifndef USE_ROSEN_DRAWING
5002         (canvas_ && canvas_->getDeviceClipBounds().isEmpty() && hardwareEnabledNodes_.empty())) {
5003 #else
5004         (canvas_ && canvas_->GetDeviceClipBounds().IsEmpty() && hardwareEnabledNodes_.empty())) {
5005 #endif
5006         return;
5007     }
5008     auto geoPtr = (node.GetRenderProperties().GetBoundsGeometry());
5009     if (isSkipCanvasNodeOutOfScreen_ && !isSubNodeOfSurfaceInProcess_ && !node.HasSubSurface() &&
5010         geoPtr && IsOutOfScreenRegion(geoPtr->GetAbsRect()) && !isSubThread_) {
5011         return;
5012     }
5013     node.MarkNodeSingleFrameComposer(isNodeSingleFrameComposer_);
5014 #ifdef RS_ENABLE_EGLQUERYSURFACE
5015     if ((isOpDropped_ && (curSurfaceNode_ != nullptr)) || isCanvasNodeSkipDfxEnabled_) {
5016         // If all the child nodes have drawing areas that do not exceed the current node, then current node
5017         // can be directly skipped if not intersect with any dirtyregion.
5018         // Otherwise, its childrenRect_ should be considered.
5019         RectI dirtyRect = node.HasChildrenOutOfRect() ?
5020             node.GetOldDirtyInSurface().JoinRect(node.GetChildrenRect()) : node.GetOldDirtyInSurface();
5021         if (isSubNodeOfSurfaceInProcess_ && !node.IsAncestorDirty() &&
5022             !curSurfaceNode_->SubNodeNeedDraw(dirtyRect, partialRenderType_) && !node.IsParentLeashWindow() &&
5023             !node.IsParentScbScreen()) {
5024             bool subSurfaceNeedDraw = false;
5025             if (isSubSurfaceEnabled_) {
5026                 subSurfaceNeedDraw = node.SubSurfaceNodeNeedDraw(partialRenderType_);
5027             }
5028             if (!subSurfaceNeedDraw) {
5029                 if (isCanvasNodeSkipDfxEnabled_) {
5030                     curSurfaceNode_->GetDirtyManager()->UpdateDirtyRegionInfoForDfx(
5031                         node.GetId(), node.GetType(), DirtyRegionType::CANVAS_NODE_SKIP_RECT, dirtyRect);
5032                 } else {
5033                     return;
5034                 }
5035             }
5036         }
5037     }
5038 #endif
5039     if (!canvas_) {
5040         RS_LOGE("RSUniRenderVisitor::ProcessCanvasRenderNode, canvas is nullptr");
5041         return;
5042     }
5043 #if defined(RS_ENABLE_DRIVEN_RENDER)
5044     // clip hole for driven render
5045     if (drivenInfo_ && !drivenInfo_->prepareInfo.hasInvalidScene &&
5046         drivenInfo_->currDrivenRenderMode != DrivenUniRenderMode::RENDER_WITH_NORMAL) {
5047         // skip render driven node sub tree
5048         if (RSDrivenRenderManager::GetInstance().ClipHoleForDrivenNode(*canvas_, node)) {
5049             return;
5050         }
5051     }
5052 #endif
5053     // in case preparation'update is skipped
5054 #ifndef USE_ROSEN_DRAWING
5055     canvas_->save();
5056 #else
5057     canvas_->Save();
5058 #endif
5059     if (node.GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE) {
5060         RSUniRenderUtil::FloorTransXYInCanvasMatrix(*canvas_);
5061     }
5062 
5063     if (node.GetSharedTransitionParam().has_value()) {
5064         // enable cache for sharingTrans on Desktop
5065         auto mainThread = RSMainThread::Instance();
5066         std::string bundleNameFocusNow = mainThread->GetFocusAppBundleName();
5067         if (bundleNameFocusNow == BIGFLODER_BUNDLE_NAME) {
5068             isTextNeedCached_ = true;
5069         }
5070         // draw self and children in sandbox which will not be affected by parent's transition
5071         const auto& sandboxMatrix = node.GetRenderProperties().GetSandBoxMatrix();
5072         if (sandboxMatrix) {
5073 #ifndef USE_ROSEN_DRAWING
5074             canvas_->setMatrix(*sandboxMatrix);
5075 #else
5076             canvas_->SetMatrix(*sandboxMatrix);
5077 #endif
5078         }
5079     }
5080     if (node.GetRenderProperties().GetUseEffect() && RSSystemParameters::GetDrawingEffectRegionEnabledDfx()) {
5081         const auto& effectData = canvas_->GetEffectData();
5082         auto geoPtr = node.GetRenderProperties().GetBoundsGeometry();
5083         if (geoPtr != nullptr) {
5084             if ((effectData == nullptr || effectData->cachedImage_ == nullptr) ||
5085                 !RSSystemProperties::GetEffectMergeEnabled()) {
5086                 nodesUseEffectFallbackForDfx_.emplace_back(geoPtr->GetAbsRect());
5087             } else {
5088                 nodesUseEffectForDfx_.emplace_back(geoPtr->GetAbsRect());
5089             }
5090         }
5091     }
5092     const auto& property = node.GetRenderProperties();
5093     if (property.IsSpherizeValid()) {
5094         isTextNeedCached_ = false;
5095         DrawSpherize(node);
5096         return;
5097     }
5098     auto preType = canvas_->GetCacheType();
5099     if (isTextNeedCached_) {
5100         RS_OPTIONAL_TRACE_NAME_FMT("BigFloderCacheEnabled[%s]", BIGFLODER_BUNDLE_NAME.c_str());
5101         canvas_->SetCacheType(RSPaintFilterCanvas::CacheType::ENABLED);
5102     }
5103     if (auto drawingNode = node.ReinterpretCastTo<RSCanvasDrawingRenderNode>()) {
5104         std::lock_guard<std::mutex> lock(drawingMutex_);
5105 #ifndef USE_ROSEN_DRAWING
5106         auto clearFunc = [id = threadIndex_](sk_sp<SkSurface> surface) {
5107             // The second param is null, 0 is an invalid value.
5108             RSUniRenderUtil::ClearNodeCacheSurface(std::move(surface), nullptr, id, 0);
5109         };
5110 #else
5111         auto clearFunc = [id = threadIndex_](std::shared_ptr<Drawing::Surface> surface) {
5112             // The second param is null, 0 is an invalid value.
5113             RSUniRenderUtil::ClearNodeCacheSurface(std::move(surface), nullptr, id, 0);
5114         };
5115 #endif
5116         drawingNode->SetSurfaceClearFunc({ threadIndex_, clearFunc });
5117     }
5118     CheckAndSetNodeCacheType(node);
5119     DrawChildCanvasRenderNode(node);
5120     notRunCheckAndSetNodeCacheType_ = false;
5121     isTextNeedCached_ = false;
5122     canvas_->SetCacheType(preType);
5123 #ifndef USE_ROSEN_DRAWING
5124     canvas_->restore();
5125 #else
5126     canvas_->Restore();
5127 #endif
5128 }
5129 
5130 void RSUniRenderVisitor::ProcessEffectRenderNode(RSEffectRenderNode& node)
5131 {
5132     if (!node.ShouldPaint()) {
5133         RS_LOGD("RSUniRenderVisitor::ProcessEffectRenderNode, no need process");
5134         return;
5135     }
5136     if (!canvas_) {
5137         RS_LOGE("RSUniRenderVisitor::ProcessEffectRenderNode, canvas is nullptr");
5138         return;
5139     }
5140     nodesUseEffectForDfx_.clear();
5141     nodesUseEffectFallbackForDfx_.clear();
5142 #ifndef USE_ROSEN_DRAWING
5143     SkAutoCanvasRestore acr(canvas_.get(), true);
5144 #else
5145     Drawing::AutoCanvasRestore acr(*canvas_.get(), true);
5146 #endif
5147     node.ProcessRenderBeforeChildren(*canvas_);
5148     ProcessChildren(node);
5149     node.ProcessRenderAfterChildren(*canvas_);
5150     effectNodeMapForDfx_[node.GetId()].first = nodesUseEffectForDfx_;
5151     effectNodeMapForDfx_[node.GetId()].second = nodesUseEffectFallbackForDfx_;
5152 }
5153 
5154 void RSUniRenderVisitor::PrepareOffscreenRender(RSRenderNode& node)
5155 {
5156     RS_TRACE_NAME("PrepareOffscreenRender");
5157     // cleanup
5158     canvasBackup_ = nullptr;
5159     offscreenSurface_ = nullptr;
5160     // check offscreen size and hardware renderer
5161     int32_t offscreenWidth = node.GetRenderProperties().GetFrameWidth();
5162     int32_t offscreenHeight = node.GetRenderProperties().GetFrameHeight();
5163     if (offscreenWidth <= 0 || offscreenHeight <= 0) {
5164         RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, offscreenWidth or offscreenHeight is invalid");
5165         return;
5166     }
5167 #ifndef USE_ROSEN_DRAWING
5168     if (canvas_->GetSurface() == nullptr) {
5169         canvas_->clipRect(SkRect::MakeWH(offscreenWidth, offscreenHeight));
5170         RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, current surface is nullptr (software renderer?)");
5171         return;
5172     }
5173     // create offscreen surface and canvas
5174     offscreenSurface_ = canvas_->GetSurface()->makeSurface(offscreenWidth, offscreenHeight);
5175     if (offscreenSurface_ == nullptr) {
5176         RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, offscreenSurface is nullptr");
5177         canvas_->clipRect(SkRect::MakeWH(offscreenWidth, offscreenHeight));
5178         return;
5179     }
5180     auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface_.get());
5181 
5182     // copy current canvas properties into offscreen canvas
5183     offscreenCanvas->CopyConfiguration(*canvas_);
5184 
5185     // backup current canvas and replace with offscreen canvas
5186     canvasBackup_ = std::exchange(canvas_, offscreenCanvas);
5187 #else
5188     if (canvas_->GetSurface() == nullptr) {
5189         canvas_->ClipRect(Drawing::Rect(0, 0, offscreenWidth, offscreenHeight), Drawing::ClipOp::INTERSECT, false);
5190         RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, current surface is nullptr (software renderer?)");
5191         return;
5192     }
5193     // create offscreen surface and canvas
5194     offscreenSurface_ = canvas_->GetSurface()->MakeSurface(offscreenWidth, offscreenHeight);
5195     if (offscreenSurface_ == nullptr) {
5196         RS_LOGD("RSUniRenderVisitor::PrepareOffscreenRender, offscreenSurface is nullptr");
5197         canvas_->ClipRect(Drawing::Rect(0, 0, offscreenWidth, offscreenHeight), Drawing::ClipOp::INTERSECT, false);
5198         return;
5199     }
5200     auto offscreenCanvas = std::make_shared<RSPaintFilterCanvas>(offscreenSurface_.get());
5201 
5202     // copy current canvas properties into offscreen canvas
5203     offscreenCanvas->CopyConfiguration(*canvas_);
5204 
5205     // backup current canvas and replace with offscreen canvas
5206     canvasBackup_ = std::exchange(canvas_, offscreenCanvas);
5207 #endif
5208 }
5209 
5210 void RSUniRenderVisitor::FinishOffscreenRender(bool isMirror)
5211 {
5212     if (canvasBackup_ == nullptr) {
5213         RS_LOGD("RSUniRenderVisitor::FinishOffscreenRender, canvasBackup_ is nullptr");
5214         return;
5215     }
5216     RS_TRACE_NAME("RSUniRenderVisitor::OffscreenRender finish");
5217     // flush offscreen canvas, maybe unnecessary
5218 #ifndef USE_ROSEN_DRAWING
5219     if (!isMirror) {
5220         canvas_->flush();
5221     }
5222     // draw offscreen surface to current canvas
5223     SkPaint paint;
5224     paint.setAntiAlias(true);
5225 #ifdef NEW_SKIA
5226     canvasBackup_->drawImage(offscreenSurface_->makeImageSnapshot(), 0, 0, SkSamplingOptions(), &paint);
5227 #else
5228     canvasBackup_->drawImage(offscreenSurface_->makeImageSnapshot(), 0, 0, &paint);
5229 #endif
5230 #else
5231     if (!isMirror) {
5232         canvas_->Flush();
5233     }
5234     // draw offscreen surface to current canvas
5235     Drawing::Brush paint;
5236     paint.SetAntiAlias(true);
5237     canvasBackup_->AttachBrush(paint);
5238     Drawing::SamplingOptions sampling =
5239         Drawing::SamplingOptions(Drawing::FilterMode::NEAREST, Drawing::MipmapMode::NEAREST);
5240     canvasBackup_->DrawImage(*offscreenSurface_->GetImageSnapshot().get(), 0, 0, sampling);
5241     canvasBackup_->DetachBrush();
5242 #endif
5243     // restore current canvas and cleanup
5244     offscreenSurface_ = nullptr;
5245     canvas_ = std::move(canvasBackup_);
5246 }
5247 
5248 bool RSUniRenderVisitor::AdaptiveSubRenderThreadMode(bool doParallel)
5249 {
5250 #if defined(RS_ENABLE_PARALLEL_RENDER) && (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK))
5251     doParallel = (doParallel && (parallelRenderType_ != ParallelRenderingType::DISABLE));
5252     if (!doParallel) {
5253         return doParallel;
5254     }
5255     auto parallelRenderManager = RSParallelRenderManager::Instance();
5256     switch (parallelRenderType_) {
5257         case ParallelRenderingType::AUTO:
5258             parallelRenderManager->SetParallelMode(doParallel);
5259             break;
5260         case ParallelRenderingType::DISABLE:
5261             parallelRenderManager->SetParallelMode(false);
5262             break;
5263         case ParallelRenderingType::ENABLE:
5264             parallelRenderManager->SetParallelMode(true);
5265             break;
5266     }
5267     return doParallel;
5268 #else
5269     return false;
5270 #endif
5271 }
5272 void RSUniRenderVisitor::ParallelRenderEnableHardwareComposer(RSSurfaceRenderNode& node)
5273 {
5274 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined (RS_ENABLE_GL)
5275     if (RSSystemProperties::GetGpuApiType() == GpuApiType::OPENGL) {
5276         if (isParallel_ && !isUIFirst_) {
5277             const auto& property = node.GetRenderProperties();
5278             auto dstRect = node.GetDstRect();
5279             RectF clipRect = {dstRect.GetLeft(), dstRect.GetTop(), dstRect.GetWidth(), dstRect.GetHeight()};
5280             RSParallelRenderManager::Instance()->AddSelfDrawingSurface(parallelRenderVisitorIndex_,
5281                 property.GetCornerRadius().IsZero(), clipRect, property.GetCornerRadius());
5282         }
5283     }
5284 #endif
5285 }
5286 
5287 void RSUniRenderVisitor::ClosePartialRenderWhenAnimatingWindows(std::shared_ptr<RSDisplayRenderNode>& node)
5288 {
5289     if (!doAnimate_) {
5290         return;
5291     }
5292     if (appWindowNum_ > PHONE_MAX_APP_WINDOW_NUM) {
5293         node->GetDirtyManager()->MergeSurfaceRect();
5294     } else {
5295         isPartialRenderEnabled_ = false;
5296         isOpDropped_ = false;
5297         RS_TRACE_NAME("ClosePartialRender 0 Window Animation");
5298     }
5299 }
5300 
5301 void RSUniRenderVisitor::SetHardwareEnabledNodes(
5302     const std::vector<std::shared_ptr<RSSurfaceRenderNode>>& hardwareEnabledNodes)
5303 {
5304     hardwareEnabledNodes_ = hardwareEnabledNodes;
5305 }
5306 
5307 bool RSUniRenderVisitor::DoDirectComposition(std::shared_ptr<RSBaseRenderNode> rootNode)
5308 {
5309     auto children = rootNode->GetChildren();
5310     if (!IsHardwareComposerEnabled() || children->empty()) {
5311         RS_LOGD("RSUniRenderVisitor::DoDirectComposition HardwareComposer disabled");
5312         return false;
5313     }
5314     RS_TRACE_NAME("DoDirectComposition");
5315     auto& child = children->front();
5316     if (child == nullptr || !child->IsInstanceOf<RSDisplayRenderNode>()) {
5317         RS_LOGE("RSUniRenderVisitor::DoDirectComposition child type not match");
5318         return false;
5319     }
5320     auto displayNode = child->ReinterpretCastTo<RSDisplayRenderNode>();
5321     if (!displayNode ||
5322         displayNode->GetCompositeType() != RSDisplayRenderNode::CompositeType::UNI_RENDER_COMPOSITE) {
5323         RS_LOGE("RSUniRenderVisitor::DoDirectComposition displayNode state error");
5324         return false;
5325     }
5326     sptr<RSScreenManager> screenManager = CreateOrGetScreenManager();
5327     screenInfo_ = screenManager->QueryScreenInfo(displayNode->GetScreenId());
5328     if (screenInfo_.state != ScreenState::HDI_OUTPUT_ENABLE) {
5329         RS_LOGE("RSUniRenderVisitor::DoDirectComposition: ScreenState error!");
5330         return false;
5331     }
5332     processor_ = RSProcessorFactory::CreateProcessor(displayNode->GetCompositeType());
5333     if (processor_ == nullptr || renderEngine_ == nullptr) {
5334         RS_LOGE("RSUniRenderVisitor::DoDirectComposition: RSProcessor or renderEngine is null!");
5335         return false;
5336     }
5337 
5338     if (!processor_->Init(*displayNode, displayNode->GetDisplayOffsetX(), displayNode->GetDisplayOffsetY(),
5339         INVALID_SCREEN_ID, renderEngine_)) {
5340         RS_LOGE("RSUniRenderVisitor::DoDirectComposition: processor init failed!");
5341         return false;
5342     }
5343 
5344     if (!RSMainThread::Instance()->WaitHardwareThreadTaskExcute()) {
5345         RS_LOGW("RSUniRenderVisitor::DoDirectComposition: hardwareThread task has too many to excute");
5346     }
5347     if (!RSMainThread::Instance()->CheckIsHardwareEnabledBufferUpdated()) {
5348         for (auto& surfaceNode: hardwareEnabledNodes_) {
5349             if (!surfaceNode->IsHardwareForcedDisabled()) {
5350                 surfaceNode->MarkCurrentFrameHardwareEnabled();
5351             }
5352         }
5353         RS_TRACE_NAME("DoDirectComposition skip commit");
5354         return true;
5355     }
5356     processor_->ProcessDisplaySurface(*displayNode);
5357     for (auto& node: hardwareEnabledNodes_) {
5358         if (!node->IsHardwareForcedDisabled()) {
5359             processor_->ProcessSurface(*node);
5360         }
5361     }
5362     DoScreenRcdTask(processor_, rcdInfo_, screenInfo_);
5363     processor_->PostProcess(displayNode.get());
5364     RS_LOGD("RSUniRenderVisitor::DoDirectComposition end");
5365     return true;
5366 }
5367 
5368 void RSUniRenderVisitor::DrawWatermarkIfNeed(RSDisplayRenderNode& node, bool isMirror)
5369 {
5370     if (RSMainThread::Instance()->GetWatermarkFlag()) {
5371         auto screenManager = CreateOrGetScreenManager();
5372         auto mainScreenInfo = screenManager->QueryScreenInfo(node.GetScreenId());
5373         auto mainWidth = static_cast<float>(mainScreenInfo.width);
5374         auto mainHeight = static_cast<float>(mainScreenInfo.height);
5375         if (RSSystemProperties::IsFoldScreenFlag() && node.GetScreenId() == 0 && isMirror) {
5376             std::swap(mainWidth, mainHeight);
5377         }
5378 #ifndef USE_ROSEN_DRAWING
5379         sk_sp<SkImage> skImage = RSMainThread::Instance()->GetWatermarkImg();
5380         if (!skImage) {
5381             RS_LOGE("RSUniRenderVisitor::DrawWatermarkIfNeed: no image!");
5382             return;
5383         }
5384         SkPaint rectPaint;
5385         auto skSrcRect = SkRect::MakeWH(skImage->width(), skImage->height());
5386         auto skDstRect = SkRect::MakeWH(mainWidth, mainHeight);
5387 #ifdef NEW_SKIA
5388         canvas_->drawImageRect(
5389             skImage, skSrcRect, skDstRect, SkSamplingOptions(), &rectPaint, SkCanvas::kStrict_SrcRectConstraint);
5390 #else
5391         canvas_->drawImageRect(skImage, skSrcRect, skDstRect, &rectPaint);
5392 #endif
5393 #else
5394         std::shared_ptr<Drawing::Image> drImage = RSMainThread::Instance()->GetWatermarkImg();
5395         if (drImage == nullptr) {
5396             return;
5397         }
5398         Drawing::Brush rectPaint;
5399         canvas_->AttachBrush(rectPaint);
5400         auto srcRect = Drawing::Rect(0, 0, drImage->GetWidth(), drImage->GetHeight());
5401         auto dstRect = Drawing::Rect(0, 0, mainWidth, mainHeight);
5402         canvas_->DrawImageRect(*drImage, srcRect, dstRect, Drawing::SamplingOptions(),
5403             Drawing::SrcRectConstraint::STRICT_SRC_RECT_CONSTRAINT);
5404         canvas_->DetachBrush();
5405 #endif
5406     }
5407 }
5408 
5409 void RSUniRenderVisitor::SetAppWindowNum(uint32_t num)
5410 {
5411     appWindowNum_ = num;
5412 }
5413 
5414 bool RSUniRenderVisitor::ParallelComposition(const std::shared_ptr<RSBaseRenderNode> rootNode)
5415 {
5416 #if defined(RS_ENABLE_PARALLEL_RENDER) && defined (RS_ENABLE_GL)
5417     if (RSSystemProperties::GetGpuApiType() == GpuApiType::VULKAN ||
5418         RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
5419         return false;
5420     }
5421     auto parallelRenderManager = RSParallelRenderManager::Instance();
5422     parallelRenderManager->SetParallelMode(true);
5423     if (parallelRenderManager->GetParallelMode()) {
5424         parallelRenderManager->PackParallelCompositionTask(shared_from_this(), rootNode);
5425         parallelRenderManager->LoadBalanceAndNotify(TaskType::COMPOSITION_TASK);
5426         parallelRenderManager->WaitCompositionEnd();
5427     } else {
5428         return false;
5429     }
5430     return true;
5431 #else
5432     return false;
5433 #endif
5434 }
5435 
5436 void RSUniRenderVisitor::PrepareSharedTransitionNode(RSBaseRenderNode& node)
5437 {
5438     // set flag for surface node whose children contain shared transition node
5439     if (curSurfaceNode_) {
5440         SetHasSharedTransitionNode(*curSurfaceNode_, true);
5441     }
5442 
5443     // Sanity check done by caller, transitionParam should always has value.
5444     auto& transitionParam = node.GetSharedTransitionParam();
5445 
5446     auto pairedNode = transitionParam->second.lock();
5447     if (pairedNode == nullptr) {
5448         // paired node is already destroyed, clear transition param and prepare directly
5449         node.SetSharedTransitionParam(std::nullopt);
5450         return;
5451     }
5452 
5453     auto& pairedParam = pairedNode->GetSharedTransitionParam();
5454     if (!pairedParam.has_value() || pairedParam->first != transitionParam->first) {
5455         // if 1. paired node is not a transition node or 2. paired node is not paired with this node, then clear
5456         // transition param and prepare directly
5457         node.SetSharedTransitionParam(std::nullopt);
5458         return;
5459     }
5460 
5461     // hack to ensure that dirty region will include the whole shared-transition nodes, and won't be clipped by parent
5462     // clip rect.
5463     prepareClipRect_.SetAll(0, 0, INT_MAX, INT_MAX);
5464 }
5465 
5466 bool RSUniRenderVisitor::ProcessSharedTransitionNode(RSBaseRenderNode& node)
5467 {
5468     // Sanity check done by caller, transitionParam should always has value.
5469     auto& transitionParam = node.GetSharedTransitionParam();
5470     if (LIKELY(!transitionParam.has_value())) {
5471         // non-transition node, prepare directly
5472         return true;
5473     }
5474 
5475     // Note: Sanity checks for shared transition nodes are already done in prepare phase, no need to do it again.
5476     // use transition key (in node id) as map index.
5477     auto key = transitionParam->first;
5478     // paired node is already visited, process both nodes in order.
5479     if (auto existingNodeIter = unpairedTransitionNodes_.find(key);
5480         existingNodeIter != unpairedTransitionNodes_.end()) {
5481         RSAutoCanvasRestore acr(canvas_);
5482         // restore render context and process the paired node.
5483         auto& [node, canvasStatus] = existingNodeIter->second;
5484         canvas_->SetCanvasStatus(canvasStatus);
5485         node->Process(shared_from_this());
5486         unpairedTransitionNodes_.erase(existingNodeIter);
5487         return true;
5488     }
5489     groupedTransitionNodesType nodes;
5490     {
5491         std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
5492         nodes = groupedTransitionNodes;
5493     }
5494     for (auto& [unused, pair] : nodes) {
5495         if (auto existingNodeIter = pair.second.find(key); existingNodeIter != pair.second.end()) {
5496             RSAutoCanvasRestore acr(canvas_);
5497             // restore render context and process the paired node.
5498             auto& [unused2, PreCanvasStatus] = pair.first;
5499             auto& [child, canvasStatus] = existingNodeIter->second;
5500             canvas_->SetCanvasStatus(canvasStatus);
5501             canvas_->MultiplyAlpha(PreCanvasStatus.alpha_);
5502 #ifndef USE_ROSEN_DRAWING
5503             canvas_->concat(PreCanvasStatus.matrix_);
5504 #else
5505             canvas_->ConcatMatrix(PreCanvasStatus.matrix_);
5506 #endif
5507             child->Process(shared_from_this());
5508             return true;
5509         }
5510     }
5511 
5512     auto pairedNode = transitionParam->second.lock();
5513     if (pairedNode == nullptr || pairedNode->GetGlobalAlpha() <= 0.0f) {
5514         // visitor may never visit the paired node, ignore the transition logic and process directly.
5515         return true;
5516     }
5517 
5518     if (!curGroupedNodes_.empty()) {
5519         // if in node group cache, add this node and render params (alpha and matrix) into groupedTransitionNodes.
5520         auto& [child, currentStatus] = curGroupedNodes_.top();
5521         auto canvasStatus = canvas_->GetCanvasStatus();
5522         if (!ROSEN_EQ(currentStatus.alpha_, 0.f)) {
5523             canvasStatus.alpha_ /= currentStatus.alpha_;
5524         } else {
5525             RS_LOGE("RSUniRenderVisitor::ProcessSharedTransitionNode: alpha_ is zero");
5526         }
5527 #ifndef USE_ROSEN_DRAWING
5528         if (!currentStatus.matrix_.invert(&canvasStatus.matrix_)) {
5529             RS_LOGE("RSUniRenderVisitor::ProcessSharedTransitionNode invert failed");
5530         }
5531 #else
5532         if (!currentStatus.matrix_.Invert(canvasStatus.matrix_)) {
5533             RS_LOGE("RSUniRenderVisitor::ProcessSharedTransitionNode invert failed");
5534         }
5535 #endif
5536         RenderParam value { node.shared_from_this(), canvasStatus };
5537         {
5538             std::lock_guard<std::mutex> lock(groupedTransitionNodesMutex);
5539             groupedTransitionNodes[child->GetId()].second.emplace(key, std::move(value));
5540         }
5541         return false;
5542     }
5543 
5544     // all sanity checks passed, add this node and render params (alpha and matrix) into unpairedTransitionNodes_.
5545     RenderParam value { node.shared_from_this(), canvas_->GetCanvasStatus() };
5546     unpairedTransitionNodes_.emplace(key, std::move(value));
5547 
5548     // skip processing the current node and all its children.
5549     return false;
5550 }
5551 
5552 void RSUniRenderVisitor::ProcessUnpairedSharedTransitionNode()
5553 {
5554     // Do cleanup for unpaired transition nodes.
5555     for (auto& [key, params] : unpairedTransitionNodes_) {
5556         RSAutoCanvasRestore acr(canvas_);
5557         // restore render context and process the unpaired node.
5558         auto& [node, canvasStatus] = params;
5559         canvas_->SetCanvasStatus(canvasStatus);
5560         node->Process(shared_from_this());
5561         // clear transition param
5562         node->SetSharedTransitionParam(std::nullopt);
5563     }
5564     unpairedTransitionNodes_.clear();
5565 }
5566 #ifdef ENABLE_RECORDING_DCL
5567 #ifndef USE_ROSEN_DRAWING
5568 void RSUniRenderVisitor::tryCapture(float width, float height)
5569 {
5570     if (!RSSystemProperties::GetRecordingEnabled()) {
5571         return;
5572     }
5573     recordingCanvas_ = std::make_unique<RSRecordingCanvas>(width, height);
5574     RS_TRACE_NAME("RSUniRender:Recording begin");
5575 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
5576 #ifdef NEW_SKIA
5577     recordingCanvas_->SetGrRecordingContext(canvas_->recordingContext());
5578 #else
5579     recordingCanvas_->SetGrContext(canvas_->getGrContext()); // SkImage::MakeFromCompressed need GrContext
5580 #endif
5581 #endif
5582     canvas_->addCanvas(recordingCanvas_.get());
5583     RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).CheckAndRecording();
5584 }
5585 
5586 void RSUniRenderVisitor::endCapture() const
5587 {
5588     if (!RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).GetRecordingEnabled()) {
5589         return;
5590     }
5591     auto drawCmdList = recordingCanvas_->GetDrawCmdList();
5592     RS_TRACE_NAME("RSUniRender:RecordingToFile curFrameNum = " +
5593         std::to_string(RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).GetCurDumpFrame()));
5594     RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).RecordingToFile(drawCmdList);
5595 }
5596 #else
5597 void RSUniRenderVisitor::tryCapture(float width, float height)
5598 {
5599     if (!RSSystemProperties::GetRecordingEnabled()) {
5600         return;
5601     }
5602     recordingCanvas_ = std::make_unique<ExtendRecordingCanvas>(width, height);
5603     RS_TRACE_NAME("RSUniRender:Recording begin");
5604 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
5605     auto renderContext = RSMainThread::Instance()->GetRenderEngine()->GetRenderContext();
5606     recordingCanvas_->SetGrRecordingContext(renderContext->GetSharedDrGPUContext());
5607 #endif
5608     canvas_->AddCanvas(recordingCanvas_.get());
5609     RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).CheckAndRecording();
5610 }
5611 
5612 void RSUniRenderVisitor::endCapture() const
5613 {
5614     if (!RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).GetRecordingEnabled()) {
5615         return;
5616     }
5617     auto drawCmdList = recordingCanvas_->GetDrawCmdList();
5618     RS_TRACE_NAME("RSUniRender:RecordingToFile curFrameNum = " +
5619         std::to_string(RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).GetCurDumpFrame()));
5620     RSRecordingThread::Instance(renderEngine_->GetRenderContext().get()).RecordingToFile(drawCmdList);
5621 }
5622 #endif
5623 #endif
5624 
5625 void RSUniRenderVisitor::RotateMirrorCanvasIfNeed(RSDisplayRenderNode& node)
5626 {
5627     auto mirrorNode = node.GetMirrorSource().lock();
5628     auto rotation = mirrorNode->GetScreenRotation();
5629     if (RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0) {
5630         if (rotation == ScreenRotation::ROTATION_270) {
5631             rotation = ScreenRotation::ROTATION_0;
5632         } else {
5633             rotation = static_cast<ScreenRotation>(static_cast<int>(rotation) + 1);
5634         }
5635     }
5636 #ifndef USE_ROSEN_DRAWING
5637     if (rotation != ScreenRotation::ROTATION_0) {
5638         auto screenManager = CreateOrGetScreenManager();
5639         auto mainScreenInfo = screenManager->QueryScreenInfo(mirrorNode->GetScreenId());
5640         if (rotation == ScreenRotation::ROTATION_90) {
5641             canvas_->rotate(90);
5642             canvas_->translate(0, -(static_cast<float>(mainScreenInfo.height)));
5643         } else if (rotation == ScreenRotation::ROTATION_180) {
5644             canvas_->rotate(180, static_cast<float>(mainScreenInfo.width) / 2,
5645                 static_cast<float>(mainScreenInfo.height) / 2);
5646         } else if (rotation == ScreenRotation::ROTATION_270) {
5647             canvas_->rotate(270);
5648             canvas_->translate(-(static_cast<float>(mainScreenInfo.width)), 0);
5649         }
5650     }
5651 #else
5652     if (rotation != ScreenRotation::ROTATION_0) {
5653         auto screenManager = CreateOrGetScreenManager();
5654         auto mainScreenInfo = screenManager->QueryScreenInfo(mirrorNode->GetScreenId());
5655         if (rotation == ScreenRotation::ROTATION_90) {
5656             canvas_->Rotate(90, 0, 0);
5657             canvas_->Translate(0, -(static_cast<float>(mainScreenInfo.height)));
5658         } else if (rotation == ScreenRotation::ROTATION_180) {
5659             canvas_->Rotate(180, static_cast<float>(mainScreenInfo.width) / 2,
5660                 static_cast<float>(mainScreenInfo.height) / 2);
5661         } else if (rotation == ScreenRotation::ROTATION_270) {
5662             canvas_->Rotate(270, 0, 0);
5663             canvas_->Translate(-(static_cast<float>(mainScreenInfo.width)), 0);
5664         }
5665     }
5666 #endif
5667 }
5668 
5669 void RSUniRenderVisitor::ScaleMirrorIfNeed(RSDisplayRenderNode& node, bool canvasRotation)
5670 {
5671     auto screenManager = CreateOrGetScreenManager();
5672     auto mirrorNode = node.GetMirrorSource().lock();
5673     auto mainScreenInfo = screenManager->QueryScreenInfo(mirrorNode->GetScreenId());
5674     float mainWidth = static_cast<float>(mainScreenInfo.width);
5675     float mainHeight = static_cast<float>(mainScreenInfo.height);
5676     if (canvasRotation) {
5677         if ((RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0) ||
5678             mirrorNode->GetScreenRotation() == ScreenRotation::ROTATION_90 ||
5679             mirrorNode->GetScreenRotation() == ScreenRotation::ROTATION_270) {
5680             std::swap(mainWidth, mainHeight);
5681         }
5682     } else {
5683         if ((RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0) ||
5684             node.GetOriginScreenRotation() == ScreenRotation::ROTATION_90 ||
5685             node.GetOriginScreenRotation() == ScreenRotation::ROTATION_270) {
5686             std::swap(mainWidth, mainHeight);
5687         }
5688         if ((RSSystemProperties::IsFoldScreenFlag() && mirrorNode->GetScreenId() == 0 &&
5689             (mirrorNode->GetScreenRotation() == ScreenRotation::ROTATION_90 ||
5690             mirrorNode->GetScreenRotation() == ScreenRotation::ROTATION_270)) || mirrorAutoRotate_) {
5691             std::swap(mainWidth, mainHeight);
5692         }
5693     }
5694     float boundsWidth = node.GetRenderProperties().GetBoundsWidth();
5695     float boundsHeight = node.GetRenderProperties().GetBoundsHeight();
5696     // If the width and height not match the main screen, calculate the dstRect.
5697     if (mainWidth != boundsWidth || mainHeight != boundsHeight) {
5698 #ifndef USE_ROSEN_DRAWING
5699         canvas_->clear(SK_ColorBLACK);
5700 #else
5701         canvas_->Clear(SK_ColorBLACK);
5702 #endif
5703         float mirrorScale = 1.0f; // 1 for init scale
5704         float startX = 0.0f;
5705         float startY = 0.0f;
5706         if ((boundsHeight / boundsWidth) < (mainHeight / mainWidth)) {
5707             mirrorScale = boundsHeight / mainHeight;
5708             startX = (boundsWidth - (mirrorScale * mainWidth)) / 2; // 2 for calc X
5709         } else if ((boundsHeight / boundsWidth) > (mainHeight / mainWidth)) {
5710             mirrorScale = boundsWidth / mainWidth;
5711             startY = (boundsHeight - (mirrorScale * mainHeight)) / 2; // 2 for calc Y
5712         }
5713 #ifndef USE_ROSEN_DRAWING
5714         canvas_->translate(startX, startY);
5715         canvas_->scale(mirrorScale, mirrorScale);
5716 #else
5717         canvas_->Translate(startX, startY);
5718         canvas_->Scale(mirrorScale, mirrorScale);
5719 #endif
5720     }
5721 }
5722 
5723 void RSUniRenderVisitor::SetHasSharedTransitionNode(RSSurfaceRenderNode& surfaceNode, bool hasSharedTransitionNode)
5724 {
5725     // only allow change hasSharedTransitionNode in leash window's child
5726     if (surfaceNode.GetSurfaceNodeType() == RSSurfaceNodeType::LEASH_WINDOW_NODE) {
5727         return;
5728     }
5729     surfaceNode.SetHasSharedTransitionNode(hasSharedTransitionNode);
5730     // sync the change to parent leash window
5731     auto leashNode =
5732         RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(surfaceNode.GetParent().lock());
5733     if (leashNode && leashNode->GetSurfaceNodeType() == RSSurfaceNodeType::LEASH_WINDOW_NODE) {
5734         leashNode->SetHasSharedTransitionNode(hasSharedTransitionNode);
5735     }
5736 }
5737 
5738 NodeId RSUniRenderVisitor::FindInstanceChildOfDisplay(std::shared_ptr<RSRenderNode> node)
5739 {
5740     if (node == nullptr || node->GetParent().lock() == nullptr) {
5741         return INVALID_NODEID;
5742     } else if (node->GetParent().lock()->GetType() == RSRenderNodeType::DISPLAY_NODE) {
5743         return node->GetId();
5744     } else {
5745         return FindInstanceChildOfDisplay(node->GetParent().lock());
5746     }
5747 }
5748 
5749 bool RSUniRenderVisitor::CheckIfNeedResetRotate()
5750 {
5751     if (canvas_ == nullptr) {
5752         return true;
5753     }
5754 #ifndef USE_ROSEN_DRAWING
5755     int angle = RSUniRenderUtil::GetRotationFromMatrix(canvas_->getTotalMatrix());
5756 #else
5757     int angle = RSUniRenderUtil::GetRotationFromMatrix(canvas_->GetTotalMatrix());
5758 #endif
5759     return angle != 0 && angle % ROTATION_90 == 0;
5760 }
5761 
5762 bool RSUniRenderVisitor::IsOutOfScreenRegion(RectI rect)
5763 {
5764     int32_t boundWidth = static_cast<int32_t>(screenInfo_.width);
5765     int32_t boundHeight = static_cast<int32_t>(screenInfo_.height);
5766     ScreenRotation rotation = screenInfo_.rotation;
5767     if (rotation == ScreenRotation::ROTATION_90 || rotation == ScreenRotation::ROTATION_270) {
5768         std::swap(boundWidth, boundHeight);
5769     }
5770 
5771     if (rect.GetRight() <= 0 ||
5772         rect.GetLeft() >= boundWidth ||
5773         rect.GetBottom() <= 0 ||
5774         rect.GetTop() >= boundHeight) {
5775         return true;
5776     }
5777 
5778     return false;
5779 }
5780 } // namespace Rosen
5781 } // namespace OHOS
5782