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_canvas_render_node.h"
17 
18 #include <algorithm>
19 #include "modifier/rs_modifier_type.h"
20 
21 #include "common/rs_obj_abs_geometry.h"
22 #include "common/rs_common_def.h"
23 #include "recording/recording_canvas.h"
24 #include "memory/rs_memory_track.h"
25 #include "memory/rs_tag_tracker.h"
26 #include "pipeline/rs_paint_filter_canvas.h"
27 #include "property/rs_properties_painter.h"
28 #include "render/rs_blur_filter.h"
29 #include "render/rs_light_up_effect_filter.h"
30 #include "platform/common/rs_log.h"
31 #include "visitor/rs_node_visitor.h"
32 #include "property/rs_property_drawable.h"
33 
34 namespace OHOS {
35 namespace Rosen {
36 namespace {
37 constexpr PropertyId ANONYMOUS_MODIFIER_ID = 0;
38 }
39 
RSCanvasRenderNode(NodeId id,const std::weak_ptr<RSContext> & context,bool isTextureExportNode)40 RSCanvasRenderNode::RSCanvasRenderNode(NodeId id, const std::weak_ptr<RSContext>& context, bool isTextureExportNode)
41     : RSRenderNode(id, context, isTextureExportNode)
42 {
43 #ifndef ROSEN_ARKUI_X
44     MemoryInfo info = {sizeof(*this), ExtractPid(id), id, MEMORY_TYPE::MEM_RENDER_NODE};
45     MemoryTrack::Instance().AddNodeRecord(id, info);
46 #endif
47 }
48 
~RSCanvasRenderNode()49 RSCanvasRenderNode::~RSCanvasRenderNode()
50 {
51 #ifndef ROSEN_ARKUI_X
52     MemoryTrack::Instance().RemoveNodeRecord(GetId());
53 #endif
54 }
55 
UpdateRecording(std::shared_ptr<Drawing::DrawCmdList> drawCmds,RSModifierType type,bool isSingleFrameComposer)56 void RSCanvasRenderNode::UpdateRecording(std::shared_ptr<Drawing::DrawCmdList> drawCmds,
57     RSModifierType type, bool isSingleFrameComposer)
58 {
59     if (!drawCmds || drawCmds->IsEmpty()) {
60         return;
61     }
62     auto renderProperty = std::make_shared<RSRenderProperty<Drawing::DrawCmdListPtr>>(drawCmds, ANONYMOUS_MODIFIER_ID);
63     auto renderModifier = std::make_shared<RSDrawCmdListRenderModifier>(renderProperty);
64     renderModifier->SetType(type);
65     AddModifier(renderModifier, isSingleFrameComposer);
66 }
67 
ClearRecording()68 void RSCanvasRenderNode::ClearRecording()
69 {
70     RemoveModifier(ANONYMOUS_MODIFIER_ID);
71 }
72 
QuickPrepare(const std::shared_ptr<RSNodeVisitor> & visitor)73 void RSCanvasRenderNode::QuickPrepare(const std::shared_ptr<RSNodeVisitor>& visitor)
74 {
75     if (!visitor) {
76         return;
77     }
78     ApplyModifiers();
79     visitor->QuickPrepareCanvasRenderNode(*this);
80 }
81 
Prepare(const std::shared_ptr<RSNodeVisitor> & visitor)82 void RSCanvasRenderNode::Prepare(const std::shared_ptr<RSNodeVisitor>& visitor)
83 {
84     if (!visitor) {
85         return;
86     }
87     ApplyModifiers();
88     visitor->PrepareCanvasRenderNode(*this);
89 }
90 
OnTreeStateChanged()91 void RSCanvasRenderNode::OnTreeStateChanged()
92 {
93     if (!IsOnTheTree()) {
94         // clear node groups cache when node is removed from tree
95         if (GetCacheType() == CacheType::CONTENT) {
96             SetCacheType(CacheType::NONE);
97             ClearCacheSurfaceInThread();
98             SetDrawingCacheType(RSDrawingCacheType::DISABLED_CACHE);
99         }
100         needClearSurface_ = true;
101         AddToPendingSyncList();
102     }
103     RSRenderNode::OnTreeStateChanged();
104 }
105 
OpincGetNodeSupportFlag()106 bool RSCanvasRenderNode::OpincGetNodeSupportFlag()
107 {
108     const auto& property = GetRenderProperties();
109     if (GetSharedTransitionParam() ||
110         property.IsSpherizeValid() ||
111         property.IsAttractionValid() ||
112         property.NeedFilter() ||
113         property.GetUseEffect() ||
114         property.GetColorBlend().has_value() ||
115         IsSelfDrawingNode()) {
116         return false;
117     }
118     return true && RSRenderNode::OpincGetNodeSupportFlag();
119 }
120 
Process(const std::shared_ptr<RSNodeVisitor> & visitor)121 void RSCanvasRenderNode::Process(const std::shared_ptr<RSNodeVisitor>& visitor)
122 {
123     if (!visitor) {
124         return;
125     }
126     RSRenderNode::RenderTraceDebug();
127     visitor->ProcessCanvasRenderNode(*this);
128 }
129 
ProcessTransitionBeforeChildren(RSPaintFilterCanvas & canvas)130 void RSCanvasRenderNode::ProcessTransitionBeforeChildren(RSPaintFilterCanvas& canvas)
131 {
132     DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::MASK, canvas);
133 }
134 
ProcessShadowBatching(RSPaintFilterCanvas & canvas)135 void RSCanvasRenderNode::ProcessShadowBatching(RSPaintFilterCanvas& canvas)
136 {
137     RSAutoCanvasRestore acr(&canvas);
138     DrawPropertyDrawableRange(RSPropertyDrawableSlot::BOUNDS_MATRIX, RSPropertyDrawableSlot::TRANSITION, canvas);
139     DrawPropertyDrawable(RSPropertyDrawableSlot::SHADOW, canvas);
140 }
141 
DrawShadow(RSModifierContext & context,RSPaintFilterCanvas & canvas)142 void RSCanvasRenderNode::DrawShadow(RSModifierContext& context, RSPaintFilterCanvas& canvas)
143 {
144     ApplyDrawCmdModifier(context, RSModifierType::TRANSITION);
145     ApplyDrawCmdModifier(context, RSModifierType::ENV_FOREGROUND_COLOR);
146 
147     auto parent = GetParent().lock();
148     if (!(parent && parent->GetRenderProperties().GetUseShadowBatching())) {
149         RSPropertiesPainter::DrawShadow(GetRenderProperties(), canvas);
150         RSPropertiesPainter::DrawOutline(GetRenderProperties(), canvas);
151     }
152 }
153 
PropertyDrawableRender(RSPaintFilterCanvas & canvas,bool includeProperty)154 void RSCanvasRenderNode::PropertyDrawableRender(RSPaintFilterCanvas& canvas, bool includeProperty)
155 {
156     auto parent = GetParent().lock();
157     if (parent &&
158         parent->GetRenderProperties().GetUseShadowBatching()) {
159         DrawPropertyDrawableRange(
160             RSPropertyDrawableSlot::TRANSITION, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR, canvas);
161         if (includeProperty) {
162             // Just need to skip RSPropertyDrawableSlot::SHADOW
163             DrawPropertyDrawableRange(
164                 RSPropertyDrawableSlot::FOREGROUND_FILTER, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
165         } else {
166             DrawPropertyDrawableRange(
167                 RSPropertyDrawableSlot::SAVE_FRAME, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
168         }
169     } else {
170         if (includeProperty) {
171             DrawPropertyDrawableRange(RSPropertyDrawableSlot::TRANSITION, RSPropertyDrawableSlot::CLIP_TO_FRAME,
172                 canvas);
173         } else {
174             DrawPropertyDrawableRange(RSPropertyDrawableSlot::TRANSITION, RSPropertyDrawableSlot::OUTLINE, canvas);
175             DrawPropertyDrawableRange(
176                 RSPropertyDrawableSlot::SAVE_FRAME, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
177         }
178     }
179 }
180 
ProcessAnimatePropertyBeforeChildren(RSPaintFilterCanvas & canvas,bool includeProperty)181 void RSCanvasRenderNode::ProcessAnimatePropertyBeforeChildren(RSPaintFilterCanvas& canvas, bool includeProperty)
182 {
183     PropertyDrawableRender(canvas, includeProperty);
184 }
185 
ProcessRenderContents(RSPaintFilterCanvas & canvas)186 void RSCanvasRenderNode::ProcessRenderContents(RSPaintFilterCanvas& canvas)
187 {
188     DrawPropertyDrawable(RSPropertyDrawableSlot::CONTENT_STYLE, canvas);
189 }
190 
ProcessRenderBeforeChildren(RSPaintFilterCanvas & canvas)191 void RSCanvasRenderNode::ProcessRenderBeforeChildren(RSPaintFilterCanvas& canvas)
192 {
193     auto parent = GetParent().lock();
194     if (parent &&
195         parent->GetRenderProperties().GetUseShadowBatching()) {
196         DrawPropertyDrawableRange(
197             RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR, canvas);
198         // Just need to skip RSPropertyDrawableSlot::SHADOW
199         DrawPropertyDrawableRange(
200             RSPropertyDrawableSlot::FOREGROUND_FILTER, RSPropertyDrawableSlot::CUSTOM_CLIP_TO_FRAME, canvas);
201     } else {
202         DrawPropertyDrawableRange(
203             RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::CUSTOM_CLIP_TO_FRAME, canvas);
204     }
205 }
206 
ProcessAnimatePropertyAfterChildren(RSPaintFilterCanvas & canvas)207 void RSCanvasRenderNode::ProcessAnimatePropertyAfterChildren(RSPaintFilterCanvas& canvas)
208 {
209     DrawPropertyDrawableRange(
210         RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::PARTICLE_EFFECT, canvas);
211 }
212 
ProcessTransitionAfterChildren(RSPaintFilterCanvas & canvas)213 void RSCanvasRenderNode::ProcessTransitionAfterChildren(RSPaintFilterCanvas& canvas)
214 {
215     DrawPropertyDrawableRange(RSPropertyDrawableSlot::PIXEL_STRETCH, RSPropertyDrawableSlot::RESTORE_ALL, canvas);
216 }
217 
ProcessRenderAfterChildren(RSPaintFilterCanvas & canvas)218 void RSCanvasRenderNode::ProcessRenderAfterChildren(RSPaintFilterCanvas& canvas)
219 {
220     DrawPropertyDrawableRange(RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::RESTORE_ALL, canvas);
221 }
222 
ApplyDrawCmdModifier(RSModifierContext & context,RSModifierType type)223 void RSCanvasRenderNode::ApplyDrawCmdModifier(RSModifierContext& context, RSModifierType type)
224 {
225     // temporary workaround, PLANNING: refactor single frame compose without modifing draw cmd list
226     auto& drawCmdModifiers = const_cast<RSRenderContent::DrawCmdContainer&>(GetDrawCmdModifiers());
227     auto itr = drawCmdModifiers.find(type);
228     if (itr == drawCmdModifiers.end() || itr->second.empty()) {
229         return;
230     }
231 
232     if (RSSystemProperties::GetSingleFrameComposerEnabled()) {
233         bool needSkip = false;
234         if (GetNodeIsSingleFrameComposer() && singleFrameComposer_ != nullptr) {
235             needSkip = singleFrameComposer_->SingleFrameModifierAddToList(type, itr->second);
236         }
237         for (const auto& modifier : itr->second) {
238             if (singleFrameComposer_ != nullptr && singleFrameComposer_->SingleFrameIsNeedSkip(needSkip, modifier)) {
239                 continue;
240             }
241             modifier->Apply(context);
242         }
243     } else {
244         for (const auto& modifier : itr->second) {
245             modifier->Apply(context);
246         }
247     }
248 }
249 
InternalDrawContent(RSPaintFilterCanvas & canvas,bool needApplyMatrix)250 void RSCanvasRenderNode::InternalDrawContent(RSPaintFilterCanvas& canvas, bool needApplyMatrix)
251 {
252     RSModifierContext context = { GetMutableRenderProperties(), &canvas };
253 
254     if (needApplyMatrix) {
255         DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::CONTENT_STYLE, canvas);
256     } else {
257         DrawPropertyDrawableRange(RSPropertyDrawableSlot::OUTLINE, RSPropertyDrawableSlot::CONTENT_STYLE, canvas);
258     }
259 
260     for (auto& child : *GetSortedChildren()) {
261         if (auto canvasChild = ReinterpretCast<RSCanvasRenderNode>(child)) {
262             canvasChild->InternalDrawContent(canvas, true);
263         }
264     }
265 
266     if (needApplyMatrix) {
267         DrawPropertyDrawableRange(RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::RESTORE_ALL,
268             canvas);
269     } else {
270         DrawPropertyDrawableRange(RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::PIXEL_STRETCH,
271             canvas);
272     }
273 }
274 
SetHDRPresent(bool hasHdrPresent)275 void RSCanvasRenderNode::SetHDRPresent(bool hasHdrPresent)
276 {
277     RS_LOGD("RSCanvasRenderNode::SetHDRPresent HDRClient id: %{public}" PRIu64, GetId());
278     hasHdrPresent_ = hasHdrPresent;
279 }
280 
GetHDRPresent() const281 bool RSCanvasRenderNode::GetHDRPresent() const
282 {
283     RS_LOGD("RSCanvasRenderNode::GetHDRPresent HDRClient id: %{public}" PRIu64, GetId());
284     return hasHdrPresent_;
285 }
286 
287 } // namespace Rosen
288 } // namespace OHOS
289