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 #ifndef USE_ROSEN_DRAWING
24 #include "include/core/SkCanvas.h"
25 #else
26 #include "recording/recording_canvas.h"
27 #endif
28 #include "memory/rs_memory_track.h"
29 #include "memory/rs_tag_tracker.h"
30 #include "pipeline/rs_paint_filter_canvas.h"
31 #include "property/rs_properties_painter.h"
32 #include "render/rs_blur_filter.h"
33 #include "render/rs_light_up_effect_filter.h"
34 #include "platform/common/rs_log.h"
35 #include "visitor/rs_node_visitor.h"
36
37 namespace OHOS {
38 namespace Rosen {
39 namespace {
40 constexpr PropertyId ANONYMOUS_MODIFIER_ID = 0;
41 }
42
RSCanvasRenderNode(NodeId id,std::weak_ptr<RSContext> context)43 RSCanvasRenderNode::RSCanvasRenderNode(NodeId id, std::weak_ptr<RSContext> context) : RSRenderNode(id, context)
44 {
45 MemoryInfo info = {sizeof(*this), ExtractPid(id), id, MEMORY_TYPE::MEM_RENDER_NODE};
46 MemoryTrack::Instance().AddNodeRecord(id, info);
47 }
48
~RSCanvasRenderNode()49 RSCanvasRenderNode::~RSCanvasRenderNode()
50 {
51 MemoryTrack::Instance().RemoveNodeRecord(GetId());
52 }
53
54 #ifndef USE_ROSEN_DRAWING
UpdateRecording(std::shared_ptr<DrawCmdList> drawCmds,RSModifierType type)55 void RSCanvasRenderNode::UpdateRecording(std::shared_ptr<DrawCmdList> drawCmds, RSModifierType type)
56 {
57 if (!drawCmds || drawCmds->GetSize() == 0) {
58 return;
59 }
60 auto renderProperty = std::make_shared<RSRenderProperty<DrawCmdListPtr>>(drawCmds, ANONYMOUS_MODIFIER_ID);
61 auto renderModifier = std::make_shared<RSDrawCmdListRenderModifier>(renderProperty);
62 renderModifier->SetType(type);
63 AddModifier(renderModifier);
64 }
65 #else
UpdateRecording(std::shared_ptr<Drawing::DrawCmdList> drawCmds,RSModifierType type)66 void RSCanvasRenderNode::UpdateRecording(std::shared_ptr<Drawing::DrawCmdList> drawCmds, RSModifierType type)
67 {
68 if (!drawCmds || drawCmds->GetData().second == 0) {
69 return;
70 }
71 auto renderProperty = std::make_shared<RSRenderProperty<Drawing::DrawCmdListPtr>>(drawCmds, ANONYMOUS_MODIFIER_ID);
72 auto renderModifier = std::make_shared<RSDrawCmdListRenderModifier>(renderProperty);
73 renderModifier->SetType(type);
74 AddModifier(renderModifier);
75 }
76 #endif
77
ClearRecording()78 void RSCanvasRenderNode::ClearRecording()
79 {
80 RemoveModifier(ANONYMOUS_MODIFIER_ID);
81 }
82
Prepare(const std::shared_ptr<RSNodeVisitor> & visitor)83 void RSCanvasRenderNode::Prepare(const std::shared_ptr<RSNodeVisitor>& visitor)
84 {
85 if (!visitor) {
86 return;
87 }
88 visitor->PrepareCanvasRenderNode(*this);
89 }
90
Process(const std::shared_ptr<RSNodeVisitor> & visitor)91 void RSCanvasRenderNode::Process(const std::shared_ptr<RSNodeVisitor>& visitor)
92 {
93 std::unique_lock<std::mutex> lock(canvasNodeProcessMutex_);
94 if (!visitor) {
95 return;
96 }
97 RSRenderNode::RenderTraceDebug();
98 visitor->ProcessCanvasRenderNode(*this);
99 }
100
ProcessTransitionBeforeChildren(RSPaintFilterCanvas & canvas)101 void RSCanvasRenderNode::ProcessTransitionBeforeChildren(RSPaintFilterCanvas& canvas)
102 {
103 RSRenderNode::ProcessTransitionBeforeChildren(canvas);
104 }
105
ProcessAnimatePropertyBeforeChildren(RSPaintFilterCanvas & canvas)106 void RSCanvasRenderNode::ProcessAnimatePropertyBeforeChildren(RSPaintFilterCanvas& canvas)
107 {
108 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
109 ApplyDrawCmdModifier(context, RSModifierType::TRANSITION);
110 ApplyDrawCmdModifier(context, RSModifierType::ENV_FOREGROUND_COLOR);
111 RSPropertiesPainter::DrawShadow(GetRenderProperties(), canvas);
112 // In NEW_SKIA version, L96 code will cause dump if the 3rd parameter is true.
113 #ifdef NEW_SKIA
114 RSPropertiesPainter::DrawBackground(GetRenderProperties(), canvas, false);
115 #else
116 RSPropertiesPainter::DrawBackground(GetRenderProperties(), canvas);
117 #endif
118
119 if (canvas.GetCacheType() != RSPaintFilterCanvas::CacheType::OFFSCREEN) {
120 if (GetRenderProperties().GetUseEffect()) {
121 RSPropertiesPainter::ApplyBackgroundEffect(GetRenderProperties(), canvas);
122 }
123 RSPropertiesPainter::DrawFilter(GetRenderProperties(), canvas, FilterType::BACKGROUND_FILTER);
124 }
125
126 ApplyDrawCmdModifier(context, RSModifierType::BACKGROUND_STYLE);
127
128 if (GetRenderProperties().IsDynamicLightUpValid()) {
129 RSPropertiesPainter::DrawDynamicLightUp(GetRenderProperties(), canvas);
130 }
131
132 #ifndef USE_ROSEN_DRAWING
133 canvasNodeSaveCount_ = canvas.Save();
134 #else
135 canvasNodeSaveCount_ = canvas.SaveAllStatus();
136 #endif
137 ApplyDrawCmdModifier(context, RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY);
138 #ifndef USE_ROSEN_DRAWING
139 canvas.translate(GetRenderProperties().GetFrameOffsetX(), GetRenderProperties().GetFrameOffsetY());
140 #else
141 canvas.Translate(GetRenderProperties().GetFrameOffsetX(), GetRenderProperties().GetFrameOffsetY());
142 #endif
143
144 if (GetRenderProperties().GetClipToFrame()) {
145 // In NEW_SKIA version, L116 code will cause dump if the 3rd parameter is true.
146 #ifdef NEW_SKIA
147 RSPropertiesPainter::Clip(canvas, GetRenderProperties().GetFrameRect(), false);
148 #else
149 RSPropertiesPainter::Clip(canvas, GetRenderProperties().GetFrameRect());
150 #endif
151 }
152 }
153
ProcessRenderContents(RSPaintFilterCanvas & canvas)154 void RSCanvasRenderNode::ProcessRenderContents(RSPaintFilterCanvas& canvas)
155 {
156 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
157 ApplyDrawCmdModifier(context, RSModifierType::CONTENT_STYLE);
158 }
159
ProcessRenderBeforeChildren(RSPaintFilterCanvas & canvas)160 void RSCanvasRenderNode::ProcessRenderBeforeChildren(RSPaintFilterCanvas& canvas)
161 {
162 ProcessTransitionBeforeChildren(canvas);
163 ProcessAnimatePropertyBeforeChildren(canvas);
164 }
165
ProcessAnimatePropertyAfterChildren(RSPaintFilterCanvas & canvas)166 void RSCanvasRenderNode::ProcessAnimatePropertyAfterChildren(RSPaintFilterCanvas& canvas)
167 {
168 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
169 ApplyDrawCmdModifier(context, RSModifierType::FOREGROUND_STYLE);
170 RSPropertiesPainter::DrawColorFilter(GetRenderProperties(), canvas);
171
172 canvas.RestoreStatus(canvasNodeSaveCount_);
173 if (GetRenderProperties().IsLightUpEffectValid()) {
174 RSPropertiesPainter::DrawLightUpEffect(GetRenderProperties(), canvas);
175 }
176 RSPropertiesPainter::DrawFilter(GetRenderProperties(), canvas, FilterType::FOREGROUND_FILTER);
177 auto para = GetRenderProperties().GetLinearGradientBlurPara();
178 RSPropertiesPainter::DrawLinearGradientBlurFilter(GetRenderProperties(), canvas);
179
180 RSPropertiesPainter::DrawBorder(GetRenderProperties(), canvas);
181 ApplyDrawCmdModifier(context, RSModifierType::OVERLAY_STYLE);
182 RSPropertiesPainter::DrawForegroundColor(GetRenderProperties(), canvas);
183 RSPropertiesPainter::DrawParticle(GetRenderProperties(), canvas);
184 }
185
ProcessTransitionAfterChildren(RSPaintFilterCanvas & canvas)186 void RSCanvasRenderNode::ProcessTransitionAfterChildren(RSPaintFilterCanvas& canvas)
187 {
188 RSPropertiesPainter::DrawPixelStretch(GetRenderProperties(), canvas);
189 RSRenderNode::ProcessRenderAfterChildren(canvas);
190 }
191
ProcessRenderAfterChildren(RSPaintFilterCanvas & canvas)192 void RSCanvasRenderNode::ProcessRenderAfterChildren(RSPaintFilterCanvas& canvas)
193 {
194 ProcessAnimatePropertyAfterChildren(canvas);
195 ProcessTransitionAfterChildren(canvas);
196 canvas.RestoreEnv();
197 }
198
ApplyDrawCmdModifier(RSModifierContext & context,RSModifierType type) const199 void RSCanvasRenderNode::ApplyDrawCmdModifier(RSModifierContext& context, RSModifierType type) const
200 {
201 auto itr = drawCmdModifiers_.find(type);
202 if (itr == drawCmdModifiers_.end() || itr->second.empty()) {
203 return;
204 }
205 for (const auto& modifier : itr->second) {
206 modifier->Apply(context);
207 }
208 }
209
InternalDrawContent(RSPaintFilterCanvas & canvas)210 void RSCanvasRenderNode::InternalDrawContent(RSPaintFilterCanvas& canvas)
211 {
212 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
213 #ifndef USE_ROSEN_DRAWING
214 canvas.translate(GetRenderProperties().GetFrameOffsetX(), GetRenderProperties().GetFrameOffsetY());
215 #else
216 canvas.Translate(GetRenderProperties().GetFrameOffsetX(), GetRenderProperties().GetFrameOffsetY());
217 #endif
218
219 if (GetRenderProperties().GetClipToFrame()) {
220 RSPropertiesPainter::Clip(canvas, GetRenderProperties().GetFrameRect());
221 }
222 ApplyDrawCmdModifier(context, RSModifierType::CONTENT_STYLE);
223
224 // temporary solution for drawing children
225 for (auto& child : GetSortedChildren()) {
226 if (auto canvasChild = ReinterpretCast<RSCanvasRenderNode>(child)) {
227 canvasChild->InternalDrawContent(canvas);
228 }
229 }
230 }
231
OnApplyModifiers()232 void RSCanvasRenderNode::OnApplyModifiers()
233 {
234 GetMutableRenderProperties().backref_ = weak_from_this();
235 }
236
ProcessDrivenBackgroundRender(RSPaintFilterCanvas & canvas)237 void RSCanvasRenderNode::ProcessDrivenBackgroundRender(RSPaintFilterCanvas& canvas)
238 {
239 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
240 RSRenderNode::ProcessRenderBeforeChildren(canvas);
241 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
242 ApplyDrawCmdModifier(context, RSModifierType::TRANSITION);
243 ApplyDrawCmdModifier(context, RSModifierType::ENV_FOREGROUND_COLOR);
244
245 RSPropertiesPainter::DrawShadow(GetRenderProperties(), canvas);
246 RSPropertiesPainter::DrawBackground(GetRenderProperties(), canvas);
247 RSPropertiesPainter::DrawFilter(GetRenderProperties(), canvas, FilterType::BACKGROUND_FILTER);
248 ApplyDrawCmdModifier(context, RSModifierType::BACKGROUND_STYLE);
249 RSRenderNode::ProcessRenderAfterChildren(canvas);
250 #endif
251 }
252
ProcessDrivenContentRender(RSPaintFilterCanvas & canvas)253 void RSCanvasRenderNode::ProcessDrivenContentRender(RSPaintFilterCanvas& canvas)
254 {
255 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
256 canvasNodeSaveCount_ = canvas.Save();
257 canvas.translate(GetRenderProperties().GetFrameOffsetX(), GetRenderProperties().GetFrameOffsetY());
258 DrawDrivenContent(canvas);
259 #endif
260 }
261
ProcessDrivenContentRenderAfterChildren(RSPaintFilterCanvas & canvas)262 void RSCanvasRenderNode::ProcessDrivenContentRenderAfterChildren(RSPaintFilterCanvas& canvas)
263 {
264 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
265 // Unresolvable bug: Driven render do not support DrawFilter/DrawBorder/FOREGROUND_STYLE/OVERLAY_STYLE
266 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
267 ApplyDrawCmdModifier(context, RSModifierType::FOREGROUND_STYLE);
268
269 canvas.RestoreStatus(canvasNodeSaveCount_);
270 #endif
271 }
272
GetDrivenContentClipFrameRect() const273 RectF RSCanvasRenderNode::GetDrivenContentClipFrameRect() const
274 {
275 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
276 // temporary solution for driven content clip
277 RectF rect;
278 auto itr = drawCmdModifiers_.find(RSModifierType::CONTENT_STYLE);
279 if (itr == drawCmdModifiers_.end() || itr->second.empty()) {
280 return rect;
281 }
282 if (!itr->second.empty()) {
283 auto drawCmdModifier = std::static_pointer_cast<RSDrawCmdListRenderModifier>(itr->second.front());
284 if (drawCmdModifier != nullptr) {
285 rect = drawCmdModifier->GetCmdsClipRect();
286 }
287 }
288 return rect;
289 #else
290 return RectF { 0.0f, 0.0f, 0.0f, 0.0f };
291 #endif
292 }
293
DrawDrivenContent(RSPaintFilterCanvas & canvas)294 void RSCanvasRenderNode::DrawDrivenContent(RSPaintFilterCanvas& canvas)
295 {
296 #if defined(RS_ENABLE_DRIVEN_RENDER) && defined(RS_ENABLE_GL)
297 RSModifierContext context = { GetMutableRenderProperties(), &canvas };
298 auto itr = drawCmdModifiers_.find(RSModifierType::CONTENT_STYLE);
299 if (itr == drawCmdModifiers_.end() || itr->second.empty()) {
300 return;
301 }
302 int32_t index = 0;
303 for (const auto& modifier : itr->second) {
304 if (index == 0) {
305 // temporary solution for driven content clip
306 auto drawCmdModifier = std::static_pointer_cast<RSDrawCmdListRenderModifier>(modifier);
307 if (drawCmdModifier != nullptr) {
308 drawCmdModifier->ApplyForDrivenContent(context);
309 index++;
310 continue;
311 }
312 }
313 if (modifier != nullptr) {
314 modifier->Apply(context);
315 }
316 index++;
317 }
318 #endif
319 }
320 } // namespace Rosen
321 } // namespace OHOS
322