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