• 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 
20 #include "animation/rs_render_animation.h"
21 #include "common/rs_obj_abs_geometry.h"
22 #include "pipeline/rs_context.h"
23 #include "pipeline/rs_surface_render_node.h"
24 #include "platform/common/rs_log.h"
25 #include "property/rs_property_trace.h"
26 #include "pipeline/rs_paint_filter_canvas.h"
27 #include "property/rs_properties_painter.h"
28 
29 namespace OHOS {
30 namespace Rosen {
RSRenderNode(NodeId id,std::weak_ptr<RSContext> context)31 RSRenderNode::RSRenderNode(NodeId id, std::weak_ptr<RSContext> context) : RSBaseRenderNode(id, context) {}
32 
~RSRenderNode()33 RSRenderNode::~RSRenderNode()
34 {
35     if (fallbackAnimationOnDestroy_) {
36         FallbackAnimationsToRoot();
37     }
38 }
39 
FallbackAnimationsToRoot()40 void RSRenderNode::FallbackAnimationsToRoot()
41 {
42     if (animationManager_.animations_.empty()) {
43         return;
44     }
45 
46     auto context = GetContext().lock();
47     if (!context) {
48         ROSEN_LOGE("Invalid context");
49         return;
50     }
51     auto target = context->GetNodeMap().GetAnimationFallbackNode();
52     if (!target) {
53         ROSEN_LOGE("Failed to move animation to root, root render node is null!");
54         return;
55     }
56     context->RegisterAnimatingRenderNode(target);
57 
58     for (const auto& [animationId, animation] : animationManager_.animations_) {
59         animation->Detach();
60         // avoid infinite loop for fallback animation
61         animation->SetRepeatCount(1);
62         target->animationManager_.AddAnimation(animation);
63     }
64 }
65 
Animate(int64_t timestamp)66 std::pair<bool, bool> RSRenderNode::Animate(int64_t timestamp)
67 {
68     return animationManager_.Animate(timestamp, IsOnTheTree());
69 }
70 
Update(RSDirtyRegionManager & dirtyManager,const RSProperties * parent,bool parentDirty)71 bool RSRenderNode::Update(RSDirtyRegionManager& dirtyManager, const RSProperties* parent, bool parentDirty)
72 {
73     // no need to update invisible nodes
74     if (!ShouldPaint() && !isLastVisible_) {
75         return false;
76     }
77     // [planning] surfaceNode use frame instead
78     Vector2f offset = (parent == nullptr || IsInstanceOf<RSSurfaceRenderNode>()) ?
79         Vector2f { 0.f, 0.f } : Vector2f { parent->GetFrameOffsetX(), parent->GetFrameOffsetY() };
80     bool dirty = renderProperties_.UpdateGeometry(parent, parentDirty, offset);
81     isDirtyRegionUpdated_ = false;
82     UpdateDirtyRegion(dirtyManager, dirty);
83     isLastVisible_ = ShouldPaint();
84     renderProperties_.ResetDirty();
85     return dirty;
86 }
87 
GetMutableRenderProperties()88 RSProperties& RSRenderNode::GetMutableRenderProperties()
89 {
90     return renderProperties_;
91 }
92 
GetRenderProperties() const93 const RSProperties& RSRenderNode::GetRenderProperties() const
94 {
95     return renderProperties_;
96 }
97 
UpdateDirtyRegion(RSDirtyRegionManager & dirtyManager,bool geoDirty)98 void RSRenderNode::UpdateDirtyRegion(RSDirtyRegionManager& dirtyManager, bool geoDirty)
99 {
100     if (!IsDirty() && !geoDirty) {
101         return;
102     }
103     if (!oldDirty_.IsEmpty()) {
104         dirtyManager.MergeDirtyRect(oldDirty_);
105     }
106     // merge old dirty if switch to invisible
107     if (!ShouldPaint() && isLastVisible_) {
108         ROSEN_LOGD("RSRenderNode:: id %" PRIu64 " UpdateDirtyRegion visible->invisible", GetId());
109     } else {
110         auto dirtyRect = renderProperties_.GetDirtyRect();
111         if (renderProperties_.IsShadowValid()) {
112             SetShadowValidLastFrame(true);
113             RectI shadowDirty;
114             if (IsInstanceOf<RSSurfaceRenderNode>()) {
115                 const RectF absBounds = {0, 0, renderProperties_.GetBoundsWidth(), renderProperties_.GetBoundsHeight()};
116                 RRect absClipRRect = RRect(absBounds, renderProperties_.GetCornerRadius());
117                 RSPropertiesPainter::GetShadowDirtyRect(shadowDirty, renderProperties_, &absClipRRect);
118             } else {
119                 RSPropertiesPainter::GetShadowDirtyRect(shadowDirty, renderProperties_);
120             }
121             if (!shadowDirty.IsEmpty()) {
122                 dirtyRect = dirtyRect.JoinRect(shadowDirty);
123             }
124         }
125         // filter invalid dirtyrect
126         if (!dirtyRect.IsEmpty()) {
127             dirtyManager.MergeDirtyRect(dirtyRect);
128             isDirtyRegionUpdated_ = true;
129             oldDirty_ = dirtyRect;
130             oldDirtyInSurface_ = oldDirty_.IntersectRect(dirtyManager.GetSurfaceRect());
131         }
132     }
133     SetClean();
134 }
135 
IsDirty() const136 bool RSRenderNode::IsDirty() const
137 {
138     return RSBaseRenderNode::IsDirty() || renderProperties_.IsDirty();
139 }
140 
UpdateRenderStatus(RectI & dirtyRegion,bool isPartialRenderEnabled)141 void RSRenderNode::UpdateRenderStatus(RectI& dirtyRegion, bool isPartialRenderEnabled)
142 {
143     auto dirtyRect = renderProperties_.GetDirtyRect();
144     // should judge if there's any child out of parent
145     if (!isPartialRenderEnabled) {
146         isRenderUpdateIgnored_ = false;
147     } else if (dirtyRegion.IsEmpty() || dirtyRect.IsEmpty()) {
148         isRenderUpdateIgnored_ = true;
149     } else {
150         RectI intersectRect = dirtyRegion.IntersectRect(dirtyRect);
151         isRenderUpdateIgnored_ = intersectRect.IsEmpty();
152     }
153 }
154 
UpdateParentChildrenRect(std::shared_ptr<RSBaseRenderNode> parentNode,const bool isCustomized,const RectI subRect) const155 void RSRenderNode::UpdateParentChildrenRect(std::shared_ptr<RSBaseRenderNode> parentNode,
156     const bool isCustomized, const RectI subRect) const
157 {
158     if (parentNode) {
159         RectI accumulatedRect = GetChildrenRect();
160         accumulatedRect = accumulatedRect.JoinRect((isCustomized ? subRect : renderProperties_.GetDirtyRect()));
161         parentNode->UpdateChildrenRect(accumulatedRect);
162     }
163 }
164 
RenderTraceDebug() const165 void RSRenderNode::RenderTraceDebug() const
166 {
167     if (RSSystemProperties::GetRenderNodeTraceEnabled()) {
168         RSPropertyTrace::GetInstance().PropertiesDisplayByTrace(GetId(),
169             std::static_pointer_cast<RSObjAbsGeometry>(GetRenderProperties().GetBoundsGeometry()));
170     }
171 }
172 
ProcessRenderBeforeChildren(RSPaintFilterCanvas & canvas)173 void RSRenderNode::ProcessRenderBeforeChildren(RSPaintFilterCanvas& canvas)
174 {
175     renderNodeSaveCount_ = canvas.SaveCanvasAndAlpha();
176     auto boundsGeo = std::static_pointer_cast<RSObjAbsGeometry>(GetRenderProperties().GetBoundsGeometry());
177     if (boundsGeo && !boundsGeo->IsEmpty()) {
178         canvas.concat(boundsGeo->GetMatrix());
179     }
180     auto alpha = renderProperties_.GetAlpha();
181     if (alpha < 1.f) {
182         if ((GetChildrenCount() == 0) || !GetRenderProperties().GetAlphaOffscreen()) {
183             canvas.MultiplyAlpha(alpha);
184         } else {
185             auto rect = RSPropertiesPainter::Rect2SkRect(GetRenderProperties().GetBoundsRect());
186             canvas.saveLayerAlpha(&rect, std::clamp(alpha, 0.f, 1.f) * UINT8_MAX);
187         }
188     }
189     RSPropertiesPainter::DrawMask(GetRenderProperties(), canvas);
190 }
191 
ProcessRenderAfterChildren(RSPaintFilterCanvas & canvas)192 void RSRenderNode::ProcessRenderAfterChildren(RSPaintFilterCanvas& canvas)
193 {
194     GetMutableRenderProperties().ResetBounds();
195     canvas.RestoreCanvasAndAlpha(renderNodeSaveCount_);
196 }
197 
AddModifier(const std::shared_ptr<RSRenderModifier> modifier)198 void RSRenderNode::AddModifier(const std::shared_ptr<RSRenderModifier> modifier)
199 {
200     if (!modifier) {
201         return;
202     }
203     if (modifier->GetType() == RSModifierType::BOUNDS || modifier->GetType() == RSModifierType::FRAME) {
204         AddGeometryModifier(modifier);
205     } else if (modifier->GetType() < RSModifierType::CUSTOM) {
206         modifiers_.emplace(modifier->GetPropertyId(), modifier);
207     } else {
208         drawCmdModifiers_[modifier->GetType()].emplace_back(modifier);
209     }
210     modifier->GetProperty()->Attach(shared_from_this());
211     SetDirty();
212 }
213 
AddGeometryModifier(const std::shared_ptr<RSRenderModifier> modifier)214 void RSRenderNode::AddGeometryModifier(const std::shared_ptr<RSRenderModifier> modifier)
215 {
216     // bounds and frame modifiers must be unique
217     if (modifier->GetType() == RSModifierType::BOUNDS) {
218         if (boundsModifier_ == nullptr) {
219             boundsModifier_ = modifier;
220         }
221         modifiers_.emplace(modifier->GetPropertyId(), boundsModifier_);
222     }
223 
224     if (modifier->GetType() == RSModifierType::FRAME) {
225         if (frameModifier_ == nullptr) {
226             frameModifier_ = modifier;
227         }
228         modifiers_.emplace(modifier->GetPropertyId(), frameModifier_);
229     }
230 }
231 
RemoveModifier(const PropertyId & id)232 void RSRenderNode::RemoveModifier(const PropertyId& id)
233 {
234     bool success = modifiers_.erase(id);
235     if (success) {
236         SetDirty();
237         return;
238     }
239     for (auto& [type, modifiers] : drawCmdModifiers_) {
240         modifiers.remove_if([id](const auto& modifier) -> bool {
241             return modifier ? modifier->GetPropertyId() == id : true;
242         });
243         if (type == RSModifierType::OVERLAY_STYLE) {
244             UpdateOverlayBounds();
245         }
246     }
247 }
248 
ApplyModifiers()249 void RSRenderNode::ApplyModifiers()
250 {
251     if (!RSBaseRenderNode::IsDirty()) {
252         return;
253     }
254     RSModifierContext context = { GetMutableRenderProperties() };
255     context.property_.Reset();
256     for (auto& [id, modifier] : modifiers_) {
257         if (modifier) {
258             modifier->Apply(context);
259         }
260     }
261 
262     UpdateOverlayBounds();
263 }
264 
UpdateOverlayBounds()265 void RSRenderNode::UpdateOverlayBounds()
266 {
267     RSModifierContext context = { GetMutableRenderProperties() };
268     RectI joinRect = RectI();
269     for (auto& iterator : drawCmdModifiers_) {
270         for (auto& overlayModifier : iterator.second) {
271             auto drawCmdModifier = std::static_pointer_cast<RSDrawCmdListRenderModifier>(overlayModifier);
272             if (!drawCmdModifier) {
273                 continue;
274             }
275             if (drawCmdModifier->GetOverlayBounds() != nullptr &&
276                 !drawCmdModifier->GetOverlayBounds()->IsEmpty()) {
277                 joinRect = joinRect.JoinRect(*(drawCmdModifier->GetOverlayBounds()));
278             } else if (drawCmdModifier->GetOverlayBounds() == nullptr) {
279                 auto recording = std::static_pointer_cast<RSRenderProperty<DrawCmdListPtr>>(
280                     drawCmdModifier->GetProperty())->Get();
281                 auto recordingRect = RectI(0, 0, recording->GetWidth(), recording->GetHeight());
282                 joinRect = recordingRect.IsEmpty() ? joinRect : joinRect.JoinRect(recordingRect);
283             }
284         }
285     }
286     context.property_.SetOverlayBounds(std::make_shared<RectI>(joinRect));
287 }
288 
GetModifier(const PropertyId & id)289 std::shared_ptr<RSRenderModifier> RSRenderNode::GetModifier(const PropertyId& id)
290 {
291     if (modifiers_.count(id)) {
292         return modifiers_[id];
293     }
294     for (auto& [type, modifiers] : drawCmdModifiers_) {
295         auto it = std::find_if(modifiers.begin(), modifiers.end(),
296             [id](const auto& modifier) -> bool { return modifier->GetPropertyId() == id; });
297         if (it != modifiers.end()) {
298             return *it;
299         }
300     }
301     return nullptr;
302 }
303 
FilterModifiersByPid(pid_t pid)304 void RSRenderNode::FilterModifiersByPid(pid_t pid)
305 {
306     // remove all modifiers added by given pid (by matching higher 32 bits of node id)
307     EraseIf(
308         modifiers_, [pid](const auto& it) -> bool { return static_cast<pid_t>(it.first >> 32) == pid; });
309 
310     // remove all modifiers added by given pid (by matching higher 32 bits of node id)
311     for (auto& [type, modifiers] : drawCmdModifiers_) {
312         modifiers.remove_if(
313             [pid](const auto& it) -> bool { return static_cast<pid_t>(it->GetPropertyId() >> 32) == pid; });
314     }
315 }
316 
ShouldPaint() const317 bool RSRenderNode::ShouldPaint() const
318 {
319     // node should be painted if either it is visible or it has disappearing transition animation, but only when its
320     // alpha is not zero
321     return (renderProperties_.GetVisible() || HasDisappearingTransition(false)) &&
322            (renderProperties_.GetAlpha() > 0.0f);
323 }
324 } // namespace Rosen
325 } // namespace OHOS
326