• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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_render_node.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <memory>
21 #include <mutex>
22 #include <set>
23 
24 #include "rs_trace.h"
25 #include "animation/rs_render_animation.h"
26 #include "common/rs_obj_abs_geometry.h"
27 #include "benchmarks/file_utils.h"
28 #include "common/rs_optional_trace.h"
29 #include "modifier/rs_modifier_type.h"
30 #include "pipeline/rs_context.h"
31 #include "pipeline/rs_display_render_node.h"
32 #include "pipeline/rs_effect_render_node.h"
33 #include "pipeline/rs_paint_filter_canvas.h"
34 #include "pipeline/rs_root_render_node.h"
35 #include "pipeline/rs_surface_render_node.h"
36 #include "platform/common/rs_log.h"
37 #include "platform/common/rs_system_properties.h"
38 #include "property/rs_properties_painter.h"
39 #include "property/rs_property_drawable.h"
40 #include "property/rs_property_trace.h"
41 #include "transaction/rs_transaction_proxy.h"
42 #include "visitor/rs_node_visitor.h"
43 
44 #ifdef RS_ENABLE_VK
45 #include "include/gpu/GrBackendSurface.h"
46 #include "platform/ohos/backend/native_buffer_utils.h"
47 #include "platform/ohos/backend/rs_vulkan_context.h"
48 #endif
49 
50 #ifdef RS_ENABLE_VK
51 namespace {
findMemoryType(uint32_t typeFilter,VkMemoryPropertyFlags properties)52 uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
53 {
54     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
55         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
56         return UINT32_MAX;
57     }
58     auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton();
59     VkPhysicalDevice physicalDevice = vkContext.GetPhysicalDevice();
60 
61     VkPhysicalDeviceMemoryProperties memProperties;
62     vkContext.vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
63 
64     for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
65         if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties) {
66             return i;
67         }
68     }
69 
70     return UINT32_MAX;
71 }
72 
73 #ifndef USE_ROSEN_DRAWING
SetVkImageInfo(GrVkImageInfo & skImageInfo,const VkImageCreateInfo & imageInfo)74 void SetVkImageInfo(GrVkImageInfo& skImageInfo, const VkImageCreateInfo& imageInfo)
75 {
76     skImageInfo.fImageTiling = imageInfo.tiling;
77     skImageInfo.fImageLayout = imageInfo.initialLayout;
78     skImageInfo.fFormat = imageInfo.format;
79     skImageInfo.fImageUsageFlags = imageInfo.usage;
80     skImageInfo.fLevelCount = imageInfo.mipLevels;
81     skImageInfo.fCurrentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
82     skImageInfo.fYcbcrConversionInfo = {};
83     skImageInfo.fSharingMode = imageInfo.sharingMode;
84 }
85 #else
SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,const VkImageCreateInfo & imageInfo)86 void SetVkImageInfo(std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo,
87     const VkImageCreateInfo& imageInfo)
88 {
89     vkImageInfo->imageTiling = imageInfo.tiling;
90     vkImageInfo->imageLayout = imageInfo.initialLayout;
91     vkImageInfo->format = imageInfo.format;
92     vkImageInfo->imageUsageFlags = imageInfo.usage;
93     vkImageInfo->levelCount = imageInfo.mipLevels;
94     vkImageInfo->currentQueueFamily = VK_QUEUE_FAMILY_EXTERNAL;
95     vkImageInfo->ycbcrConversionInfo = {};
96     vkImageInfo->sharingMode = imageInfo.sharingMode;
97 }
98 #endif
99 
100 #ifndef USE_ROSEN_DRAWING
MakeBackendTexture(uint32_t width,uint32_t height,VkFormat format=VK_FORMAT_R8G8B8A8_UNORM)101 GrBackendTexture MakeBackendTexture(uint32_t width, uint32_t height, VkFormat format = VK_FORMAT_R8G8B8A8_UNORM)
102 #else
103 OHOS::Rosen::Drawing::BackendTexture MakeBackendTexture(uint32_t width, uint32_t height,
104     VkFormat format = VK_FORMAT_R8G8B8A8_UNORM)
105 #endif
106 {
107     VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL;
108     VkImageUsageFlags usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
109         VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
110     VkImageCreateInfo imageInfo {
111         .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
112         .pNext = nullptr,
113         .flags = 0,
114         .imageType = VK_IMAGE_TYPE_2D,
115         .format = format,
116         .extent = {width, height, 1},
117         .mipLevels = 1,
118         .arrayLayers = 1,
119         .samples = VK_SAMPLE_COUNT_1_BIT,
120         .tiling = tiling,
121         .usage = usage,
122         .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
123         .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED
124     };
125 
126     auto& vkContext = OHOS::Rosen::RsVulkanContext::GetSingleton();
127     VkDevice device = vkContext.GetDevice();
128     VkImage image = VK_NULL_HANDLE;
129     VkDeviceMemory memory = VK_NULL_HANDLE;
130 
131     if (vkContext.vkCreateImage(device, &imageInfo, nullptr, &image) != VK_SUCCESS) {
132         return {};
133     }
134 
135     VkMemoryRequirements memRequirements;
136     vkContext.vkGetImageMemoryRequirements(device, image, &memRequirements);
137 
138     VkMemoryAllocateInfo allocInfo{};
139     allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
140     allocInfo.allocationSize = memRequirements.size;
141     allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
142     if (allocInfo.memoryTypeIndex == UINT32_MAX) {
143         return {};
144     }
145 
146     if (vkContext.vkAllocateMemory(device, &allocInfo, nullptr, &memory) != VK_SUCCESS) {
147         return {};
148     }
149 
150     vkContext.vkBindImageMemory(device, image, memory, 0);
151 
152 #ifndef USE_ROSEN_DRAWING
153     GrVkAlloc alloc;
154     alloc.fMemory = memory;
155     alloc.fOffset = memRequirements.size;
156 
157     GrVkImageInfo skImageInfo;
158     skImageInfo.fImage = image;
159     skImageInfo.fAlloc = alloc;
160     SetVkImageInfo(skImageInfo, imageInfo);
161 
162     return GrBackendTexture(width, height, skImageInfo);
163 #else
164     OHOS::Rosen::Drawing::BackendTexture backendTexture(true);
165     OHOS::Rosen::Drawing::TextureInfo textureInfo;
166     textureInfo.SetWidth(width);
167     textureInfo.SetHeight(height);
168 
169     std::shared_ptr<OHOS::Rosen::Drawing::VKTextureInfo> vkImageInfo =
170         std::make_shared<OHOS::Rosen::Drawing::VKTextureInfo>();
171     vkImageInfo->vkImage = image;
172     vkImageInfo->vkAlloc.memory = memory;
173     vkImageInfo->vkAlloc.size = memRequirements.size;
174 
175     SetVkImageInfo(vkImageInfo, imageInfo);
176     textureInfo.SetVKTextureInfo(vkImageInfo);
177     backendTexture.SetTextureInfo(textureInfo);
178     return backendTexture;
179 #endif
180 }
181 } // un-named
182 #endif
183 
184 namespace OHOS {
185 namespace Rosen {
OnRegister(const std::weak_ptr<RSContext> & context)186 void RSRenderNode::OnRegister(const std::weak_ptr<RSContext>& context)
187 {
188     context_ = context;
189     renderContent_->type_ = GetType();
190     renderContent_->renderProperties_.backref_ = weak_from_this();
191     SetDirty(true);
192 }
193 
IsPureContainer() const194 bool RSRenderNode::IsPureContainer() const
195 {
196     auto& drawCmdModifiers_ = renderContent_->drawCmdModifiers_;
197     return (drawCmdModifiers_.empty() && !GetRenderProperties().isDrawn_ && !GetRenderProperties().alphaNeedApply_);
198 }
199 
IsContentNode() const200 bool RSRenderNode::IsContentNode() const
201 {
202     auto& drawCmdModifiers_ = renderContent_->drawCmdModifiers_;
203     return ((drawCmdModifiers_.size() == 1 && drawCmdModifiers_.count(RSModifierType::CONTENT_STYLE)) ||
204                drawCmdModifiers_.empty()) &&
205            !GetRenderProperties().isDrawn_;
206 }
207 
208 namespace {
209 const std::set<RSModifierType> GROUPABLE_ANIMATION_TYPE = {
210     RSModifierType::ALPHA,
211     RSModifierType::ROTATION,
212     RSModifierType::SCALE,
213 };
214 const std::set<RSModifierType> CACHEABLE_ANIMATION_TYPE = {
215     RSModifierType::BOUNDS,
216     RSModifierType::FRAME,
217 };
218 const std::set<RSModifierType> BASIC_GEOTRANSFORM_ANIMATION_TYPE = {
219     RSModifierType::TRANSLATE,
220     RSModifierType::SCALE,
221 };
222 }
223 
RSRenderNode(NodeId id,const std::weak_ptr<RSContext> & context,bool isTextureExportNode)224 RSRenderNode::RSRenderNode(NodeId id, const std::weak_ptr<RSContext>& context, bool isTextureExportNode)
225     : id_(id), context_(context), isTextureExportNode_(isTextureExportNode)
226 {}
227 
RSRenderNode(NodeId id,bool isOnTheTree,const std::weak_ptr<RSContext> & context,bool isTextureExportNode)228 RSRenderNode::RSRenderNode(
229     NodeId id, bool isOnTheTree, const std::weak_ptr<RSContext>& context, bool isTextureExportNode)
230     : isOnTheTree_(isOnTheTree), id_(id), context_(context), isTextureExportNode_(isTextureExportNode)
231 {}
232 
GetIsTextureExportNode() const233 bool RSRenderNode::GetIsTextureExportNode() const
234 {
235     return isTextureExportNode_;
236 }
237 
AddChild(SharedPtr child,int index)238 void RSRenderNode::AddChild(SharedPtr child, int index)
239 {
240     // sanity check, avoid loop
241     if (child == nullptr || child->GetId() == GetId()) {
242         return;
243     }
244     // if child already has a parent, remove it from its previous parent
245     if (auto prevParent = child->GetParent().lock()) {
246         prevParent->RemoveChild(child);
247     }
248 
249     // Set parent-child relationship
250     child->SetParent(weak_from_this());
251     if (index < 0 || index >= static_cast<int>(children_.size())) {
252         children_.emplace_back(child);
253     } else {
254         children_.emplace(std::next(children_.begin(), index), child);
255     }
256 
257     disappearingChildren_.remove_if([&child](const auto& pair) -> bool { return pair.first == child; });
258     // A child is not on the tree until its parent is on the tree
259     if (isOnTheTree_) {
260         child->SetIsOnTheTree(true, instanceRootNodeId_, firstLevelNodeId_, drawingCacheRootId_);
261     }
262     SetContentDirty();
263     isFullChildrenListValid_ = false;
264 }
265 
SetContainBootAnimation(bool isContainBootAnimation)266 void RSRenderNode::SetContainBootAnimation(bool isContainBootAnimation)
267 {
268     isContainBootAnimation_ = isContainBootAnimation;
269     isFullChildrenListValid_ = false;
270 }
271 
GetContainBootAnimation() const272 bool RSRenderNode::GetContainBootAnimation() const
273 {
274     return isContainBootAnimation_;
275 }
276 
MoveChild(SharedPtr child,int index)277 void RSRenderNode::MoveChild(SharedPtr child, int index)
278 {
279     if (child == nullptr || child->GetParent().lock().get() != this) {
280         return;
281     }
282     auto it = std::find_if(children_.begin(), children_.end(),
283         [&](WeakPtr& ptr) -> bool { return ROSEN_EQ<RSRenderNode>(ptr, child); });
284     if (it == children_.end()) {
285         return;
286     }
287 
288     // Reset parent-child relationship
289     if (index < 0 || index >= static_cast<int>(children_.size())) {
290         children_.emplace_back(child);
291     } else {
292         children_.emplace(std::next(children_.begin(), index), child);
293     }
294     children_.erase(it);
295     SetContentDirty();
296     isFullChildrenListValid_ = false;
297 }
298 
RemoveChild(SharedPtr child,bool skipTransition)299 void RSRenderNode::RemoveChild(SharedPtr child, bool skipTransition)
300 {
301     if (child == nullptr) {
302         return;
303     }
304     // break parent-child relationship
305     auto it = std::find_if(children_.begin(), children_.end(),
306         [&](WeakPtr& ptr) -> bool { return ROSEN_EQ<RSRenderNode>(ptr, child); });
307     if (it == children_.end()) {
308         return;
309     }
310     // avoid duplicate entry in disappearingChildren_ (this should not happen)
311     disappearingChildren_.remove_if([&child](const auto& pair) -> bool { return pair.first == child; });
312     // if child has disappearing transition, add it to disappearingChildren_
313     if (skipTransition == false && child->HasDisappearingTransition(true)) {
314         ROSEN_LOGD("RSRenderNode::RemoveChild %{public}" PRIu64 " move child(id %{public}" PRIu64 ") into"
315             " disappearingChildren", GetId(), child->GetId());
316         // keep shared_ptr alive for transition
317         uint32_t origPos = static_cast<uint32_t>(std::distance(children_.begin(), it));
318         disappearingChildren_.emplace_back(child, origPos);
319     } else {
320         child->ResetParent();
321     }
322     children_.erase(it);
323     if (child->GetBootAnimation()) {
324         SetContainBootAnimation(false);
325     }
326     if (!children_.empty() || !disappearingChildren_.empty()) {
327         isFullChildrenListValid_ = false;
328     } else { // directly clear children list
329         isFullChildrenListValid_ = true;
330         isChildrenSorted_ = true;
331         std::atomic_store_explicit(&fullChildrenList_, EmptyChildrenList, std::memory_order_release);
332     }
333 }
334 
SetIsOnTheTree(bool flag,NodeId instanceRootNodeId,NodeId firstLevelNodeId,NodeId cacheNodeId)335 void RSRenderNode::SetIsOnTheTree(bool flag, NodeId instanceRootNodeId, NodeId firstLevelNodeId, NodeId cacheNodeId)
336 {
337     // We do not need to label a child when the child is removed from a parent that is not on the tree
338     if (flag == isOnTheTree_) {
339         return;
340     }
341     isNewOnTree_ = flag && !isOnTheTree_;
342     isOnTheTree_ = flag;
343     if (isOnTheTree_) {
344         instanceRootNodeId_ = instanceRootNodeId;
345         firstLevelNodeId_ = firstLevelNodeId;
346         OnTreeStateChanged();
347     } else {
348         OnTreeStateChanged();
349         instanceRootNodeId_ = instanceRootNodeId;
350         firstLevelNodeId_ = firstLevelNodeId;
351     }
352     // if node is marked as cacheRoot, update subtree status when update surface
353     // in case prepare stage upper cacheRoot cannot specify dirty subnode
354     if (cacheNodeId != INVALID_NODEID) {
355         drawingCacheRootId_ = cacheNodeId;
356     }
357 
358     for (auto& weakChild : children_) {
359         auto child = weakChild.lock();
360         if (child == nullptr) {
361             continue;
362         }
363         child->SetIsOnTheTree(flag, instanceRootNodeId, firstLevelNodeId, cacheNodeId);
364     }
365 
366     for (auto& [child, _] : disappearingChildren_) {
367         child->SetIsOnTheTree(flag, instanceRootNodeId, firstLevelNodeId, cacheNodeId);
368     }
369 }
370 
UpdateChildrenRect(const RectI & subRect)371 void RSRenderNode::UpdateChildrenRect(const RectI& subRect)
372 {
373     if (!subRect.IsEmpty()) {
374         if (childrenRect_.IsEmpty()) {
375             // init as not empty subRect in case join RectI enlarging area
376             childrenRect_ = subRect;
377         } else {
378             childrenRect_ = childrenRect_.JoinRect(subRect);
379         }
380     }
381 }
382 
AddCrossParentChild(const SharedPtr & child,int32_t index)383 void RSRenderNode::AddCrossParentChild(const SharedPtr& child, int32_t index)
384 {
385     // AddCrossParentChild only used as: the child is under multiple parents(e.g. a window cross multi-screens),
386     // so this child will not remove from the old parent.
387     if (child == nullptr) {
388         return;
389     }
390 
391     // Set parent-child relationship
392     child->SetParent(weak_from_this());
393     if (index < 0 || index >= static_cast<int32_t>(children_.size())) {
394         children_.emplace_back(child);
395     } else {
396         children_.emplace(std::next(children_.begin(), index), child);
397     }
398 
399     disappearingChildren_.remove_if([&child](const auto& pair) -> bool { return pair.first == child; });
400     // A child is not on the tree until its parent is on the tree
401     if (isOnTheTree_) {
402         child->SetIsOnTheTree(true, instanceRootNodeId_, firstLevelNodeId_, drawingCacheRootId_);
403     }
404     SetContentDirty();
405     isFullChildrenListValid_ = false;
406 }
407 
RemoveCrossParentChild(const SharedPtr & child,const WeakPtr & newParent)408 void RSRenderNode::RemoveCrossParentChild(const SharedPtr& child, const WeakPtr& newParent)
409 {
410     // RemoveCrossParentChild only used as: the child is under multiple parents(e.g. a window cross multi-screens),
411     // set the newParentId to rebuild the parent-child relationship.
412     if (child == nullptr) {
413         return;
414     }
415     // break parent-child relationship
416     auto it = std::find_if(children_.begin(), children_.end(),
417         [&](WeakPtr& ptr) -> bool { return ROSEN_EQ<RSRenderNode>(ptr, child); });
418     if (it == children_.end()) {
419         return;
420     }
421     // avoid duplicate entry in disappearingChildren_ (this should not happen)
422     disappearingChildren_.remove_if([&child](const auto& pair) -> bool { return pair.first == child; });
423     // if child has disappearing transition, add it to disappearingChildren_
424     if (child->HasDisappearingTransition(true)) {
425         ROSEN_LOGD("RSRenderNode::RemoveChild %{public}" PRIu64 " move child(id %{public}" PRIu64 ")"
426             " into disappearingChildren", GetId(), child->GetId());
427         // keep shared_ptr alive for transition
428         uint32_t origPos = static_cast<uint32_t>(std::distance(children_.begin(), it));
429         disappearingChildren_.emplace_back(child, origPos);
430     } else {
431         child->SetParent(newParent);
432         // attention: set new parent means 'old' parent has removed this child
433         hasRemovedChild_ = true;
434     }
435     children_.erase(it);
436     SetContentDirty();
437     if (!children_.empty() || !disappearingChildren_.empty()) {
438         isFullChildrenListValid_ = false;
439     } else { // directly clear children list
440         isFullChildrenListValid_ = true;
441         isChildrenSorted_ = true;
442         std::atomic_store_explicit(&fullChildrenList_, EmptyChildrenList, std::memory_order_release);
443     }
444 }
445 
RemoveFromTree(bool skipTransition)446 void RSRenderNode::RemoveFromTree(bool skipTransition)
447 {
448     auto parentPtr = parent_.lock();
449     if (parentPtr == nullptr) {
450         return;
451     }
452     auto child = shared_from_this();
453     parentPtr->RemoveChild(child, skipTransition);
454     if (skipTransition == false) {
455         return;
456     }
457     // force remove child from disappearingChildren_ and clean sortChildren_ cache
458     parentPtr->disappearingChildren_.remove_if([&child](const auto& pair) -> bool { return pair.first == child; });
459     parentPtr->isFullChildrenListValid_ = false;
460     child->ResetParent();
461 }
462 
ClearChildren()463 void RSRenderNode::ClearChildren()
464 {
465     if (children_.empty()) {
466         return;
467     }
468     // Cache the parent's transition state to avoid redundant recursively check
469     bool parentHasDisappearingTransition = HasDisappearingTransition(true);
470     uint32_t pos = 0;
471     for (auto& childWeakPtr : children_) {
472         auto child = childWeakPtr.lock();
473         if (child == nullptr) {
474             ++pos;
475             continue;
476         }
477         // avoid duplicate entry in disappearingChildren_ (this should not happen)
478         disappearingChildren_.remove_if([&child](const auto& pair) -> bool { return pair.first == child; });
479         if (parentHasDisappearingTransition || child->HasDisappearingTransition(false)) {
480             // keep shared_ptr alive for transition
481             disappearingChildren_.emplace_back(child, pos);
482         } else {
483             child->ResetParent();
484         }
485         ++pos;
486     }
487     children_.clear();
488     SetContentDirty();
489     if (!disappearingChildren_.empty()) {
490         isFullChildrenListValid_ = false;
491     } else { // directly clear children list
492         isFullChildrenListValid_ = true;
493         isChildrenSorted_ = true;
494         std::atomic_store_explicit(&fullChildrenList_, EmptyChildrenList, std::memory_order_release);
495     }
496 }
497 
SetParent(WeakPtr parent)498 void RSRenderNode::SetParent(WeakPtr parent)
499 {
500     UpdateSubSurfaceCnt(parent.lock(), parent_.lock());
501     parent_ = parent;
502     if (isSubSurfaceEnabled_) {
503         AddSubSurfaceNode(shared_from_this(), parent.lock());
504     }
505 }
506 
ResetParent()507 void RSRenderNode::ResetParent()
508 {
509     if (auto parentNode = parent_.lock()) {
510         if (isSubSurfaceEnabled_) {
511             auto it = std::find_if(parentNode->disappearingChildren_.begin(), parentNode->disappearingChildren_.end(),
512                 [childPtr = shared_from_this()](const auto& pair) -> bool { return pair.first == childPtr; });
513             if (it == parentNode->disappearingChildren_.end()) {
514                 RemoveSubSurfaceNode(shared_from_this(), parentNode);
515             }
516         }
517         parentNode->hasRemovedChild_ = true;
518         parentNode->SetContentDirty();
519         UpdateSubSurfaceCnt(nullptr, parentNode);
520     }
521     parent_.reset();
522     SetIsOnTheTree(false);
523     OnResetParent();
524 }
525 
GetParent() const526 RSRenderNode::WeakPtr RSRenderNode::GetParent() const
527 {
528     return parent_;
529 }
530 
IsFirstLevelSurfaceNode()531 bool RSRenderNode::IsFirstLevelSurfaceNode()
532 {
533     if (!this->IsInstanceOf<RSSurfaceRenderNode>()) {
534         return false;
535     }
536     auto parentNode = parent_.lock();
537     while (parentNode && !parentNode->IsInstanceOf<RSDisplayRenderNode>()) {
538         auto node = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(parentNode);
539         if (node != nullptr && (node->IsMainWindowType() || node->IsLeashWindow())) {
540             return false;
541         }
542         parentNode = parentNode->GetParent().lock();
543     }
544     return true;
545 }
546 
SubSurfaceNodeNeedDraw(PartialRenderType opDropType)547 bool RSRenderNode::SubSurfaceNodeNeedDraw(PartialRenderType opDropType)
548 {
549     for (auto &nodes : subSurfaceNodes_) {
550         for (auto &node : nodes.second) {
551             const auto& surfaceNode = RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(node.lock());
552             if (surfaceNode != nullptr &&
553                 (surfaceNode->SubNodeNeedDraw(surfaceNode->GetOldDirtyInSurface(), opDropType) ||
554                 surfaceNode->SubSurfaceNodeNeedDraw(opDropType))) {
555                 return true;
556             }
557         }
558     }
559     return false;
560 }
561 
AddSubSurfaceNode(SharedPtr child,SharedPtr parent)562 void RSRenderNode::AddSubSurfaceNode(SharedPtr child, SharedPtr parent)
563 {
564     if (parent->subSurfaceNodes_.find(child->GetId()) != parent->subSurfaceNodes_.end()) {
565         return;
566     }
567     std::vector<WeakPtr> subSurfaceNodes;
568     if (child->IsInstanceOf<RSSurfaceRenderNode>() &&
569         (RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child)->IsMainWindowType() ||
570         RSBaseRenderNode::ReinterpretCast<RSSurfaceRenderNode>(child)->IsLeashWindow())) {
571         subSurfaceNodes.push_back(child);
572     } else {
573         for (auto &nodes : child->subSurfaceNodes_) {
574             subSurfaceNodes.insert(subSurfaceNodes.end(), nodes.second.begin(), nodes.second.end());
575         }
576     }
577     if (subSurfaceNodes.size() == 0) {
578         return;
579     }
580 
581     auto childNode = child;
582     auto parentNode = parent;
583     while (parentNode && !parentNode->IsInstanceOf<RSDisplayRenderNode>()) {
584         auto id = childNode->GetId();
585         if (parentNode->subSurfaceNodes_.find(id) == parentNode->subSurfaceNodes_.end()) {
586             parentNode->subSurfaceNodes_.insert({id, subSurfaceNodes});
587         } else {
588             parentNode->subSurfaceNodes_[id].insert(parentNode->subSurfaceNodes_[id].end(),
589                 subSurfaceNodes.begin(), subSurfaceNodes.end());
590         }
591         std::sort(parentNode->subSurfaceNodes_[id].begin(), parentNode->subSurfaceNodes_[id].end(),
592             [](const auto &first, const auto &second) {
593             return
594                 first.lock()->GetRenderProperties().GetPositionZ() <
595                 second.lock()->GetRenderProperties().GetPositionZ();
596         });
597         if (parentNode->IsInstanceOf<RSSurfaceRenderNode>()) {
598             break;
599         }
600         childNode = parentNode;
601         parentNode = parentNode->GetParent().lock();
602     }
603 }
604 
RemoveSubSurfaceNode(SharedPtr child,SharedPtr parent)605 void RSRenderNode::RemoveSubSurfaceNode(SharedPtr child, SharedPtr parent)
606 {
607     if (parent->subSurfaceNodes_.find(child->GetId()) == parent->subSurfaceNodes_.end()) {
608         return;
609     }
610     auto subSurfaceNodes = parent->subSurfaceNodes_[child->GetId()];
611     parent->subSurfaceNodes_.erase(child->GetId());
612     auto childNode = parent;
613     auto parentNode = parent->GetParent().lock();
614     while (parentNode && !parentNode->IsInstanceOf<RSDisplayRenderNode>()) {
615         auto id = childNode->GetId();
616         for (auto iter : subSurfaceNodes) {
617             parentNode->subSurfaceNodes_[id].erase(
618                 remove_if(parentNode->subSurfaceNodes_[id].begin(), parentNode->subSurfaceNodes_[id].end(),
619                     [iter](WeakPtr it) {
620                         return iter.lock() && it.lock() && iter.lock()->GetId() == it.lock()->GetId();
621                     }),
622                 parentNode->subSurfaceNodes_[id].end()
623             );
624         }
625         if (parentNode->subSurfaceNodes_[id].size() == 0) {
626             parentNode->subSurfaceNodes_.erase(id);
627         }
628         if (parentNode->IsInstanceOf<RSSurfaceRenderNode>()) {
629             break;
630         }
631         childNode = parentNode;
632         parentNode = parentNode->GetParent().lock();
633     }
634 }
635 
DumpTree(int32_t depth,std::string & out) const636 void RSRenderNode::DumpTree(int32_t depth, std::string& out) const
637 {
638     for (int32_t i = 0; i < depth; ++i) {
639         out += "  ";
640     }
641     out += "| ";
642     DumpNodeType(out);
643     out += "[" + std::to_string(GetId()) + "], instanceRootNodeId" + "[" +
644         std::to_string(GetInstanceRootNodeId()) + "]";
645     if (IsSuggestedDrawInGroup()) {
646         out += ", [node group]";
647     }
648     DumpSubClassNode(out);
649     out += ", Properties: " + GetRenderProperties().Dump();
650     out += ", GetBootAnimation: " + std::to_string(GetBootAnimation());
651     out += ", isContainBootAnimation_: " + std::to_string(isContainBootAnimation_);
652     out += ", isNodeDirty: " + std::to_string(static_cast<int>(dirtyStatus_));
653     out += ", isPropertyDirty: " + std::to_string(GetRenderProperties().IsDirty());
654     out += ", IsPureContainer: " + std::to_string(IsPureContainer());
655     DumpDrawCmdModifiers(out);
656     animationManager_.DumpAnimations(out);
657     out += "\n";
658 
659     for (auto& child : *GetSortedChildren()) {
660         child->DumpTree(depth + 1, out);
661     }
662     for (auto& [child, pos] : disappearingChildren_) {
663         child->DumpTree(depth + 1, out);
664     }
665 }
666 
DumpNodeType(std::string & out) const667 void RSRenderNode::DumpNodeType(std::string& out) const
668 {
669     switch (GetType()) {
670         case RSRenderNodeType::DISPLAY_NODE: {
671             out += "DISPLAY_NODE";
672             break;
673         }
674         case RSRenderNodeType::RS_NODE: {
675             out += "RS_NODE";
676             break;
677         }
678         case RSRenderNodeType::SURFACE_NODE: {
679             out += "SURFACE_NODE";
680             break;
681         }
682         case RSRenderNodeType::CANVAS_NODE: {
683             out += "CANVAS_NODE";
684             break;
685         }
686         case RSRenderNodeType::ROOT_NODE: {
687             out += "ROOT_NODE";
688             break;
689         }
690         case RSRenderNodeType::PROXY_NODE: {
691             out += "PROXY_NODE";
692             break;
693         }
694         case RSRenderNodeType::CANVAS_DRAWING_NODE: {
695             out += "CANVAS_DRAWING_NODE";
696             break;
697         }
698         default: {
699             out += "UNKNOWN_NODE";
700             break;
701         }
702     }
703 }
704 
DumpSubClassNode(std::string & out) const705 void RSRenderNode::DumpSubClassNode(std::string& out) const
706 {
707     if (GetType() == RSRenderNodeType::SURFACE_NODE) {
708         auto surfaceNode = (static_cast<const RSSurfaceRenderNode*>(this));
709         auto p = parent_.lock();
710         out += ", Parent [" + (p != nullptr ? std::to_string(p->GetId()) : "null") + "]";
711         out += ", Name [" + surfaceNode->GetName() + "]";
712         const RSSurfaceHandler& surfaceHandler = static_cast<const RSSurfaceHandler&>(*surfaceNode);
713         out += ", hasConsumer: " + std::to_string(surfaceHandler.HasConsumer());
714         std::string contextAlpha = std::to_string(surfaceNode->contextAlpha_);
715         std::string propertyAlpha = std::to_string(surfaceNode->GetRenderProperties().GetAlpha());
716         out += ", Alpha: " + propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
717         out += ", Visible: " + std::to_string(surfaceNode->GetRenderProperties().GetVisible());
718         out += ", " + surfaceNode->GetVisibleRegion().GetRegionInfo();
719         out += ", OcclusionBg: " + std::to_string(surfaceNode->GetAbilityBgAlpha());
720         out += ", SecurityLayer: " + std::to_string(surfaceNode->GetSecurityLayer());
721         out += ", skipLayer: " + std::to_string(surfaceNode->GetSkipLayer());
722     } else if (GetType() == RSRenderNodeType::ROOT_NODE) {
723         auto rootNode = static_cast<const RSRootRenderNode*>(this);
724         out += ", Visible: " + std::to_string(rootNode->GetRenderProperties().GetVisible());
725         out += ", Size: [" + std::to_string(rootNode->GetRenderProperties().GetFrameWidth()) + ", " +
726             std::to_string(rootNode->GetRenderProperties().GetFrameHeight()) + "]";
727         out += ", EnableRender: " + std::to_string(rootNode->GetEnableRender());
728     } else if (GetType() == RSRenderNodeType::DISPLAY_NODE) {
729         auto displayNode = static_cast<const RSDisplayRenderNode*>(this);
730         out += ", skipLayer: " + std::to_string(displayNode->GetSecurityDisplay());
731     }
732 }
733 
DumpDrawCmdModifiers(std::string & out) const734 void RSRenderNode::DumpDrawCmdModifiers(std::string& out) const
735 {
736     if (renderContent_->drawCmdModifiers_.empty()) {
737         return;
738     }
739     std::string splitStr = ", ";
740     std::string modifierDesc = ", DrawCmdModifiers:[";
741     for (auto& [type, modifiers] : renderContent_->drawCmdModifiers_) {
742         modifierDesc += "type:" + std::to_string(static_cast<int>(type)) + ", modifiers: ";
743         std::string propertyDesc = "Property_";
744         for (auto& modifier : modifiers) {
745             DumpDrawCmdModifier(propertyDesc, type, modifier);
746             propertyDesc += "], ";
747         }
748         modifierDesc += propertyDesc.substr(0, propertyDesc.length() - splitStr.length());
749         modifierDesc += splitStr;
750     }
751     out += modifierDesc.substr(0, modifierDesc.length() - splitStr.length());
752     out += "]";
753 }
754 
DumpDrawCmdModifier(std::string & propertyDesc,RSModifierType type,std::shared_ptr<RSRenderModifier> & modifier) const755 void RSRenderNode::DumpDrawCmdModifier(std::string& propertyDesc, RSModifierType type,
756     std::shared_ptr<RSRenderModifier>& modifier) const
757 {
758     if (type < RSModifierType::ENV_FOREGROUND_COLOR) {
759         propertyDesc += "drawCmdList:[";
760         auto propertyValue = std::static_pointer_cast<RSRenderProperty<Drawing::DrawCmdListPtr>>
761             (modifier->GetProperty())->Get();
762         propertyDesc += propertyValue->GetOpsWithDesc();
763         std::string::size_type pos = 0;
764         while ((pos = propertyDesc.find("\n", pos)) != std::string::npos) {
765             propertyDesc.replace(pos, 1, ",");
766         }
767         propertyDesc.pop_back();
768     } else if (type == RSModifierType::ENV_FOREGROUND_COLOR) {
769         propertyDesc += "ENV_FOREGROUND_COLOR:[Rgba-";
770         auto propertyValue = std::static_pointer_cast<RSRenderAnimatableProperty<Color>>
771             (modifier->GetProperty())->Get();
772         propertyDesc += std::to_string(propertyValue.AsRgbaInt());
773     } else if (type == RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY) {
774         propertyDesc += "ENV_FOREGROUND_COLOR_STRATEGY:[";
775         auto propertyValue = std::static_pointer_cast<RSRenderProperty<ForegroundColorStrategyType>>
776             (modifier->GetProperty())->Get();
777         propertyDesc += std::to_string(static_cast<int>(propertyValue));
778     } else if (type == RSModifierType::GEOMETRYTRANS) {
779         propertyDesc += "GEOMETRYTRANS:[";
780         auto propertyValue = std::static_pointer_cast<RSRenderProperty<SkMatrix>>
781             (modifier->GetProperty())->Get();
782         propertyValue.dump(propertyDesc, 0);
783     }
784 }
785 
ResetIsOnlyBasicGeoTransform()786 void RSRenderNode::ResetIsOnlyBasicGeoTransform()
787 {
788     isOnlyBasicGeoTransform_ = true;
789 }
790 
IsOnlyBasicGeoTransform() const791 bool RSRenderNode::IsOnlyBasicGeoTransform() const
792 {
793     return isOnlyBasicGeoTransform_;
794 }
795 
796 // attention: current all base node's dirty ops causing content dirty
SetContentDirty()797 void RSRenderNode::SetContentDirty()
798 {
799     isContentDirty_ = true;
800     isOnlyBasicGeoTransform_ = false;
801     SetDirty();
802 }
803 
SetDirty(bool forceAddToActiveList)804 void RSRenderNode::SetDirty(bool forceAddToActiveList)
805 {
806     // TO avoid redundant add, only add if both: 1. on-tree node 2. newly dirty node (or forceAddToActiveList = true)
807 #ifndef USE_ROSEN_DRAWING
808     if (dirtyStatus_ == NodeDirty::CLEAN || dirtyTypes_.empty() || forceAddToActiveList) {
809 #else
810     if (dirtyStatus_ == NodeDirty::CLEAN || dirtyTypes_.none() || forceAddToActiveList) {
811 #endif
812         if (auto context = GetContext().lock()) {
813             context->AddActiveNode(shared_from_this());
814         }
815     }
816     dirtyStatus_ = NodeDirty::DIRTY;
817 }
818 
819 void RSRenderNode::SetClean()
820 {
821     isNewOnTree_ = false;
822     isContentDirty_ = false;
823     dirtyStatus_ = NodeDirty::CLEAN;
824 }
825 
826 void RSRenderNode::CollectSurface(
827     const std::shared_ptr<RSRenderNode>& node, std::vector<RSRenderNode::SharedPtr>& vec, bool isUniRender,
828     bool onlyFirstLevel)
829 {
830     for (auto& child : *node->GetSortedChildren()) {
831         child->CollectSurface(child, vec, isUniRender, onlyFirstLevel);
832     }
833 }
834 
835 void RSRenderNode::CollectSurfaceForUIFirstSwitch(uint32_t& leashWindowCount, uint32_t minNodeNum)
836 {
837     for (auto& child : *GetSortedChildren()) {
838         child->CollectSurfaceForUIFirstSwitch(leashWindowCount, minNodeNum);
839         if (leashWindowCount >= minNodeNum) {
840             return;
841         }
842     }
843 }
844 
845 void RSRenderNode::Prepare(const std::shared_ptr<RSNodeVisitor>& visitor)
846 {
847     if (!visitor) {
848         return;
849     }
850     visitor->PrepareChildren(*this);
851 }
852 
853 void RSRenderNode::Process(const std::shared_ptr<RSNodeVisitor>& visitor)
854 {
855     if (!visitor) {
856         return;
857     }
858     visitor->ProcessChildren(*this);
859 }
860 
861 void RSRenderNode::SendCommandFromRT(std::unique_ptr<RSCommand>& command, NodeId nodeId)
862 {
863     auto transactionProxy = RSTransactionProxy::GetInstance();
864     if (transactionProxy != nullptr) {
865         transactionProxy->AddCommandFromRT(command, nodeId);
866     }
867 }
868 
869 void RSRenderNode::InternalRemoveSelfFromDisappearingChildren()
870 {
871     // internal use only, force remove self from parent's disappearingChildren_
872     auto parent = parent_.lock();
873     if (parent == nullptr) {
874         return;
875     }
876     auto it = std::find_if(parent->disappearingChildren_.begin(), parent->disappearingChildren_.end(),
877         [childPtr = shared_from_this()](const auto& pair) -> bool { return pair.first == childPtr; });
878     if (it == parent->disappearingChildren_.end()) {
879         return;
880     }
881     parent->disappearingChildren_.erase(it);
882     parent->isFullChildrenListValid_ = false;
883     ResetParent();
884 }
885 
886 RSRenderNode::~RSRenderNode()
887 {
888     if (appPid_ != 0) {
889         RSSingleFrameComposer::AddOrRemoveAppPidToMap(false, appPid_);
890     }
891     if (fallbackAnimationOnDestroy_) {
892         FallbackAnimationsToRoot();
893     }
894     if (clearCacheSurfaceFunc_ && (cacheSurface_ || cacheCompletedSurface_)) {
895         clearCacheSurfaceFunc_(std::move(cacheSurface_), std::move(cacheCompletedSurface_), cacheSurfaceThreadIndex_,
896             completedSurfaceThreadIndex_);
897     }
898     ClearCacheSurface();
899 }
900 
901 void RSRenderNode::FallbackAnimationsToRoot()
902 {
903     if (animationManager_.animations_.empty()) {
904         return;
905     }
906 
907     auto context = GetContext().lock();
908     if (!context) {
909         ROSEN_LOGE("Invalid context");
910         return;
911     }
912     auto target = context->GetNodeMap().GetAnimationFallbackNode();
913     if (!target) {
914         ROSEN_LOGE("Failed to move animation to root, root render node is null!");
915         return;
916     }
917     context->RegisterAnimatingRenderNode(target);
918 
919     for (auto& [unused, animation] : animationManager_.animations_) {
920         animation->Detach(true);
921         // avoid infinite loop for fallback animation
922         animation->SetRepeatCount(1);
923         target->animationManager_.AddAnimation(std::move(animation));
924     }
925     animationManager_.animations_.clear();
926 }
927 
928 void RSRenderNode::ActivateDisplaySync()
929 {
930     if (!displaySync_) {
931         displaySync_ = std::make_shared<RSRenderDisplaySync>(GetId());
932     }
933 }
934 
935 void RSRenderNode::InActivateDisplaySync()
936 {
937     displaySync_ = nullptr;
938 }
939 
940 void RSRenderNode::UpdateDisplaySyncRange()
941 {
942     if (!displaySync_) {
943         return;
944     }
945     auto animationRange = animationManager_.GetFrameRateRange();
946     if (animationRange.IsValid()) {
947         displaySync_->SetExpectedFrameRateRange(animationRange);
948     }
949 }
950 
951 std::tuple<bool, bool, bool> RSRenderNode::Animate(int64_t timestamp, int64_t period, bool isDisplaySyncEnabled)
952 {
953     if (displaySync_ && displaySync_->OnFrameSkip(timestamp, period, isDisplaySyncEnabled)) {
954         return displaySync_->GetAnimateResult();
955     }
956     RS_OPTIONAL_TRACE_BEGIN("RSRenderNode:Animate node id: [" + std::to_string(GetId()) + "]");
957     auto animateResult = animationManager_.Animate(timestamp, IsOnTheTree());
958     if (displaySync_) {
959         displaySync_->SetAnimateResult(animateResult);
960     }
961     RS_OPTIONAL_TRACE_END();
962     return animateResult;
963 }
964 
965 bool RSRenderNode::IsClipBound() const
966 {
967     return GetRenderProperties().GetClipBounds() || GetRenderProperties().GetClipToFrame();
968 }
969 
970 const std::shared_ptr<RSRenderContent> RSRenderNode::GetRenderContent() const
971 {
972     return renderContent_;
973 }
974 
975 bool RSRenderNode::Update(
976     RSDirtyRegionManager& dirtyManager, const std::shared_ptr<RSRenderNode>& parent, bool parentDirty,
977     std::optional<RectI> clipRect)
978 {
979     // no need to update invisible nodes
980     if (!ShouldPaint() && !isLastVisible_) {
981         SetClean();
982         GetMutableRenderProperties().ResetDirty();
983         return false;
984     }
985     // [planning] surfaceNode use frame instead
986 #ifndef USE_ROSEN_DRAWING
987     std::optional<SkPoint> offset;
988     if (parent != nullptr && !IsInstanceOf<RSSurfaceRenderNode>()) {
989         auto& properties = parent->GetRenderProperties();
990         offset = SkPoint { properties.GetFrameOffsetX(), properties.GetFrameOffsetY() };
991     }
992 #else
993     std::optional<Drawing::Point> offset;
994     if (parent != nullptr && !IsInstanceOf<RSSurfaceRenderNode>()) {
995         auto& properties = parent->GetRenderProperties();
996         offset = Drawing::Point { properties.GetFrameOffsetX(), properties.GetFrameOffsetY() };
997     }
998 #endif
999     // in some case geodirty_ is not marked in drawCmdModifiers_, we should update node geometry
1000     // [planing] using drawcmdModifierDirty from dirtyType_
1001     parentDirty = parentDirty || (dirtyStatus_ != NodeDirty::CLEAN);
1002     auto parentProperties = parent ? &parent->GetRenderProperties() : nullptr;
1003     bool dirty = GetMutableRenderProperties().UpdateGeometry(parentProperties, parentDirty, offset,
1004         GetContextClipRegion());
1005     if ((IsDirty() || dirty) && renderContent_->drawCmdModifiers_.count(RSModifierType::GEOMETRYTRANS)) {
1006         RSModifierContext context = { GetMutableRenderProperties() };
1007         for (auto& modifier : renderContent_->drawCmdModifiers_[RSModifierType::GEOMETRYTRANS]) {
1008             modifier->Apply(context);
1009         }
1010     }
1011     isDirtyRegionUpdated_ = false;
1012     isLastVisible_ = ShouldPaint();
1013     GetMutableRenderProperties().ResetDirty();
1014 
1015     // Note:
1016     // 1. cache manager will use dirty region to update cache validity, background filter cache manager should use
1017     // 'dirty region of all the nodes drawn before this node', and foreground filter cache manager should use 'dirty
1018     // region of all the nodes drawn before this node, this node, and the children of this node'
1019     // 2. Filter must be valid when filter cache manager is valid, we make sure that in RSRenderNode::ApplyModifiers().
1020     UpdateFilterCacheWithDirty(dirtyManager, false);
1021     UpdateDirtyRegion(dirtyManager, dirty, clipRect);
1022     return dirty;
1023 }
1024 
1025 RSProperties& RSRenderNode::GetMutableRenderProperties()
1026 {
1027     return renderContent_->GetMutableRenderProperties();
1028 }
1029 
1030 const RSProperties& RSRenderNode::GetRenderProperties() const
1031 {
1032     return renderContent_->GetRenderProperties();
1033 }
1034 
1035 void RSRenderNode::UpdateDirtyRegion(
1036     RSDirtyRegionManager& dirtyManager, bool geoDirty, std::optional<RectI> clipRect)
1037 {
1038     if (!IsDirty() && !geoDirty) {
1039         return;
1040     }
1041     if (RSSystemProperties::GetSkipGeometryNotChangeEnabled()) {
1042         // while node absRect not change and other content not change, return directly for not generate dirty region
1043         if (!IsSelfDrawingNode() && !geometryChangeNotPerceived_ && !geoDirty) {
1044             return;
1045         }
1046         geometryChangeNotPerceived_ = false;
1047     }
1048     if (!oldDirty_.IsEmpty()) {
1049         dirtyManager.MergeDirtyRect(oldDirty_);
1050     }
1051     // merge old dirty if switch to invisible
1052     if (!ShouldPaint() && isLastVisible_) {
1053         ROSEN_LOGD("RSRenderNode:: id %{public}" PRIu64 " UpdateDirtyRegion visible->invisible", GetId());
1054     } else {
1055         RectI drawRegion;
1056         RectI shadowRect;
1057         auto dirtyRect = GetRenderProperties().GetDirtyRect(drawRegion);
1058         auto rectFromRenderProperties = dirtyRect;
1059         if (GetRenderProperties().IsShadowValid()) {
1060             SetShadowValidLastFrame(true);
1061             if (IsInstanceOf<RSSurfaceRenderNode>()) {
1062                 const RectF absBounds = {0, 0, GetRenderProperties().GetBoundsWidth(),
1063                     GetRenderProperties().GetBoundsHeight()};
1064                 RRect absClipRRect = RRect(absBounds, GetRenderProperties().GetCornerRadius());
1065                 RSPropertiesPainter::GetShadowDirtyRect(shadowRect, GetRenderProperties(), &absClipRRect);
1066             } else {
1067                 RSPropertiesPainter::GetShadowDirtyRect(shadowRect, GetRenderProperties());
1068             }
1069             if (!shadowRect.IsEmpty()) {
1070                 dirtyRect = dirtyRect.JoinRect(shadowRect);
1071             }
1072         }
1073 
1074         auto outline = GetRenderProperties().GetOutline();
1075         RectI outlineRect;
1076         if (outline && outline->HasBorder()) {
1077             RSPropertiesPainter::GetOutlineDirtyRect(outlineRect, GetRenderProperties());
1078             if (!outlineRect.IsEmpty()) {
1079                 dirtyRect = dirtyRect.JoinRect(outlineRect);
1080             }
1081         }
1082 
1083         if (GetRenderProperties().pixelStretch_) {
1084             auto stretchDirtyRect = GetRenderProperties().GetPixelStretchDirtyRect();
1085             dirtyRect = dirtyRect.JoinRect(stretchDirtyRect);
1086         }
1087 
1088         if (clipRect.has_value()) {
1089             dirtyRect = dirtyRect.IntersectRect(*clipRect);
1090         }
1091         oldDirty_ = dirtyRect;
1092         oldDirtyInSurface_ = oldDirty_.IntersectRect(dirtyManager.GetSurfaceRect());
1093         // filter invalid dirtyrect
1094         if (!dirtyRect.IsEmpty()) {
1095             dirtyManager.MergeDirtyRect(dirtyRect);
1096             isDirtyRegionUpdated_ = true;
1097             // save types of dirty region of target dirty manager for dfx
1098             if (dirtyManager.IsTargetForDfx() &&
1099                 (GetType() == RSRenderNodeType::CANVAS_NODE || GetType() == RSRenderNodeType::SURFACE_NODE)) {
1100                 dirtyManager.UpdateDirtyRegionInfoForDfx(
1101                     GetId(), GetType(), DirtyRegionType::UPDATE_DIRTY_REGION, oldDirtyInSurface_);
1102                 dirtyManager.UpdateDirtyRegionInfoForDfx(
1103                     GetId(), GetType(), DirtyRegionType::OVERLAY_RECT, drawRegion);
1104                 dirtyManager.UpdateDirtyRegionInfoForDfx(
1105                     GetId(), GetType(), DirtyRegionType::SHADOW_RECT, shadowRect);
1106                 dirtyManager.UpdateDirtyRegionInfoForDfx(
1107                     GetId(), GetType(), DirtyRegionType::PREPARE_CLIP_RECT, clipRect.value_or(RectI()));
1108                 dirtyManager.UpdateDirtyRegionInfoForDfx(
1109                     GetId(), GetType(), DirtyRegionType::RENDER_PROPERTIES_RECT, rectFromRenderProperties);
1110                 dirtyManager.UpdateDirtyRegionInfoForDfx(
1111                     GetId(), GetType(), DirtyRegionType::OUTLINE_RECT, outlineRect);
1112             }
1113         }
1114     }
1115 
1116     SetClean();
1117 }
1118 
1119 bool RSRenderNode::IsSelfDrawingNode() const
1120 {
1121     return GetType() == RSRenderNodeType::CANVAS_DRAWING_NODE || GetType() == RSRenderNodeType::SURFACE_NODE;
1122 }
1123 
1124 bool RSRenderNode::IsDirty() const
1125 {
1126     return dirtyStatus_ != NodeDirty::CLEAN || GetRenderProperties().IsDirty();
1127 }
1128 
1129 bool RSRenderNode::IsContentDirty() const
1130 {
1131     // Considering renderNode, it should consider both basenode's case and its properties
1132     return isContentDirty_ || GetRenderProperties().IsContentDirty();
1133 }
1134 
1135 void RSRenderNode::UpdateRenderStatus(RectI& dirtyRegion, bool isPartialRenderEnabled)
1136 {
1137     auto dirtyRect = GetRenderProperties().GetDirtyRect();
1138     // should judge if there's any child out of parent
1139     if (!isPartialRenderEnabled || HasChildrenOutOfRect()) {
1140         isRenderUpdateIgnored_ = false;
1141     } else if (dirtyRegion.IsEmpty() || dirtyRect.IsEmpty()) {
1142         isRenderUpdateIgnored_ = true;
1143     } else {
1144         RectI intersectRect = dirtyRegion.IntersectRect(dirtyRect);
1145         isRenderUpdateIgnored_ = intersectRect.IsEmpty();
1146     }
1147 }
1148 
1149 void RSRenderNode::UpdateParentChildrenRect(std::shared_ptr<RSRenderNode> parentNode) const
1150 {
1151     if (!ShouldPaint() || (oldDirty_.IsEmpty() && GetChildrenRect().IsEmpty())) {
1152         return;
1153     }
1154     auto renderParent = (parentNode);
1155     if (renderParent) {
1156         // accumulate current node's all children region(including itself)
1157         // apply oldDirty_ as node's real region(including overlay and shadow)
1158         RectI accumulatedRect = GetChildrenRect().JoinRect(oldDirty_);
1159         renderParent->UpdateChildrenRect(accumulatedRect);
1160         // check each child is inside of parent
1161         if (!accumulatedRect.IsInsideOf(renderParent->GetOldDirty())) {
1162             renderParent->UpdateChildrenOutOfRectFlag(true);
1163         }
1164     }
1165 }
1166 
1167 bool RSRenderNode::IsBackgroundFilterCacheValid() const
1168 {
1169     auto& manager = GetRenderProperties().GetFilterCacheManager(false);
1170     if (manager == nullptr) {
1171         return false;
1172     }
1173     bool backgroundFilterCacheValid = manager->IsCacheValid();
1174     return backgroundFilterCacheValid;
1175 }
1176 
1177 void RSRenderNode::UpdateFilterCacheWithDirty(RSDirtyRegionManager& dirtyManager, bool isForeground)
1178 {
1179 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
1180     if (!RSProperties::FilterCacheEnabled) {
1181         return;
1182     }
1183     auto& properties = GetRenderProperties();
1184     auto& manager = properties.GetFilterCacheManager(isForeground);
1185     if (manager == nullptr) {
1186         return;
1187     }
1188     if (!manager->IsCacheValid()) {
1189         return;
1190     }
1191     auto& cachedImageRect = manager->GetCachedImageRegion();
1192     if (manager->UpdateCacheStateWithDirtyRegion(dirtyManager)) {
1193         dirtyManager.MergeDirtyRect(cachedImageRect);
1194     }
1195 #endif
1196 }
1197 
1198 void RSRenderNode::RenderTraceDebug() const
1199 {
1200     if (RSSystemProperties::GetRenderNodeTraceEnabled()) {
1201         RSPropertyTrace::GetInstance().PropertiesDisplayByTrace(GetId(), GetRenderProperties());
1202     }
1203 }
1204 
1205 void RSRenderNode::ApplyBoundsGeometry(RSPaintFilterCanvas& canvas)
1206 {
1207     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1208         DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::BOUNDS_MATRIX, canvas);
1209         return;
1210     }
1211 #ifndef USE_ROSEN_DRAWING
1212     renderNodeSaveCount_ = canvas.Save();
1213 #else
1214     renderNodeSaveCount_ = canvas.SaveAllStatus();
1215 #endif
1216     auto boundsGeo = (GetRenderProperties().GetBoundsGeometry());
1217     if (boundsGeo && !boundsGeo->IsEmpty()) {
1218 #ifndef USE_ROSEN_DRAWING
1219         canvas.concat(boundsGeo->GetMatrix());
1220 #else
1221         canvas.ConcatMatrix(boundsGeo->GetMatrix());
1222 #endif
1223     }
1224 }
1225 
1226 void RSRenderNode::ApplyAlpha(RSPaintFilterCanvas& canvas)
1227 {
1228     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1229         DrawPropertyDrawable(RSPropertyDrawableSlot::ALPHA, canvas);
1230         return;
1231     }
1232     auto alpha = GetRenderProperties().GetAlpha();
1233     if (alpha < 1.f) {
1234         if (!(GetRenderProperties().GetAlphaOffscreen() || IsForcedDrawInGroup())) {
1235             canvas.MultiplyAlpha(alpha);
1236         } else {
1237 #ifndef USE_ROSEN_DRAWING
1238             auto rect = RSPropertiesPainter::Rect2SkRect(GetRenderProperties().GetBoundsRect());
1239             canvas.saveLayerAlpha(&rect, std::clamp(alpha, 0.f, 1.f) * UINT8_MAX);
1240 #else
1241             auto rect = RSPropertiesPainter::Rect2DrawingRect(GetRenderProperties().GetBoundsRect());
1242             Drawing::Brush brush;
1243             brush.SetAlpha(std::clamp(alpha, 0.f, 1.f) * UINT8_MAX);
1244             Drawing::SaveLayerOps slr(&rect, &brush);
1245             canvas.SaveLayer(slr);
1246 #endif
1247         }
1248     }
1249 }
1250 
1251 void RSRenderNode::ProcessTransitionBeforeChildren(RSPaintFilterCanvas& canvas)
1252 {
1253     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1254         DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::MASK, canvas);
1255         return;
1256     }
1257     ApplyBoundsGeometry(canvas);
1258     ApplyAlpha(canvas);
1259     RSPropertiesPainter::DrawMask(GetRenderProperties(), canvas);
1260 }
1261 
1262 void RSRenderNode::ProcessRenderBeforeChildren(RSPaintFilterCanvas& canvas)
1263 {
1264     RSRenderNode::ProcessTransitionBeforeChildren(canvas);
1265 }
1266 
1267 void RSRenderNode::ProcessTransitionAfterChildren(RSPaintFilterCanvas& canvas)
1268 {
1269     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1270         DrawPropertyDrawable(RSPropertyDrawableSlot::RESTORE_ALL, canvas);
1271         return;
1272     }
1273     canvas.RestoreStatus(renderNodeSaveCount_);
1274 }
1275 
1276 void RSRenderNode::ProcessRenderAfterChildren(RSPaintFilterCanvas& canvas)
1277 {
1278     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1279         DrawPropertyDrawable(RSPropertyDrawableSlot::RESTORE_ALL, canvas);
1280         return;
1281     }
1282     canvas.RestoreStatus(renderNodeSaveCount_);
1283 }
1284 
1285 void RSRenderNode::AddModifier(const std::shared_ptr<RSRenderModifier>& modifier, bool isSingleFrameComposer)
1286 {
1287     if (!modifier) {
1288         return;
1289     }
1290     SetDirty();
1291     if (RSSystemProperties::GetSingleFrameComposerEnabled() &&
1292         GetNodeIsSingleFrameComposer() && isSingleFrameComposer) {
1293         if (singleFrameComposer_ == nullptr) {
1294             singleFrameComposer_ = std::make_shared<RSSingleFrameComposer>();
1295         }
1296         singleFrameComposer_->SingleFrameAddModifier(modifier);
1297         return;
1298     }
1299     if (modifier->GetType() == RSModifierType::BOUNDS || modifier->GetType() == RSModifierType::FRAME) {
1300         AddGeometryModifier(modifier);
1301     } else if (modifier->GetType() < RSModifierType::CUSTOM) {
1302         modifiers_.emplace(modifier->GetPropertyId(), modifier);
1303     } else {
1304         modifier->SetSingleFrameModifier(false);
1305         renderContent_->drawCmdModifiers_[modifier->GetType()].emplace_back(modifier);
1306     }
1307     modifier->GetProperty()->Attach(shared_from_this());
1308 }
1309 
1310 void RSRenderNode::AddGeometryModifier(const std::shared_ptr<RSRenderModifier>& modifier)
1311 {
1312     // bounds and frame modifiers must be unique
1313     if (modifier->GetType() == RSModifierType::BOUNDS) {
1314         if (boundsModifier_ == nullptr) {
1315             boundsModifier_ = modifier;
1316         } else {
1317             boundsModifier_->Update(modifier->GetProperty(), false);
1318         }
1319         modifiers_.emplace(modifier->GetPropertyId(), boundsModifier_);
1320     }
1321 
1322     if (modifier->GetType() == RSModifierType::FRAME) {
1323         if (frameModifier_ == nullptr) {
1324             frameModifier_ = modifier;
1325         } else {
1326             frameModifier_->Update(modifier->GetProperty(), false);
1327         }
1328         modifiers_.emplace(modifier->GetPropertyId(), frameModifier_);
1329     }
1330 }
1331 
1332 void RSRenderNode::RemoveModifier(const PropertyId& id)
1333 {
1334     SetDirty();
1335     auto it = modifiers_.find(id);
1336     if (it != modifiers_.end()) {
1337         if (it->second) {
1338             AddDirtyType(it->second->GetType());
1339         }
1340         modifiers_.erase(it);
1341         return;
1342     }
1343     for (auto& [type, modifiers] : renderContent_->drawCmdModifiers_) {
1344         modifiers.remove_if([id](const auto& modifier) -> bool {
1345             return modifier ? modifier->GetPropertyId() == id : true;
1346         });
1347     }
1348 }
1349 
1350 void RSRenderNode::DumpNodeInfo(DfxString& log)
1351 {
1352 #ifndef USE_ROSEN_DRAWING
1353     for (const auto& [type, modifiers] : renderContent_->drawCmdModifiers_) {
1354         for (auto modifier : modifiers) {
1355             modifier->DumpPicture(log);
1356         }
1357     }
1358 #else
1359 // Drawing is not supported
1360 #endif
1361 }
1362 
1363 bool RSRenderNode::ApplyModifiers()
1364 {
1365     // quick reject test
1366 #ifndef USE_ROSEN_DRAWING
1367     if (!RSRenderNode::IsDirty() || dirtyTypes_.empty()) {
1368 #else
1369     if (!RSRenderNode::IsDirty() || dirtyTypes_.none()) {
1370 #endif
1371         return false;
1372     }
1373     const auto prevPositionZ = GetRenderProperties().GetPositionZ();
1374 
1375     // Reset and re-apply all modifiers
1376     RSModifierContext context = { GetMutableRenderProperties() };
1377 
1378     // Reset before apply modifiers
1379     GetMutableRenderProperties().ResetProperty(dirtyTypes_);
1380 
1381     // Apply modifiers
1382     for (auto& [id, modifier] : modifiers_) {
1383 #ifndef USE_ROSEN_DRAWING
1384         if (!dirtyTypes_.count(modifier->GetType())) {
1385 #else
1386         if (!dirtyTypes_.test(static_cast<size_t>(modifier->GetType()))) {
1387 #endif
1388             continue;
1389         }
1390         modifier->Apply(context);
1391         if (!BASIC_GEOTRANSFORM_ANIMATION_TYPE.count(modifier->GetType())) {
1392             isOnlyBasicGeoTransform_ = false;
1393         }
1394     }
1395     // execute hooks
1396     GetMutableRenderProperties().OnApplyModifiers();
1397     OnApplyModifiers();
1398 
1399 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
1400     if (auto& manager = GetRenderProperties().GetFilterCacheManager(false);
1401         manager != nullptr &&
1402 #ifndef USE_ROSEN_DRAWING
1403         (dirtyTypes_.count(RSModifierType::BACKGROUND_COLOR) || dirtyTypes_.count(RSModifierType::BG_IMAGE))) {
1404 #else
1405         (dirtyTypes_.test(static_cast<size_t>(RSModifierType::BACKGROUND_COLOR)) ||
1406         dirtyTypes_.test(static_cast<size_t>(RSModifierType::BG_IMAGE)))) {
1407 #endif
1408         manager->InvalidateCache();
1409     }
1410     if (auto& manager = GetRenderProperties().GetFilterCacheManager(true)) {
1411         manager->InvalidateCache();
1412     }
1413 
1414     if (RSSystemProperties::GetPropertyDrawableEnable()) {
1415         // Generate drawable
1416         UpdateDrawableVec();
1417     }
1418 #endif
1419 
1420     // update state
1421 #ifndef USE_ROSEN_DRAWING
1422     dirtyTypes_.clear();
1423 #else
1424     dirtyTypes_.reset();
1425 #endif
1426     UpdateShouldPaint();
1427 
1428     // update rate decider scale reference size.
1429     animationManager_.SetRateDeciderScaleSize(GetRenderProperties().GetBoundsWidth(),
1430         GetRenderProperties().GetBoundsHeight());
1431 
1432     // return true if positionZ changed
1433     return GetRenderProperties().GetPositionZ() != prevPositionZ;
1434 }
1435 
1436 void RSRenderNode::UpdateDrawableVec()
1437 {
1438 #ifndef ROSEN_ARKUI_X
1439     // Collect dirty slots
1440     auto dirtySlots = RSPropertyDrawable::GenerateDirtySlots(GetRenderProperties(), dirtyTypes_);
1441     if (!GetIsUsedBySubThread()) {
1442         UpdateDrawableVecInternal(dirtySlots);
1443     } else if (auto context = context_.lock()) {
1444         context->PostTask([weakPtr = weak_from_this(), dirtySlots]() {
1445             if (auto node = weakPtr.lock()) {
1446                 node->UpdateDrawableVecInternal(dirtySlots);
1447             }
1448         });
1449     } else {
1450         ROSEN_LOGI("%{public}s GetIsUsedBySubThread[%{public}d].", __func__, GetIsUsedBySubThread());
1451         UpdateDrawableVecInternal(dirtySlots);
1452     }
1453 #endif
1454 }
1455 
1456 void RSRenderNode::UpdateDrawableVecInternal(std::unordered_set<RSPropertyDrawableSlot> dirtySlots)
1457 {
1458 #ifndef ROSEN_ARKUI_X
1459      // initialize necessary save/clip/restore
1460     if (drawableVecStatus_ == 0) {
1461         RSPropertyDrawable::InitializeSaveRestore(*renderContent_, renderContent_->propertyDrawablesVec_);
1462     }
1463     // Update or regenerate drawable
1464     bool drawableChanged =
1465         RSPropertyDrawable::UpdateDrawableVec(*renderContent_, renderContent_->propertyDrawablesVec_, dirtySlots);
1466     // if 1. first initialized or 2. any drawables changed, update save/clip/restore
1467     if (drawableChanged || drawableVecStatus_ == 0) {
1468         RSPropertyDrawable::UpdateSaveRestore(
1469             *renderContent_, renderContent_->propertyDrawablesVec_, drawableVecStatus_);
1470     }
1471 #endif
1472 }
1473 
1474 #ifndef USE_ROSEN_DRAWING
1475 void RSRenderNode::UpdateEffectRegion(std::optional<SkIRect>& region, bool isForced)
1476 #else
1477 void RSRenderNode::UpdateEffectRegion(std::optional<Drawing::RectI>& region, bool isForced)
1478 #endif
1479 {
1480     if (!region.has_value()) {
1481         return;
1482     }
1483     const auto& property = GetRenderProperties();
1484     if (!isForced && !property.GetUseEffect()) {
1485         return;
1486     }
1487 
1488     auto absRect = property.GetBoundsGeometry()->GetAbsRect();
1489 #ifndef USE_ROSEN_DRAWING
1490     region->join(SkIRect::MakeXYWH(absRect.GetLeft(), absRect.GetTop(), absRect.GetWidth(), absRect.GetHeight()));
1491 #else
1492     region->Join(Drawing::RectI(absRect.GetLeft(), absRect.GetTop(), absRect.GetRight(), absRect.GetBottom()));
1493 #endif
1494 }
1495 
1496 std::shared_ptr<RSRenderModifier> RSRenderNode::GetModifier(const PropertyId& id)
1497 {
1498     if (modifiers_.count(id)) {
1499         return modifiers_[id];
1500     }
1501     for (const auto& [type, modifiers] : renderContent_->drawCmdModifiers_) {
1502         auto it = std::find_if(modifiers.begin(), modifiers.end(),
1503             [id](const auto& modifier) -> bool { return modifier->GetPropertyId() == id; });
1504         if (it != modifiers.end()) {
1505             return *it;
1506         }
1507     }
1508     return nullptr;
1509 }
1510 
1511 void RSRenderNode::FilterModifiersByPid(pid_t pid)
1512 {
1513     // remove all modifiers added by given pid (by matching higher 32 bits of node id)
1514     EraseIf(modifiers_, [pid](const auto& pair) -> bool { return ExtractPid(pair.first) == pid; });
1515 
1516     // remove all modifiers added by given pid (by matching higher 32 bits of node id)
1517     for (auto& [type, modifiers] : renderContent_->drawCmdModifiers_) {
1518         modifiers.remove_if(
1519             [pid](const auto& it) -> bool { return ExtractPid(it->GetPropertyId()) == pid; });
1520     }
1521 }
1522 
1523 bool RSRenderNode::ShouldPaint() const
1524 {
1525     return shouldPaint_;
1526 }
1527 
1528 void RSRenderNode::UpdateShouldPaint()
1529 {
1530     // node should be painted if either it is visible or it has disappearing transition animation, but only when its
1531     // alpha is not zero
1532     shouldPaint_ = (GetRenderProperties().GetAlpha() > 0.0f) &&
1533         (GetRenderProperties().GetVisible() || HasDisappearingTransition(false));
1534 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
1535     if (!shouldPaint_) {
1536         // clear filter cache when node is not visible
1537         GetMutableRenderProperties().ClearFilterCache();
1538         GetMutableRenderProperties().ReleaseColorPickerTaskShadow();
1539     }
1540 #endif
1541 }
1542 
1543 void RSRenderNode::SetSharedTransitionParam(const std::optional<SharedTransitionParam>&& sharedTransitionParam)
1544 {
1545     if (!sharedTransitionParam_.has_value() && !sharedTransitionParam.has_value()) {
1546         // both are empty, do nothing
1547         return;
1548     }
1549     sharedTransitionParam_ = sharedTransitionParam;
1550     SetDirty();
1551 }
1552 
1553 const std::optional<RSRenderNode::SharedTransitionParam>& RSRenderNode::GetSharedTransitionParam() const
1554 {
1555     return sharedTransitionParam_;
1556 }
1557 
1558 void RSRenderNode::SetGlobalAlpha(float alpha)
1559 {
1560     if (globalAlpha_ == alpha) {
1561         return;
1562     }
1563     if ((ROSEN_EQ(globalAlpha_, 1.0f) && alpha != 1.0f) ||
1564         (ROSEN_EQ(alpha, 1.0f) && globalAlpha_ != 1.0f)) {
1565         OnAlphaChanged();
1566     }
1567     globalAlpha_ = alpha;
1568 }
1569 
1570 float RSRenderNode::GetGlobalAlpha() const
1571 {
1572     return globalAlpha_;
1573 }
1574 
1575 void RSRenderNode::SetBootAnimation(bool isBootAnimation)
1576 {
1577     ROSEN_LOGD("SetBootAnimation:: id:%{public}" PRIu64 "isBootAnimation %{public}d",
1578         GetId(), isBootAnimation);
1579     isBootAnimation_ = isBootAnimation;
1580 }
1581 
1582 bool RSRenderNode::GetBootAnimation() const
1583 {
1584     return isBootAnimation_;
1585 }
1586 
1587 bool RSRenderNode::NeedInitCacheSurface() const
1588 {
1589     auto cacheType = GetCacheType();
1590     int width = 0;
1591     int height = 0;
1592     if (cacheType == CacheType::ANIMATE_PROPERTY &&
1593         GetRenderProperties().IsShadowValid() && !GetRenderProperties().IsSpherizeValid()) {
1594         const RectF boundsRect = GetRenderProperties().GetBoundsRect();
1595         RRect rrect = RRect(boundsRect, {0, 0, 0, 0});
1596         RectI shadowRect;
1597         RSPropertiesPainter::GetShadowDirtyRect(shadowRect, GetRenderProperties(), &rrect, false);
1598         width = shadowRect.GetWidth();
1599         height = shadowRect.GetHeight();
1600     } else {
1601         Vector2f size = GetOptionalBufferSize();
1602         width =  size.x_;
1603         height = size.y_;
1604     }
1605     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1606     if (cacheSurface_ == nullptr) {
1607         return true;
1608     }
1609 #ifndef USE_ROSEN_DRAWING
1610     return cacheSurface_->width() != width || cacheSurface_->height() !=height;
1611 #else
1612     auto cacheCanvas = cacheSurface_->GetCanvas();
1613     if (cacheCanvas == nullptr) {
1614         return true;
1615     }
1616     return cacheCanvas->GetWidth() != width || cacheCanvas->GetHeight() != height;
1617 #endif
1618 }
1619 
1620 bool RSRenderNode::NeedInitCacheCompletedSurface() const
1621 {
1622     Vector2f size = GetOptionalBufferSize();
1623     int width = static_cast<int>(size.x_);
1624     int height = static_cast<int>(size.y_);
1625     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1626     if (cacheCompletedSurface_ == nullptr) {
1627         return true;
1628     }
1629 #ifndef USE_ROSEN_DRAWING
1630     return cacheCompletedSurface_->width() != width || cacheCompletedSurface_->height() !=height;
1631 #else
1632     auto cacheCanvas = cacheCompletedSurface_->GetCanvas();
1633     if (cacheCanvas == nullptr) {
1634         return true;
1635     }
1636     return cacheCanvas->GetWidth() != width || cacheCanvas->GetHeight() != height;
1637 #endif
1638 }
1639 
1640 #ifndef USE_ROSEN_DRAWING
1641 #ifdef NEW_SKIA
1642 void RSRenderNode::InitCacheSurface(GrRecordingContext* grContext, ClearCacheSurfaceFunc func, uint32_t threadIndex)
1643 #else
1644 void RSRenderNode::InitCacheSurface(GrContext* grContext, ClearCacheSurfaceFunc func, uint32_t threadIndex)
1645 #endif
1646 #else
1647 void RSRenderNode::InitCacheSurface(Drawing::GPUContext* gpuContext, ClearCacheSurfaceFunc func, uint32_t threadIndex)
1648 #endif
1649 {
1650     if (func) {
1651         cacheSurfaceThreadIndex_ = threadIndex;
1652         if (!clearCacheSurfaceFunc_) {
1653             clearCacheSurfaceFunc_ = func;
1654         }
1655         if (cacheSurface_) {
1656             func(std::move(cacheSurface_), nullptr,
1657                 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
1658             std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1659             cacheSurface_ = nullptr;
1660         }
1661     } else {
1662         cacheSurface_ = nullptr;
1663     }
1664     auto cacheType = GetCacheType();
1665     float width = 0.0f, height = 0.0f;
1666     Vector2f size = GetOptionalBufferSize();
1667     boundsWidth_ = size.x_;
1668     boundsHeight_ = size.y_;
1669     if (cacheType == CacheType::ANIMATE_PROPERTY &&
1670         GetRenderProperties().IsShadowValid() && !GetRenderProperties().IsSpherizeValid()) {
1671         const RectF boundsRect = GetRenderProperties().GetBoundsRect();
1672         RRect rrect = RRect(boundsRect, {0, 0, 0, 0});
1673         RectI shadowRect;
1674         RSPropertiesPainter::GetShadowDirtyRect(shadowRect, GetRenderProperties(), &rrect, false);
1675         width = shadowRect.GetWidth();
1676         height = shadowRect.GetHeight();
1677         shadowRectOffsetX_ = -shadowRect.GetLeft();
1678         shadowRectOffsetY_ = -shadowRect.GetTop();
1679     } else {
1680         width = boundsWidth_;
1681         height = boundsHeight_;
1682     }
1683 #ifndef USE_ROSEN_DRAWING
1684 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
1685     if (grContext == nullptr) {
1686         if (func) {
1687             func(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
1688                 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
1689             ClearCacheSurface();
1690         }
1691         return;
1692     }
1693 #ifdef RS_ENABLE_GL
1694     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
1695         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
1696         SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
1697         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1698         cacheSurface_ = SkSurface::MakeRenderTarget(grContext, SkBudgeted::kYes, info);
1699     }
1700 #endif
1701 #ifdef RS_ENABLE_VK
1702     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
1703         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
1704         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1705         cacheBackendTexture_ = MakeBackendTexture(width, height);
1706         if (!cacheBackendTexture_.isValid()) {
1707             if (func) {
1708                 func(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
1709                     cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
1710                 ClearCacheSurface();
1711             }
1712             return;
1713         }
1714         GrVkImageInfo imageInfo;
1715         cacheBackendTexture_.getVkImageInfo(&imageInfo);
1716         cacheCleanupHelper_ = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
1717             imageInfo.fImage, imageInfo.fAlloc.fMemory);
1718         SkSurfaceProps props(0, SkPixelGeometry::kUnknown_SkPixelGeometry);
1719         cacheSurface_ = SkSurface::MakeFromBackendTexture(
1720             grContext, cacheBackendTexture_, kBottomLeft_GrSurfaceOrigin, 1, kRGBA_8888_SkColorType,
1721             SkColorSpace::MakeSRGB(), &props, NativeBufferUtils::DeleteVkImage, cacheCleanupHelper_);
1722     }
1723 #endif
1724 #else
1725     cacheSurface_ = SkSurface::MakeRasterN32Premul(width, height);
1726 #endif
1727 #else // USE_ROSEN_DRAWING
1728 #if (defined (RS_ENABLE_GL) || defined (RS_ENABLE_VK)) && (defined RS_ENABLE_EGLIMAGE)
1729     if (gpuContext == nullptr) {
1730         if (func) {
1731             func(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
1732                 cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
1733             ClearCacheSurface();
1734         }
1735         return;
1736     }
1737 #ifdef RS_ENABLE_GL
1738     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
1739         OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
1740         Drawing::ImageInfo info = Drawing::ImageInfo::MakeN32Premul(width, height);
1741         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1742         cacheSurface_ = Drawing::Surface::MakeRenderTarget(gpuContext, true, info);
1743     }
1744 #endif
1745 #ifdef RS_ENABLE_VK
1746     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
1747         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
1748         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1749         cacheBackendTexture_ = MakeBackendTexture(width, height);
1750         auto vkTextureInfo = cacheBackendTexture_.GetTextureInfo().GetVKTextureInfo();
1751         if (!cacheBackendTexture_.isValid() || !vkTextureInfo) {
1752             if (func) {
1753                 func(std::move(cacheSurface_), std::move(cacheCompletedSurface_),
1754                     cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
1755                 ClearCacheSurface();
1756             }
1757             return;
1758         }
1759         cacheCleanupHelper_ = new NativeBufferUtils::VulkanCleanupHelper(RsVulkanContext::GetSingleton(),
1760             vkTextureInfo->vkImage, vkTextureInfo->vkAlloc.memory);
1761         cacheSurface_ = Drawing::Surface::MakeFromBackendTexture(
1762             gpuContext, cacheBackendTexture_.GetTextureInfo(), Drawing::TextureOrigin::BOTTOM_LEFT,
1763             1, Drawing::ColorType::COLORTYPE_RGBA_8888, nullptr,
1764             NativeBufferUtils::DeleteVkImage, cacheCleanupHelper_);
1765     }
1766 #endif
1767 #else
1768     cacheSurface_ = Drawing::Surface::MakeRasterN32Premul(width, height);
1769 #endif
1770 #endif // USE_ROSEN_DRAWING
1771 }
1772 
1773 bool RSRenderNode::IsCacheSurfaceValid() const
1774 {
1775     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1776     return  (cacheCompletedSurface_ != nullptr);
1777 }
1778 
1779 Vector2f RSRenderNode::GetOptionalBufferSize() const
1780 {
1781     const auto& modifier = boundsModifier_ ? boundsModifier_ : frameModifier_;
1782     if (!modifier) {
1783         return {0.0f, 0.0f};
1784     }
1785     auto renderProperty = std::static_pointer_cast<RSRenderAnimatableProperty<Vector4f>>(modifier->GetProperty());
1786     auto vector4f = renderProperty->Get();
1787     // bounds vector4f: x y z w -> left top width height
1788     return { vector4f.z_, vector4f.w_ };
1789 }
1790 
1791 #ifndef USE_ROSEN_DRAWING
1792 void RSRenderNode::DrawCacheSurface(RSPaintFilterCanvas& canvas, uint32_t threadIndex, bool isUIFirst)
1793 {
1794     if (ROSEN_EQ(boundsWidth_, 0.f) || ROSEN_EQ(boundsHeight_, 0.f)) {
1795         return;
1796     }
1797     auto cacheType = GetCacheType();
1798     canvas.save();
1799     Vector2f size = GetOptionalBufferSize();
1800     float scaleX = size.x_ / boundsWidth_;
1801     float scaleY = size.y_ / boundsHeight_;
1802     canvas.scale(scaleX, scaleY);
1803     auto cacheImage = GetCompletedImage(canvas, threadIndex, isUIFirst);
1804     if (cacheImage == nullptr) {
1805         canvas.restore();
1806         return;
1807     }
1808     auto samplingOptions = SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kNone);
1809     if (RSSystemProperties::GetRecordingEnabled()) {
1810         if (cacheImage->isTextureBacked()) {
1811             RS_LOGI("RSRenderNode::DrawCacheSurface convert cacheImage from texture to raster image");
1812             cacheImage = cacheImage->makeRasterImage();
1813         }
1814     }
1815     if ((cacheType == CacheType::ANIMATE_PROPERTY && GetRenderProperties().IsShadowValid()) || isUIFirst) {
1816         auto surfaceNode = ReinterpretCastTo<RSSurfaceRenderNode>();
1817         Vector2f gravityTranslate = surfaceNode ?
1818             surfaceNode->GetGravityTranslate(cacheImage->Width(), cacheImage->Height()) : Vector2f(0.0f, 0.0f);
1819         canvas.drawImage(cacheImage, -shadowRectOffsetX_ * scaleX + gravityTranslate.x_,
1820             -shadowRectOffsetY_ * scaleY + gravityTranslate.y_, samplingOptions);
1821     } else {
1822         canvas.drawImage(cacheImage, 0.f, 0.f, samplingOptions);
1823     }
1824     canvas.restore();
1825 }
1826 
1827 sk_sp<SkImage> RSRenderNode::GetCompletedImage(RSPaintFilterCanvas& canvas, uint32_t threadIndex, bool isUIFirst)
1828 {
1829     if (isUIFirst) {
1830 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
1831         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1832         if (!cacheCompletedBackendTexture_.isValid()) {
1833             RS_LOGE("invalid grBackendTexture_");
1834             return nullptr;
1835         }
1836 #ifdef RS_ENABLE_VK
1837         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
1838             OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
1839             if (!cacheCompletedSurface_ || !cacheCompletedCleanupHelper_) {
1840                 return nullptr;
1841             }
1842         }
1843 #endif
1844         sk_sp<SkImage> image = nullptr;
1845 #ifdef RS_ENABLE_GL
1846         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
1847             OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
1848             image = SkImage::MakeFromTexture(canvas.recordingContext(), cacheCompletedBackendTexture_,
1849                 kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr);
1850         }
1851 #endif
1852 
1853 #ifdef RS_ENABLE_VK
1854         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
1855             OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
1856             image = SkImage::MakeFromTexture(canvas.recordingContext(), cacheCompletedBackendTexture_,
1857                 kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr,
1858                 NativeBufferUtils::DeleteVkImage, cacheCompletedCleanupHelper_->Ref());
1859         }
1860 #endif
1861         return image;
1862 #endif
1863     }
1864 
1865     if (!cacheCompletedSurface_) {
1866         RS_LOGE("DrawCacheSurface invalid cacheCompletedSurface");
1867         return nullptr;
1868     }
1869     auto completeImage = cacheCompletedSurface_->makeImageSnapshot();
1870     if (!completeImage) {
1871         RS_LOGE("Get complete image failed");
1872         return nullptr;
1873     }
1874     if (threadIndex == completedSurfaceThreadIndex_) {
1875         return completeImage;
1876     }
1877 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
1878     GrSurfaceOrigin origin = kBottomLeft_GrSurfaceOrigin;
1879     auto backendTexture = completeImage->getBackendTexture(false, &origin);
1880     if (!backendTexture.isValid()) {
1881         RS_LOGE("get backendTexture failed");
1882         return nullptr;
1883     }
1884     auto cacheImage = SkImage::MakeFromTexture(canvas.recordingContext(), backendTexture, origin,
1885         completeImage->colorType(), completeImage->alphaType(), nullptr);
1886     return cacheImage;
1887 #else
1888     return completeImage;
1889 #endif
1890 }
1891 #else
1892 void RSRenderNode::DrawCacheSurface(RSPaintFilterCanvas& canvas, uint32_t threadIndex, bool isUIFirst)
1893 {
1894     if (ROSEN_EQ(boundsWidth_, 0.f) || ROSEN_EQ(boundsHeight_, 0.f)) {
1895         return;
1896     }
1897     auto cacheType = GetCacheType();
1898     canvas.Save();
1899     Vector2f size = GetOptionalBufferSize();
1900     float scaleX = size.x_ / boundsWidth_;
1901     float scaleY = size.y_ / boundsHeight_;
1902     canvas.Scale(scaleX, scaleY);
1903     auto cacheImage = GetCompletedImage(canvas, threadIndex, isUIFirst);
1904     if (cacheImage == nullptr) {
1905         canvas.Restore();
1906         return;
1907     }
1908     auto samplingOptions = Drawing::SamplingOptions(Drawing::FilterMode::LINEAR, Drawing::MipmapMode::NONE);
1909     if (RSSystemProperties::GetRecordingEnabled()) {
1910         if (cacheImage->IsTextureBacked()) {
1911             RS_LOGI("RSRenderNode::DrawCacheSurface convert cacheImage from texture to raster image");
1912             cacheImage = cacheImage->MakeRasterImage();
1913         }
1914     }
1915     Drawing::Brush brush;
1916     canvas.AttachBrush(brush);
1917     if ((cacheType == CacheType::ANIMATE_PROPERTY && GetRenderProperties().IsShadowValid()) || isUIFirst) {
1918         auto surfaceNode = ReinterpretCastTo<RSSurfaceRenderNode>();
1919         Vector2f gravityTranslate = surfaceNode ?
1920             surfaceNode->GetGravityTranslate(cacheImage->GetWidth(), cacheImage->GetHeight()) : Vector2f(0.0f, 0.0f);
1921         canvas.DrawImage(*cacheImage, -shadowRectOffsetX_ * scaleX + gravityTranslate.x_,
1922             -shadowRectOffsetY_ * scaleY + gravityTranslate.y_, samplingOptions);
1923     } else {
1924         if (canvas.GetTotalMatrix().HasPerspective()) {
1925             // In case of perspective transformation, make dstRect 1px outset to anti-alias
1926             Drawing::Rect dst(0, 0, cacheImage->GetWidth(), cacheImage->GetHeight());
1927             dst.MakeOutset(1, 1);
1928             canvas.DrawImageRect(*cacheImage, dst, samplingOptions);
1929         } else {
1930             canvas.DrawImage(*cacheImage, 0.0, 0.0, samplingOptions);
1931         }
1932     }
1933     canvas.DetachBrush();
1934     canvas.Restore();
1935 }
1936 
1937 std::shared_ptr<Drawing::Image> RSRenderNode::GetCompletedImage(
1938     RSPaintFilterCanvas& canvas, uint32_t threadIndex, bool isUIFirst)
1939 {
1940     if (isUIFirst) {
1941 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1942         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
1943         if (!cacheCompletedBackendTexture_.IsValid()) {
1944             RS_LOGE("invalid grBackendTexture_");
1945             return nullptr;
1946         }
1947 #ifdef RS_ENABLE_VK
1948         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
1949             OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
1950             if (!cacheCompletedSurface_ || !cacheCompletedCleanupHelper_) {
1951                 return nullptr;
1952             }
1953         }
1954 #endif
1955         auto image = std::make_shared<Drawing::Image>();
1956         Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
1957         Drawing::BitmapFormat info = Drawing::BitmapFormat{ Drawing::COLORTYPE_RGBA_8888,
1958             Drawing::ALPHATYPE_PREMUL };
1959 #ifdef RS_ENABLE_GL
1960         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::VULKAN &&
1961             OHOS::Rosen::RSSystemProperties::GetGpuApiType() != OHOS::Rosen::GpuApiType::DDGR) {
1962             image->BuildFromTexture(*canvas.GetGPUContext(), cacheCompletedBackendTexture_.GetTextureInfo(),
1963                 origin, info, nullptr);
1964         }
1965 #endif
1966 
1967 #ifdef RS_ENABLE_VK
1968         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
1969             OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
1970             image->BuildFromTexture(*canvas.GetGPUContext(), cacheCompletedBackendTexture_.GetTextureInfo(),
1971                 origin, info, nullptr,
1972                 NativeBufferUtils::DeleteVkImage, cacheCompletedCleanupHelper_->Ref());
1973         }
1974 #endif
1975         return image;
1976 #endif
1977     }
1978 
1979     if (!cacheCompletedSurface_) {
1980         RS_LOGE("DrawCacheSurface invalid cacheCompletedSurface");
1981         return nullptr;
1982     }
1983     auto completeImage = cacheCompletedSurface_->GetImageSnapshot();
1984     if (!completeImage) {
1985         RS_LOGE("Get complete image failed");
1986         return nullptr;
1987     }
1988     if (threadIndex == completedSurfaceThreadIndex_) {
1989         return completeImage;
1990     }
1991 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
1992     Drawing::TextureOrigin origin = Drawing::TextureOrigin::BOTTOM_LEFT;
1993     auto backendTexture = completeImage->GetBackendTexture(false, &origin);
1994     if (!backendTexture.IsValid()) {
1995         RS_LOGE("get backendTexture failed");
1996         return nullptr;
1997     }
1998     auto cacheImage = std::make_shared<Drawing::Image>();
1999     Drawing::BitmapFormat info =
2000         Drawing::BitmapFormat{ completeImage->GetColorType(), completeImage->GetAlphaType() };
2001     bool ret = cacheImage->BuildFromTexture(*canvas.GetGPUContext(), backendTexture.GetTextureInfo(),
2002         origin, info, nullptr);
2003     if (!ret) {
2004         RS_LOGE("RSRenderNode::GetCompletedImage image BuildFromTexture failed");
2005         return nullptr;
2006     }
2007     return cacheImage;
2008 #else
2009     return completeImage;
2010 #endif
2011 }
2012 #endif
2013 
2014 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
2015 void RSRenderNode::UpdateBackendTexture()
2016 {
2017     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2018     if (cacheSurface_ == nullptr) {
2019         return;
2020     }
2021 #ifndef USE_ROSEN_DRAWING
2022     cacheBackendTexture_
2023         = cacheSurface_->getBackendTexture(SkSurface::BackendHandleAccess::kFlushRead_BackendHandleAccess);
2024 #else
2025     cacheBackendTexture_ = cacheSurface_->GetBackendTexture();
2026 #endif
2027 }
2028 #endif
2029 
2030 #ifndef USE_ROSEN_DRAWING
2031 sk_sp<SkSurface> RSRenderNode::GetCompletedCacheSurface(uint32_t threadIndex, bool needCheckThread,
2032     bool releaseAfterGet)
2033 #else
2034 std::shared_ptr<Drawing::Surface> RSRenderNode::GetCompletedCacheSurface(uint32_t threadIndex, bool needCheckThread,
2035     bool releaseAfterGet)
2036 #endif
2037 {
2038     {
2039         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2040         if (releaseAfterGet) {
2041             return std::move(cacheCompletedSurface_);
2042         }
2043         if (!needCheckThread || completedSurfaceThreadIndex_ == threadIndex || !cacheCompletedSurface_) {
2044             return cacheCompletedSurface_;
2045         }
2046     }
2047 
2048     // freeze cache scene
2049     ClearCacheSurfaceInThread();
2050     return nullptr;
2051 }
2052 
2053 void RSRenderNode::ClearCacheSurfaceInThread()
2054 {
2055     if (clearCacheSurfaceFunc_) {
2056         clearCacheSurfaceFunc_(std::move(cacheSurface_), std::move(cacheCompletedSurface_), cacheSurfaceThreadIndex_,
2057             completedSurfaceThreadIndex_);
2058     }
2059     ClearCacheSurface();
2060 }
2061 
2062 #ifndef USE_ROSEN_DRAWING
2063 sk_sp<SkSurface> RSRenderNode::GetCacheSurface(uint32_t threadIndex, bool needCheckThread, bool releaseAfterGet)
2064 #else
2065 std::shared_ptr<Drawing::Surface> RSRenderNode::GetCacheSurface(uint32_t threadIndex, bool needCheckThread,
2066     bool releaseAfterGet)
2067 #endif
2068 {
2069     {
2070         std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2071         if (releaseAfterGet) {
2072             return std::move(cacheSurface_);
2073         }
2074         if (!needCheckThread || cacheSurfaceThreadIndex_ == threadIndex || !cacheSurface_) {
2075             return cacheSurface_;
2076         }
2077     }
2078 
2079     // freeze cache scene
2080     ClearCacheSurfaceInThread();
2081     return nullptr;
2082 }
2083 
2084 void RSRenderNode::CheckGroupableAnimation(const PropertyId& id, bool isAnimAdd)
2085 {
2086     if (id <= 0 || GetType() != RSRenderNodeType::CANVAS_NODE) {
2087         return;
2088     }
2089     auto context = GetContext().lock();
2090     if (!RSSystemProperties::GetAnimationCacheEnabled() ||
2091         !context || !context->GetNodeMap().IsResidentProcessNode(GetId())) {
2092         return;
2093     }
2094     auto target = modifiers_.find(id);
2095     if (target == modifiers_.end() || !target->second) {
2096         return;
2097     }
2098     if (isAnimAdd) {
2099         if (GROUPABLE_ANIMATION_TYPE.count(target->second->GetType())) {
2100             MarkNodeGroup(NodeGroupType::GROUPED_BY_ANIM, true, false);
2101         } else if (CACHEABLE_ANIMATION_TYPE.count(target->second->GetType())) {
2102             hasCacheableAnim_ = true;
2103         }
2104         return;
2105     }
2106     bool hasGroupableAnim = false;
2107     hasCacheableAnim_ = false;
2108     for (auto& [_, animation] : animationManager_.animations_) {
2109         if (!animation || id == animation->GetPropertyId()) {
2110             continue;
2111         }
2112         auto itr = modifiers_.find(animation->GetPropertyId());
2113         if (itr == modifiers_.end() || !itr->second) {
2114             continue;
2115         }
2116         hasGroupableAnim = (hasGroupableAnim || (GROUPABLE_ANIMATION_TYPE.count(itr->second->GetType()) != 0));
2117         hasCacheableAnim_ = (hasCacheableAnim_ || (CACHEABLE_ANIMATION_TYPE.count(itr->second->GetType()) != 0));
2118     }
2119     MarkNodeGroup(NodeGroupType::GROUPED_BY_ANIM, hasGroupableAnim, false);
2120 }
2121 
2122 bool RSRenderNode::IsForcedDrawInGroup() const
2123 {
2124     return nodeGroupType_ == NodeGroupType::GROUPED_BY_USER;
2125 }
2126 
2127 bool RSRenderNode::IsSuggestedDrawInGroup() const
2128 {
2129     return nodeGroupType_ != NodeGroupType::NONE;
2130 }
2131 
2132 void RSRenderNode::MarkNodeGroup(NodeGroupType type, bool isNodeGroup, bool includeProperty)
2133 {
2134     if (type >= nodeGroupType_) {
2135         if (isNodeGroup && type == NodeGroupType::GROUPED_BY_UI) {
2136             auto context = GetContext().lock();
2137             if (context && context->GetNodeMap().IsResidentProcessNode(GetId())) {
2138                 nodeGroupType_ = type;
2139                 SetDirty();
2140             }
2141         } else {
2142             nodeGroupType_ = isNodeGroup ? type : NodeGroupType::NONE;
2143             SetDirty();
2144         }
2145         nodeGroupIncludeProperty_ = includeProperty;
2146         if (type == NodeGroupType::GROUPED_BY_USER) {
2147             GetMutableRenderProperties().SetAlphaOffscreen(isNodeGroup);
2148         }
2149     }
2150 }
2151 
2152 bool RSRenderNode::IsNodeGroupIncludeProperty() const
2153 {
2154     return nodeGroupIncludeProperty_;
2155 }
2156 
2157 void RSRenderNode::MarkNodeSingleFrameComposer(bool isNodeSingleFrameComposer, pid_t pid)
2158 {
2159     isNodeSingleFrameComposer_ = isNodeSingleFrameComposer;
2160     appPid_ = pid;
2161 }
2162 
2163 bool RSRenderNode::GetNodeIsSingleFrameComposer() const
2164 {
2165     return isNodeSingleFrameComposer_;
2166 }
2167 
2168 void RSRenderNode::CheckDrawingCacheType()
2169 {
2170     if (nodeGroupType_ == NodeGroupType::NONE) {
2171         SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
2172     } else if (nodeGroupType_ == NodeGroupType::GROUPED_BY_USER) {
2173         SetDrawingCacheType(RSDrawingCacheType::FORCED_CACHE);
2174     } else {
2175         SetDrawingCacheType(RSDrawingCacheType::TARGETED_CACHE);
2176     }
2177 }
2178 
2179 void RSRenderNode::ResetFilterRectsInCache(const std::unordered_set<NodeId>& curRects)
2180 {
2181     curCacheFilterRects_ = curRects;
2182 }
2183 
2184 void RSRenderNode::GetFilterRectsInCache(std::unordered_map<NodeId, std::unordered_set<NodeId>>& allRects) const
2185 {
2186     if (!curCacheFilterRects_.empty()) {
2187         allRects.emplace(GetId(), curCacheFilterRects_);
2188     }
2189 }
2190 
2191 bool RSRenderNode::IsFilterRectsInCache() const
2192 {
2193     return !curCacheFilterRects_.empty();
2194 }
2195 
2196 RectI RSRenderNode::GetFilterRect() const
2197 {
2198     auto& properties = GetRenderProperties();
2199     auto geoPtr = (properties.GetBoundsGeometry());
2200     if (!geoPtr) {
2201         return {};
2202     }
2203     if (properties.GetClipBounds() != nullptr) {
2204 #ifndef USE_ROSEN_DRAWING
2205         auto filterRect = properties.GetClipBounds()->GetSkiaPath().getBounds();
2206         auto absRect = geoPtr->GetAbsMatrix().mapRect(filterRect);
2207         return {absRect.x(), absRect.y(), absRect.width(), absRect.height()};
2208 #else
2209         auto filterRect = properties.GetClipBounds()->GetDrawingPath().GetBounds();
2210         Drawing::Rect absRect;
2211         geoPtr->GetAbsMatrix().MapRect(absRect, filterRect);
2212         return {absRect.GetLeft(), absRect.GetTop(), absRect.GetWidth(), absRect.GetHeight()};
2213 #endif
2214     } else {
2215         return geoPtr->GetAbsRect();
2216     }
2217 }
2218 
2219 void RSRenderNode::UpdateFullScreenFilterCacheRect(
2220     RSDirtyRegionManager& dirtyManager, bool isForeground) const
2221 {
2222 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2223     auto& renderProperties = GetRenderProperties();
2224     auto& manager = renderProperties.GetFilterCacheManager(isForeground);
2225     // Record node's cache area if it has valid filter cache
2226     // If there are any invalid caches under full screen cache filter, the occlusion should be invalidated
2227     if (!manager->IsCacheValid() && dirtyManager.IsCacheableFilterRectEmpty()) {
2228         dirtyManager.InvalidateFilterCacheRect();
2229     } else if (ROSEN_EQ(GetGlobalAlpha(), 1.0f) && ROSEN_EQ(renderProperties.GetCornerRadius().x_, 0.0f) &&
2230         manager->GetCachedImageRegion() == dirtyManager.GetSurfaceRect() && !IsInstanceOf<RSEffectRenderNode>()) {
2231         // Only record full screen filter cache for occlusion calculation
2232         dirtyManager.UpdateCacheableFilterRect(manager->GetCachedImageRegion());
2233     }
2234 #endif
2235 }
2236 
2237 void RSRenderNode::UpdateFilterCacheManagerWithCacheRegion(
2238     RSDirtyRegionManager& dirtyManager, const std::optional<RectI>& clipRect)
2239 {
2240 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2241     if (!RSProperties::FilterCacheEnabled) {
2242         return;
2243     }
2244     auto& renderProperties = GetRenderProperties();
2245     if (!renderProperties.NeedFilter()) {
2246         return;
2247     }
2248     auto filterRect = GetFilterRect();
2249     if (clipRect.has_value()) {
2250         filterRect.IntersectRect(*clipRect);
2251     }
2252 
2253     // background filter
2254     if (auto& manager = renderProperties.GetFilterCacheManager(false)) {
2255         // invalidate cache if filter region is not inside of cached image region
2256         if (manager->IsCacheValid() && !filterRect.IsInsideOf(manager->GetCachedImageRegion())) {
2257             manager->UpdateCacheStateWithFilterRegion();
2258             if (auto context = GetContext().lock()) {
2259                 RS_TRACE_NAME_FMT("background filter of node Id:%" PRIu64 " is invalid", GetId());
2260                 context->MarkNeedPurge(ClearMemoryMoment::FILTER_INVALID, RSContext::PurgeType::STRONGLY);
2261             }
2262         }
2263         UpdateFullScreenFilterCacheRect(dirtyManager, false);
2264     }
2265     // foreground filter
2266     if (auto& manager = renderProperties.GetFilterCacheManager(true)) {
2267         // invalidate cache if filter region is not inside of cached image region
2268         if (manager->IsCacheValid() && !filterRect.IsInsideOf(manager->GetCachedImageRegion())) {
2269             manager->UpdateCacheStateWithFilterRegion();
2270             if (auto context = GetContext().lock()) {
2271                 RS_TRACE_NAME_FMT("foreground filter of node Id:%" PRIu64 " is invalid", GetId());
2272                 context->MarkNeedPurge(ClearMemoryMoment::FILTER_INVALID, RSContext::PurgeType::STRONGLY);
2273             }
2274         }
2275         UpdateFullScreenFilterCacheRect(dirtyManager, true);
2276     }
2277 #endif
2278 }
2279 
2280 void RSRenderNode::OnTreeStateChanged()
2281 {
2282     if (isOnTheTree_) {
2283         // Set dirty and force add to active node list, re-generate children list if needed
2284         SetDirty(true);
2285     }
2286 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2287     if (!isOnTheTree_) {
2288         // clear filter cache when node is removed from tree
2289         GetMutableRenderProperties().ClearFilterCache();
2290         GetMutableRenderProperties().ReleaseColorPickerTaskShadow();
2291     }
2292 #endif
2293 }
2294 
2295 bool RSRenderNode::HasDisappearingTransition(bool recursive) const
2296 {
2297     if (disappearingTransitionCount_ > 0) {
2298         return true;
2299     }
2300     if (recursive == false) {
2301         return false;
2302     }
2303     auto parent = GetParent().lock();
2304     if (parent == nullptr) {
2305         return false;
2306     }
2307     return parent->HasDisappearingTransition(true);
2308 }
2309 
2310 RSRenderNode::ChildrenListSharedPtr RSRenderNode::GetChildren() const
2311 {
2312     return std::atomic_load_explicit(&fullChildrenList_, std::memory_order_acquire);
2313 }
2314 
2315 RSRenderNode::ChildrenListSharedPtr RSRenderNode::GetSortedChildren() const
2316 {
2317     return std::atomic_load_explicit(&fullChildrenList_, std::memory_order_acquire);
2318 }
2319 
2320 std::shared_ptr<RSRenderNode> RSRenderNode::GetFirstChild() const
2321 {
2322     return children_.empty() ? nullptr : children_.front().lock();
2323 }
2324 
2325 void RSRenderNode::UpdateFullChildrenListIfNeeded()
2326 {
2327     if (!isFullChildrenListValid_) {
2328         GenerateFullChildrenList();
2329     } else if (!isChildrenSorted_) {
2330         ResortChildren();
2331     }
2332 }
2333 
2334 void RSRenderNode::GenerateFullChildrenList()
2335 {
2336     // both children_ and disappearingChildren_ are empty, no need to generate fullChildrenList_
2337     if (children_.empty() && disappearingChildren_.empty()) {
2338         auto prevFullChildrenList = fullChildrenList_;
2339         isFullChildrenListValid_ = true;
2340         isChildrenSorted_ = true;
2341         std::atomic_store_explicit(&fullChildrenList_, EmptyChildrenList, std::memory_order_release);
2342         return;
2343     }
2344 
2345     // Step 0: Initialize
2346     auto fullChildrenList = std::make_shared<std::vector<std::shared_ptr<RSRenderNode>>>();
2347 
2348     // Step 1: Copy all children into sortedChildren while checking and removing expired children.
2349     children_.remove_if([&](const auto& child) -> bool {
2350         auto existingChild = child.lock();
2351         if (existingChild == nullptr) {
2352             ROSEN_LOGI("RSRenderNode::GenerateSortedChildren removing expired child, this is rare but possible.");
2353             return true;
2354         }
2355         if (isContainBootAnimation_ && !existingChild->GetBootAnimation()) {
2356             ROSEN_LOGD("RSRenderNode::GenerateSortedChildren %{public}" PRIu64 " skip"
2357             " move not bootAnimation displaynode"
2358             "child(id %{public}" PRIu64 ")"" into children_", GetId(), existingChild->GetId());
2359             return false;
2360         }
2361         fullChildrenList->emplace_back(std::move(existingChild));
2362         return false;
2363     });
2364 
2365     // Step 2: Insert disappearing children into sortedChildren at their original position.
2366     // Note:
2367     //     1. We don't need to check if the disappearing transition is finished; it's already handled in
2368     //     RSRenderTransition::OnDetach.
2369     //     2. We don't need to check if the disappearing child is expired; it's already been checked when moving from
2370     //     children_ to disappearingChildren_. We hold ownership of the shared_ptr of the child after that.
2371     std::for_each(disappearingChildren_.begin(), disappearingChildren_.end(), [&](const auto& pair) -> void {
2372         auto& disappearingChild = pair.first;
2373         if (isContainBootAnimation_ && !disappearingChild->GetBootAnimation()) {
2374             ROSEN_LOGD("RSRenderNode::GenerateSortedChildren %{public}" PRIu64 " skip"
2375             " move not bootAnimation displaynode"
2376             "child(id %{public}" PRIu64 ")"" into disappearingChild", GetId(), disappearingChild->GetId());
2377             return;
2378         }
2379         const auto& origPos = pair.second;
2380         if (origPos < fullChildrenList->size()) {
2381             fullChildrenList->emplace(std::next(fullChildrenList->begin(), origPos), disappearingChild);
2382         } else {
2383             fullChildrenList->emplace_back(disappearingChild);
2384         }
2385     });
2386 
2387     // Step 3: Sort all children by z-order
2388     std::stable_sort(
2389         fullChildrenList->begin(), fullChildrenList->end(), [](const auto& first, const auto& second) -> bool {
2390         return first->GetRenderProperties().GetPositionZ() < second->GetRenderProperties().GetPositionZ();
2391     });
2392 
2393     // Keep a reference to fullChildrenList_ to prevent its deletion when swapping it
2394     auto prevFullChildrenList = fullChildrenList_;
2395 
2396     // Update the flag to indicate that children are now valid and sorted
2397     isFullChildrenListValid_ = true;
2398     isChildrenSorted_ = true;
2399 
2400     // Move the fullChildrenList to fullChildrenList_ atomically
2401     ChildrenListSharedPtr constFullChildrenList = std::move(fullChildrenList);
2402     std::atomic_store_explicit(&fullChildrenList_, constFullChildrenList, std::memory_order_release);
2403 }
2404 
2405 void RSRenderNode::ResortChildren()
2406 {
2407     // Make a copy of the fullChildrenList for sorting
2408     auto fullChildrenList = std::make_shared<std::vector<std::shared_ptr<RSRenderNode>>>(*fullChildrenList_);
2409 
2410     // Sort the children by their z-order
2411     std::stable_sort(
2412         fullChildrenList->begin(), fullChildrenList->end(), [](const auto& first, const auto& second) -> bool {
2413         return first->GetRenderProperties().GetPositionZ() < second->GetRenderProperties().GetPositionZ();
2414     });
2415 
2416     // Keep a reference to fullChildrenList_ to prevent its deletion when swapping it
2417     auto prevFullChildrenList = fullChildrenList_;
2418 
2419     // Update the flag to indicate that children are now sorted
2420     isChildrenSorted_ = true;
2421 
2422     // Move the fullChildrenList to fullChildrenList_ atomically
2423     ChildrenListSharedPtr constFullChildrenList = std::move(fullChildrenList);
2424     std::atomic_store_explicit(&fullChildrenList_, constFullChildrenList, std::memory_order_release);
2425 }
2426 
2427 uint32_t RSRenderNode::GetChildrenCount() const
2428 {
2429     return children_.size();
2430 }
2431 
2432 bool RSRenderNode::IsOnTheTree() const
2433 {
2434     return isOnTheTree_;
2435 }
2436 void RSRenderNode::SetTunnelHandleChange(bool change)
2437 {
2438     isTunnelHandleChange_ = change;
2439 }
2440 bool RSRenderNode::GetTunnelHandleChange() const
2441 {
2442     return isTunnelHandleChange_;
2443 }
2444 bool RSRenderNode::HasChildrenOutOfRect() const
2445 {
2446     if (GetRenderProperties().GetClipToBounds() || GetRenderProperties().GetClipToFrame()) {
2447         return false;
2448     }
2449     return hasChildrenOutOfRect_;
2450 }
2451 void RSRenderNode::UpdateChildrenOutOfRectFlag(bool flag)
2452 {
2453     hasChildrenOutOfRect_ = flag;
2454 }
2455 void RSRenderNode::ResetHasRemovedChild()
2456 {
2457     hasRemovedChild_ = false;
2458 }
2459 bool RSRenderNode::HasRemovedChild() const
2460 {
2461     return hasRemovedChild_;
2462 }
2463 void RSRenderNode::ResetChildrenRect()
2464 {
2465     childrenRect_ = RectI();
2466 }
2467 RectI RSRenderNode::GetChildrenRect() const
2468 {
2469     return childrenRect_;
2470 }
2471 bool RSRenderNode::ChildHasFilter() const
2472 {
2473     return childHasFilter_;
2474 }
2475 void RSRenderNode::SetChildHasFilter(bool childHasFilter)
2476 {
2477     childHasFilter_ = childHasFilter;
2478 }
2479 NodeId RSRenderNode::GetInstanceRootNodeId() const
2480 {
2481     return instanceRootNodeId_;
2482 }
2483 const std::shared_ptr<RSRenderNode> RSRenderNode::GetInstanceRootNode() const
2484 {
2485     auto context = GetContext().lock();
2486     if (!context) {
2487         ROSEN_LOGE("Invalid context");
2488         return nullptr;
2489     }
2490     return context->GetNodeMap().GetRenderNode(instanceRootNodeId_);
2491 }
2492 NodeId RSRenderNode::GetFirstLevelNodeId() const
2493 {
2494     return firstLevelNodeId_;
2495 }
2496 bool RSRenderNode::IsRenderUpdateIgnored() const
2497 {
2498     return isRenderUpdateIgnored_;
2499 }
2500 RSAnimationManager& RSRenderNode::GetAnimationManager()
2501 {
2502     return animationManager_;
2503 }
2504 RectI RSRenderNode::GetOldDirty() const
2505 {
2506     return oldDirty_;
2507 }
2508 RectI RSRenderNode::GetOldDirtyInSurface() const
2509 {
2510     return oldDirtyInSurface_;
2511 }
2512 bool RSRenderNode::IsDirtyRegionUpdated() const
2513 {
2514     return isDirtyRegionUpdated_;
2515 }
2516 void RSRenderNode::CleanDirtyRegionUpdated()
2517 {
2518     isDirtyRegionUpdated_ = false;
2519 }
2520 bool RSRenderNode::IsShadowValidLastFrame() const
2521 {
2522     return isShadowValidLastFrame_;
2523 }
2524 void RSRenderNode::SetStaticCached(bool isStaticCached)
2525 {
2526     isStaticCached_ = isStaticCached;
2527     // ensure defrost subtree would be updated
2528     if (!isStaticCached_) {
2529         SetContentDirty();
2530     }
2531 }
2532 bool RSRenderNode::IsStaticCached() const
2533 {
2534     return isStaticCached_;
2535 }
2536 void RSRenderNode::UpdateCompletedCacheSurface()
2537 {
2538     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2539     std::swap(cacheSurface_, cacheCompletedSurface_);
2540     std::swap(cacheSurfaceThreadIndex_, completedSurfaceThreadIndex_);
2541 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2542     std::swap(cacheBackendTexture_, cacheCompletedBackendTexture_);
2543 #ifdef RS_ENABLE_VK
2544     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
2545         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
2546         std::swap(cacheCleanupHelper_, cacheCompletedCleanupHelper_);
2547     }
2548 #endif
2549     SetTextureValidFlag(true);
2550 #endif
2551 }
2552 void RSRenderNode::SetTextureValidFlag(bool isValid)
2553 {
2554 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2555     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2556     isTextureValid_ = isValid;
2557 #endif
2558 }
2559 void RSRenderNode::ClearCacheSurface(bool isClearCompletedCacheSurface)
2560 {
2561     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2562     cacheSurface_ = nullptr;
2563 #ifdef RS_ENABLE_VK
2564     if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
2565         OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
2566         cacheCleanupHelper_ = nullptr;
2567     }
2568 #endif
2569     if (isClearCompletedCacheSurface) {
2570         cacheCompletedSurface_ = nullptr;
2571 #ifdef RS_ENABLE_VK
2572         if (OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::VULKAN ||
2573             OHOS::Rosen::RSSystemProperties::GetGpuApiType() == OHOS::Rosen::GpuApiType::DDGR) {
2574             cacheCompletedCleanupHelper_ = nullptr;
2575         }
2576 #endif
2577 #if defined(NEW_SKIA) && (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2578         isTextureValid_ = false;
2579 #endif
2580     }
2581 }
2582 void RSRenderNode::SetCacheType(CacheType cacheType)
2583 {
2584     cacheType_ = cacheType;
2585 }
2586 CacheType RSRenderNode::GetCacheType() const
2587 {
2588     return cacheType_;
2589 }
2590 int RSRenderNode::GetShadowRectOffsetX() const
2591 {
2592     return shadowRectOffsetX_;
2593 }
2594 int RSRenderNode::GetShadowRectOffsetY() const
2595 {
2596     return shadowRectOffsetY_;
2597 }
2598 void RSRenderNode::SetDrawingCacheType(RSDrawingCacheType cacheType)
2599 {
2600     drawingCacheType_ = cacheType;
2601 }
2602 RSDrawingCacheType RSRenderNode::GetDrawingCacheType() const
2603 {
2604     return drawingCacheType_;
2605 }
2606 void RSRenderNode::SetDrawingCacheChanged(bool cacheChanged)
2607 {
2608     isDrawingCacheChanged_ = drawingCacheNeedUpdate_ || cacheChanged;
2609     drawingCacheNeedUpdate_ = isDrawingCacheChanged_;
2610 }
2611 bool RSRenderNode::GetDrawingCacheChanged() const
2612 {
2613     return isDrawingCacheChanged_;
2614 }
2615 void RSRenderNode::ResetDrawingCacheNeedUpdate()
2616 {
2617     drawingCacheNeedUpdate_ = false;
2618 }
2619 void RSRenderNode::SetCacheGeoPreparationDelay(bool val)
2620 {
2621     cacheGeoPreparationDelay_ = cacheGeoPreparationDelay_ || val;
2622 }
2623 void RSRenderNode::ResetCacheGeoPreparationDelay()
2624 {
2625     cacheGeoPreparationDelay_ = false;
2626 }
2627 bool RSRenderNode::GetCacheGeoPreparationDelay() const
2628 {
2629     return cacheGeoPreparationDelay_;
2630 }
2631 
2632 void RSRenderNode::StoreMustRenewedInfo()
2633 {
2634     mustRenewedInfo_ = hasHardwareNode_ || hasFilter_ || hasEffectNode_;
2635 }
2636 
2637 bool RSRenderNode::HasMustRenewedInfo() const
2638 {
2639     return mustRenewedInfo_;
2640 }
2641 
2642 void RSRenderNode::SetUseEffectNodes(bool val)
2643 {
2644     hasEffectNode_ = val;
2645 }
2646 
2647 bool RSRenderNode::HasUseEffectNodes() const
2648 {
2649     return hasEffectNode_;
2650 }
2651 
2652 void RSRenderNode::SetVisitedCacheRootIds(const std::unordered_set<NodeId>& visitedNodes)
2653 {
2654     visitedCacheRoots_ = visitedNodes;
2655 }
2656 const std::unordered_set<NodeId>& RSRenderNode::GetVisitedCacheRootIds() const
2657 {
2658     return visitedCacheRoots_;
2659 }
2660 void RSRenderNode::UpdateSubSurfaceCnt(SharedPtr curParent, SharedPtr preParent)
2661 {
2662     uint32_t subSurfaceCnt = GetType() == RSRenderNodeType::SURFACE_NODE ?
2663         subSurfaceCnt_ + 1 : subSurfaceCnt_;
2664     if (subSurfaceCnt == 0) {
2665         return;
2666     }
2667     if (curParent) {
2668         curParent->subSurfaceCnt_ += subSurfaceCnt;
2669         UpdateSubSurfaceCnt(curParent->GetParent().lock(), nullptr);
2670     }
2671     if (preParent) {
2672         preParent->subSurfaceCnt_ -= subSurfaceCnt;
2673         UpdateSubSurfaceCnt(nullptr, preParent->GetParent().lock());
2674     }
2675 }
2676 bool RSRenderNode::HasSubSurface() const
2677 {
2678     return subSurfaceCnt_ > 0;
2679 }
2680 void RSRenderNode::SetDrawingCacheRootId(NodeId id)
2681 {
2682     drawingCacheRootId_ = id;
2683 }
2684 NodeId RSRenderNode::GetDrawingCacheRootId() const
2685 {
2686     return drawingCacheRootId_;
2687 }
2688 void RSRenderNode::SetIsMarkDriven(bool isMarkDriven)
2689 {
2690     isMarkDriven_ = isMarkDriven;
2691 }
2692 bool RSRenderNode::IsMarkDriven() const
2693 {
2694     return isMarkDriven_;
2695 }
2696 void RSRenderNode::SetIsMarkDrivenRender(bool isMarkDrivenRender)
2697 {
2698     isMarkDrivenRender_ = isMarkDrivenRender;
2699 }
2700 bool RSRenderNode::IsMarkDrivenRender() const
2701 {
2702     return isMarkDrivenRender_;
2703 }
2704 void RSRenderNode::SetItemIndex(int index)
2705 {
2706     itemIndex_ = index;
2707 }
2708 int RSRenderNode::GetItemIndex() const
2709 {
2710     return itemIndex_;
2711 }
2712 void RSRenderNode::SetPaintState(bool paintState)
2713 {
2714     paintState_ = paintState;
2715 }
2716 bool RSRenderNode::GetPaintState() const
2717 {
2718     return paintState_;
2719 }
2720 void RSRenderNode::SetIsContentChanged(bool isChanged)
2721 {
2722     isContentChanged_ = isChanged;
2723 }
2724 bool RSRenderNode::IsContentChanged() const
2725 {
2726     return isContentChanged_ || HasAnimation();
2727 }
2728 bool RSRenderNode::HasAnimation() const
2729 {
2730     return !animationManager_.animations_.empty();
2731 }
2732 bool RSRenderNode::HasFilter() const
2733 {
2734     return hasFilter_;
2735 }
2736 void RSRenderNode::SetHasFilter(bool hasFilter)
2737 {
2738     hasFilter_ = hasFilter;
2739 }
2740 std::recursive_mutex& RSRenderNode::GetSurfaceMutex() const
2741 {
2742     return surfaceMutex_;
2743 }
2744 bool RSRenderNode::HasHardwareNode() const
2745 {
2746     return hasHardwareNode_;
2747 }
2748 void RSRenderNode::SetHasHardwareNode(bool hasHardwareNode)
2749 {
2750     hasHardwareNode_ = hasHardwareNode;
2751 }
2752 bool RSRenderNode::HasAbilityComponent() const
2753 {
2754     return hasAbilityComponent_;
2755 }
2756 void RSRenderNode::SetHasAbilityComponent(bool hasAbilityComponent)
2757 {
2758     hasAbilityComponent_ = hasAbilityComponent;
2759 }
2760 uint32_t RSRenderNode::GetCacheSurfaceThreadIndex() const
2761 {
2762     return cacheSurfaceThreadIndex_;
2763 }
2764 uint32_t RSRenderNode::GetCompletedSurfaceThreadIndex() const
2765 {
2766     return completedSurfaceThreadIndex_;
2767 }
2768 
2769 bool RSRenderNode::IsMainThreadNode() const
2770 {
2771     return isMainThreadNode_;
2772 }
2773 void RSRenderNode::SetIsMainThreadNode(bool isMainThreadNode)
2774 {
2775     isMainThreadNode_ = isMainThreadNode;
2776 }
2777 bool RSRenderNode::IsScale() const
2778 {
2779     return isScale_;
2780 }
2781 void RSRenderNode::SetIsScale(bool isScale)
2782 {
2783     isScale_ = isScale;
2784 }
2785 void RSRenderNode::SetPriority(NodePriorityType priority)
2786 {
2787     priority_ = priority;
2788 }
2789 NodePriorityType RSRenderNode::GetPriority()
2790 {
2791     return priority_;
2792 }
2793 bool RSRenderNode::IsAncestorDirty() const
2794 {
2795     return isAncestorDirty_;
2796 }
2797 void RSRenderNode::SetIsAncestorDirty(bool isAncestorDirty)
2798 {
2799     isAncestorDirty_ = isAncestorDirty;
2800 }
2801 bool RSRenderNode::IsParentLeashWindow() const
2802 {
2803     return isParentLeashWindow_;
2804 }
2805 void RSRenderNode::SetParentLeashWindow()
2806 {
2807     isParentLeashWindow_ = true;
2808 }
2809 bool RSRenderNode::IsParentScbScreen() const
2810 {
2811     return isParentScbScreen_;
2812 }
2813 void RSRenderNode::SetParentScbScreen()
2814 {
2815     isParentScbScreen_ = true;
2816 }
2817 bool RSRenderNode::HasCachedTexture() const
2818 {
2819 #if (defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK))
2820     std::scoped_lock<std::recursive_mutex> lock(surfaceMutex_);
2821     return isTextureValid_;
2822 #else
2823     return true;
2824 #endif
2825 }
2826 void RSRenderNode::SetDrawRegion(const std::shared_ptr<RectF>& rect)
2827 {
2828     drawRegion_ = rect;
2829     GetMutableRenderProperties().SetDrawRegion(rect);
2830 }
2831 const std::shared_ptr<RectF>& RSRenderNode::GetDrawRegion() const
2832 {
2833     return drawRegion_;
2834 }
2835 void RSRenderNode::SetOutOfParent(OutOfParentType outOfParent)
2836 {
2837     outOfParent_ = outOfParent;
2838 }
2839 OutOfParentType RSRenderNode::GetOutOfParent() const
2840 {
2841     return outOfParent_;
2842 }
2843 RSRenderNode::NodeGroupType RSRenderNode::GetNodeGroupType()
2844 {
2845     return nodeGroupType_;
2846 }
2847 
2848 void RSRenderNode::MarkNonGeometryChanged()
2849 {
2850     geometryChangeNotPerceived_ = true;
2851 }
2852 
2853 bool RSRenderNode::GetIsUsedBySubThread() const
2854 {
2855     return isUsedBySubThread_.load();
2856 }
2857 void RSRenderNode::SetIsUsedBySubThread(bool isUsedBySubThread)
2858 {
2859     isUsedBySubThread_.store(isUsedBySubThread);
2860 }
2861 
2862 bool RSRenderNode::GetLastIsNeedAssignToSubThread() const
2863 {
2864     return lastIsNeedAssignToSubThread_;
2865 }
2866 void RSRenderNode::SetLastIsNeedAssignToSubThread(bool lastIsNeedAssignToSubThread)
2867 {
2868     lastIsNeedAssignToSubThread_ = lastIsNeedAssignToSubThread;
2869 }
2870 } // namespace Rosen
2871 } // namespace OHOS
2872