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