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.NeedFilter() ||
112 property.GetUseEffect() ||
113 property.GetColorBlend().has_value() ||
114 IsSelfDrawingNode()) {
115 return false;
116 }
117 return true && RSRenderNode::OpincGetNodeSupportFlag();
118 }
119
Process(const std::shared_ptr<RSNodeVisitor> & visitor)120 void RSCanvasRenderNode::Process(const std::shared_ptr<RSNodeVisitor>& visitor)
121 {
122 if (!visitor) {
123 return;
124 }
125 RSRenderNode::RenderTraceDebug();
126 visitor->ProcessCanvasRenderNode(*this);
127 }
128
ProcessTransitionBeforeChildren(RSPaintFilterCanvas & canvas)129 void RSCanvasRenderNode::ProcessTransitionBeforeChildren(RSPaintFilterCanvas& canvas)
130 {
131 DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::MASK, canvas);
132 }
133
ProcessShadowBatching(RSPaintFilterCanvas & canvas)134 void RSCanvasRenderNode::ProcessShadowBatching(RSPaintFilterCanvas& canvas)
135 {
136 RSAutoCanvasRestore acr(&canvas);
137 DrawPropertyDrawableRange(RSPropertyDrawableSlot::BOUNDS_MATRIX, RSPropertyDrawableSlot::TRANSITION, canvas);
138 DrawPropertyDrawable(RSPropertyDrawableSlot::SHADOW, canvas);
139 }
140
DrawShadow(RSModifierContext & context,RSPaintFilterCanvas & canvas)141 void RSCanvasRenderNode::DrawShadow(RSModifierContext& context, RSPaintFilterCanvas& canvas)
142 {
143 ApplyDrawCmdModifier(context, RSModifierType::TRANSITION);
144 ApplyDrawCmdModifier(context, RSModifierType::ENV_FOREGROUND_COLOR);
145
146 auto parent = GetParent().lock();
147 if (!(parent && parent->GetRenderProperties().GetUseShadowBatching())) {
148 RSPropertiesPainter::DrawShadow(GetRenderProperties(), canvas);
149 RSPropertiesPainter::DrawOutline(GetRenderProperties(), canvas);
150 }
151 }
152
PropertyDrawableRender(RSPaintFilterCanvas & canvas,bool includeProperty)153 void RSCanvasRenderNode::PropertyDrawableRender(RSPaintFilterCanvas& canvas, bool includeProperty)
154 {
155 auto parent = GetParent().lock();
156 if (parent &&
157 parent->GetRenderProperties().GetUseShadowBatching()) {
158 DrawPropertyDrawableRange(
159 RSPropertyDrawableSlot::TRANSITION, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR, canvas);
160 if (includeProperty) {
161 // Just need to skip RSPropertyDrawableSlot::SHADOW
162 DrawPropertyDrawableRange(
163 RSPropertyDrawableSlot::FOREGROUND_FILTER, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
164 } else {
165 DrawPropertyDrawableRange(
166 RSPropertyDrawableSlot::SAVE_FRAME, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
167 }
168 } else {
169 if (includeProperty) {
170 DrawPropertyDrawableRange(RSPropertyDrawableSlot::TRANSITION, RSPropertyDrawableSlot::CLIP_TO_FRAME,
171 canvas);
172 } else {
173 DrawPropertyDrawableRange(RSPropertyDrawableSlot::TRANSITION, RSPropertyDrawableSlot::OUTLINE, canvas);
174 DrawPropertyDrawableRange(
175 RSPropertyDrawableSlot::SAVE_FRAME, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
176 }
177 }
178 }
179
ProcessAnimatePropertyBeforeChildren(RSPaintFilterCanvas & canvas,bool includeProperty)180 void RSCanvasRenderNode::ProcessAnimatePropertyBeforeChildren(RSPaintFilterCanvas& canvas, bool includeProperty)
181 {
182 PropertyDrawableRender(canvas, includeProperty);
183 }
184
ProcessRenderContents(RSPaintFilterCanvas & canvas)185 void RSCanvasRenderNode::ProcessRenderContents(RSPaintFilterCanvas& canvas)
186 {
187 DrawPropertyDrawable(RSPropertyDrawableSlot::CONTENT_STYLE, canvas);
188 }
189
ProcessRenderBeforeChildren(RSPaintFilterCanvas & canvas)190 void RSCanvasRenderNode::ProcessRenderBeforeChildren(RSPaintFilterCanvas& canvas)
191 {
192 auto parent = GetParent().lock();
193 if (parent &&
194 parent->GetRenderProperties().GetUseShadowBatching()) {
195 DrawPropertyDrawableRange(
196 RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR, canvas);
197 // Just need to skip RSPropertyDrawableSlot::SHADOW
198 DrawPropertyDrawableRange(
199 RSPropertyDrawableSlot::FOREGROUND_FILTER, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
200 } else {
201 DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::CLIP_TO_FRAME, canvas);
202 }
203 }
204
ProcessAnimatePropertyAfterChildren(RSPaintFilterCanvas & canvas)205 void RSCanvasRenderNode::ProcessAnimatePropertyAfterChildren(RSPaintFilterCanvas& canvas)
206 {
207 DrawPropertyDrawableRange(
208 RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::PARTICLE_EFFECT, canvas);
209 }
210
ProcessTransitionAfterChildren(RSPaintFilterCanvas & canvas)211 void RSCanvasRenderNode::ProcessTransitionAfterChildren(RSPaintFilterCanvas& canvas)
212 {
213 DrawPropertyDrawableRange(RSPropertyDrawableSlot::PIXEL_STRETCH, RSPropertyDrawableSlot::RESTORE_ALL, canvas);
214 }
215
ProcessRenderAfterChildren(RSPaintFilterCanvas & canvas)216 void RSCanvasRenderNode::ProcessRenderAfterChildren(RSPaintFilterCanvas& canvas)
217 {
218 DrawPropertyDrawableRange(RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::RESTORE_ALL, canvas);
219 }
220
ApplyDrawCmdModifier(RSModifierContext & context,RSModifierType type)221 void RSCanvasRenderNode::ApplyDrawCmdModifier(RSModifierContext& context, RSModifierType type)
222 {
223 // temporary workaround, PLANNING: refactor single frame compose without modifing draw cmd list
224 auto& drawCmdModifiers = const_cast<RSRenderContent::DrawCmdContainer&>(GetDrawCmdModifiers());
225 auto itr = drawCmdModifiers.find(type);
226 if (itr == drawCmdModifiers.end() || itr->second.empty()) {
227 return;
228 }
229
230 if (RSSystemProperties::GetSingleFrameComposerEnabled()) {
231 bool needSkip = false;
232 if (GetNodeIsSingleFrameComposer() && singleFrameComposer_ != nullptr) {
233 needSkip = singleFrameComposer_->SingleFrameModifierAddToList(type, itr->second);
234 }
235 for (const auto& modifier : itr->second) {
236 if (singleFrameComposer_ != nullptr && singleFrameComposer_->SingleFrameIsNeedSkip(needSkip, modifier)) {
237 continue;
238 }
239 modifier->Apply(context);
240 }
241 } else {
242 for (const auto& modifier : itr->second) {
243 modifier->Apply(context);
244 }
245 }
246 }
247
InternalDrawContent(RSPaintFilterCanvas & canvas,bool needApplyMatrix)248 void RSCanvasRenderNode::InternalDrawContent(RSPaintFilterCanvas& canvas, bool needApplyMatrix)
249 {
250 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
251
252 if (needApplyMatrix) {
253 DrawPropertyDrawableRange(RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::CONTENT_STYLE, canvas);
254 } else {
255 DrawPropertyDrawableRange(RSPropertyDrawableSlot::OUTLINE, RSPropertyDrawableSlot::CONTENT_STYLE, canvas);
256 }
257
258 for (auto& child : *GetSortedChildren()) {
259 if (auto canvasChild = ReinterpretCast<RSCanvasRenderNode>(child)) {
260 canvasChild->InternalDrawContent(canvas, true);
261 }
262 }
263
264 if (needApplyMatrix) {
265 DrawPropertyDrawableRange(RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::RESTORE_ALL,
266 canvas);
267 } else {
268 DrawPropertyDrawableRange(RSPropertyDrawableSlot::FOREGROUND_STYLE, RSPropertyDrawableSlot::PIXEL_STRETCH,
269 canvas);
270 }
271 }
272 } // namespace Rosen
273 } // namespace OHOS
274