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