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 ®ion)
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