1 /*
2 * Copyright (c) 2024 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 "drawable/rs_drawable.h"
17
18 #include <limits>
19
20 #include "drawable/rs_misc_drawable.h"
21 #include "drawable/rs_property_drawable.h"
22 #include "drawable/rs_property_drawable_background.h"
23 #include "drawable/rs_property_drawable_foreground.h"
24 #include "pipeline/rs_render_node.h"
25 #include "pipeline/rs_surface_render_node.h"
26
27 namespace OHOS::Rosen {
28 namespace {
29 using namespace DrawableV2;
30
31 // NOTE: This LUT should always the same size and order as RSModifierType
32 // key = RSModifierType, value = RSDrawableSlot
33 constexpr int DIRTY_LUT_SIZE = static_cast<int>(RSModifierType::MAX_RS_MODIFIER_TYPE);
34 static constexpr std::array<RSDrawableSlot, DIRTY_LUT_SIZE> g_propertyToDrawableLut = {
35 RSDrawableSlot::INVALID, // INVALID
36 RSDrawableSlot::CLIP_TO_BOUNDS, // BOUNDS
37 RSDrawableSlot::FRAME_OFFSET, // FRAME
38 RSDrawableSlot::INVALID, // POSITION_Z
39 RSDrawableSlot::INVALID, // POSITION_Z_APPLICABLE_CAMERA3D
40 RSDrawableSlot::INVALID, // PIVOT
41 RSDrawableSlot::INVALID, // PIVOT_Z
42 RSDrawableSlot::INVALID, // QUATERNION
43 RSDrawableSlot::INVALID, // ROTATION
44 RSDrawableSlot::INVALID, // ROTATION_X
45 RSDrawableSlot::INVALID, // ROTATION_Y
46 RSDrawableSlot::INVALID, // CAMERA_DISTANCE
47 RSDrawableSlot::INVALID, // SCALE
48 RSDrawableSlot::INVALID, // SCALE_Z
49 RSDrawableSlot::INVALID, // SKEW
50 RSDrawableSlot::INVALID, // PERSP
51 RSDrawableSlot::INVALID, // TRANSLATE
52 RSDrawableSlot::INVALID, // TRANSLATE_Z
53 RSDrawableSlot::INVALID, // SUBLAYER_TRANSFORM
54 RSDrawableSlot::CLIP_TO_BOUNDS, // CORNER_RADIUS
55 RSDrawableSlot::INVALID, // ALPHA
56 RSDrawableSlot::INVALID, // ALPHA_OFFSCREEN
57 RSDrawableSlot::FOREGROUND_COLOR, // FOREGROUND_COLOR
58 RSDrawableSlot::BACKGROUND_COLOR, // BACKGROUND_COLOR
59 RSDrawableSlot::BACKGROUND_SHADER, // BACKGROUND_SHADER
60 RSDrawableSlot::BACKGROUND_SHADER, // BACKGROUND_SHADER_PROGRESS
61 RSDrawableSlot::BACKGROUND_IMAGE, // BG_IMAGE
62 RSDrawableSlot::BACKGROUND_IMAGE, // BG_IMAGE_INNER_RECT
63 RSDrawableSlot::BACKGROUND_IMAGE, // BG_IMAGE_WIDTH
64 RSDrawableSlot::BACKGROUND_IMAGE, // BG_IMAGE_HEIGHT
65 RSDrawableSlot::BACKGROUND_IMAGE, // BG_IMAGE_POSITION_X
66 RSDrawableSlot::BACKGROUND_IMAGE, // BG_IMAGE_POSITION_Y
67 RSDrawableSlot::INVALID, // SURFACE_BG_COLOR
68 RSDrawableSlot::BORDER, // BORDER_COLOR
69 RSDrawableSlot::BORDER, // BORDER_WIDTH
70 RSDrawableSlot::BORDER, // BORDER_STYLE
71 RSDrawableSlot::BORDER, // BORDER_DASH_WIDTH
72 RSDrawableSlot::BORDER, // BORDER_DASH_GAP
73 RSDrawableSlot::COMPOSITING_FILTER, // FILTER
74 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_FILTER
75 RSDrawableSlot::COMPOSITING_FILTER, // LINEAR_GRADIENT_BLUR_PARA
76 RSDrawableSlot::DYNAMIC_LIGHT_UP, // DYNAMIC_LIGHT_UP_RATE
77 RSDrawableSlot::DYNAMIC_LIGHT_UP, // DYNAMIC_LIGHT_UP_DEGREE
78 RSDrawableSlot::BLENDER, // FG_BRIGHTNESS_RATES
79 RSDrawableSlot::BLENDER, // FG_BRIGHTNESS_SATURATION
80 RSDrawableSlot::BLENDER, // FG_BRIGHTNESS_POSCOEFF
81 RSDrawableSlot::BLENDER, // FG_BRIGHTNESS_NEGCOEFF
82 RSDrawableSlot::BLENDER, // FG_BRIGHTNESS_FRACTION
83 RSDrawableSlot::BACKGROUND_COLOR, // BG_BRIGHTNESS_RATES
84 RSDrawableSlot::BACKGROUND_COLOR, // BG_BRIGHTNESS_SATURATION
85 RSDrawableSlot::BACKGROUND_COLOR, // BG_BRIGHTNESS_POSCOEFF
86 RSDrawableSlot::BACKGROUND_COLOR, // BG_BRIGHTNESS_NEGCOEFF
87 RSDrawableSlot::BACKGROUND_COLOR, // BG_BRIGHTNESS_FRACTION
88 RSDrawableSlot::FRAME_OFFSET, // FRAME_GRAVITY
89 RSDrawableSlot::CLIP_TO_BOUNDS, // CLIP_RRECT
90 RSDrawableSlot::CLIP_TO_BOUNDS, // CLIP_BOUNDS
91 RSDrawableSlot::CLIP_TO_BOUNDS, // CLIP_TO_BOUNDS
92 RSDrawableSlot::CLIP_TO_FRAME, // CLIP_TO_FRAME
93 RSDrawableSlot::INVALID, // VISIBLE
94 RSDrawableSlot::SHADOW, // SHADOW_COLOR
95 RSDrawableSlot::SHADOW, // SHADOW_OFFSET_X
96 RSDrawableSlot::SHADOW, // SHADOW_OFFSET_Y
97 RSDrawableSlot::SHADOW, // SHADOW_ALPHA
98 RSDrawableSlot::SHADOW, // SHADOW_ELEVATION
99 RSDrawableSlot::SHADOW, // SHADOW_RADIUS
100 RSDrawableSlot::SHADOW, // SHADOW_PATH
101 RSDrawableSlot::SHADOW, // SHADOW_MASK
102 RSDrawableSlot::SHADOW, // SHADOW_COLOR_STRATEGY
103 RSDrawableSlot::MASK, // MASK
104 RSDrawableSlot::FOREGROUND_FILTER, // SPHERIZE
105 RSDrawableSlot::LIGHT_UP_EFFECT, // LIGHT_UP_EFFECT
106 RSDrawableSlot::PIXEL_STRETCH, // PIXEL_STRETCH
107 RSDrawableSlot::PIXEL_STRETCH, // PIXEL_STRETCH_PERCENT
108 RSDrawableSlot::PIXEL_STRETCH, // PIXEL_STRETCH_TILE_MODE
109 RSDrawableSlot::USE_EFFECT, // USE_EFFECT
110 RSDrawableSlot::USE_EFFECT, // USE_EFFECT_TYPE
111 RSDrawableSlot::BLENDER, // COLOR_BLEND_MODE
112 RSDrawableSlot::BLENDER, // COLOR_BLEND_APPLY_TYPE
113 RSDrawableSlot::INVALID, // SANDBOX
114 RSDrawableSlot::COLOR_FILTER, // GRAY_SCALE
115 RSDrawableSlot::COLOR_FILTER, // BRIGHTNESS
116 RSDrawableSlot::COLOR_FILTER, // CONTRAST
117 RSDrawableSlot::COLOR_FILTER, // SATURATE
118 RSDrawableSlot::COLOR_FILTER, // SEPIA
119 RSDrawableSlot::COLOR_FILTER, // INVERT
120 RSDrawableSlot::BINARIZATION, // AIINVERT
121 RSDrawableSlot::BACKGROUND_FILTER, // SYSTEMBAREFFECT
122 RSDrawableSlot::BACKGROUND_FILTER, // WATER_RIPPLE_PROGRESS
123 RSDrawableSlot::BACKGROUND_FILTER, // WATER_RIPPLE_EFFECT
124 RSDrawableSlot::COLOR_FILTER, // HUE_ROTATE
125 RSDrawableSlot::COLOR_FILTER, // COLOR_BLEND
126 RSDrawableSlot::PARTICLE_EFFECT, // PARTICLE
127 RSDrawableSlot::SHADOW, // SHADOW_IS_FILLED
128 RSDrawableSlot::OUTLINE, // OUTLINE_COLOR
129 RSDrawableSlot::OUTLINE, // OUTLINE_WIDTH
130 RSDrawableSlot::OUTLINE, // OUTLINE_STYLE
131 RSDrawableSlot::OUTLINE, // OUTLINE_DASH_WIDTH
132 RSDrawableSlot::OUTLINE, // OUTLINE_DASH_GAP
133 RSDrawableSlot::OUTLINE, // OUTLINE_RADIUS
134 RSDrawableSlot::INVALID, // GREY_COEF
135 RSDrawableSlot::POINT_LIGHT, // LIGHT_INTENSITY
136 RSDrawableSlot::POINT_LIGHT, // LIGHT_COLOR
137 RSDrawableSlot::POINT_LIGHT, // LIGHT_POSITION
138 RSDrawableSlot::POINT_LIGHT, // ILLUMINATED_BORDER_WIDTH
139 RSDrawableSlot::POINT_LIGHT, // ILLUMINATED_TYPE
140 RSDrawableSlot::POINT_LIGHT, // BLOOM
141 RSDrawableSlot::FOREGROUND_FILTER, // FOREGROUND_EFFECT_RADIUS
142 RSDrawableSlot::CHILDREN, // USE_SHADOW_BATCHING,
143 RSDrawableSlot::FOREGROUND_FILTER, // MOTION_BLUR_PARA
144 RSDrawableSlot::PARTICLE_EFFECT, // PARTICLE_EMITTER_UPDATER
145 RSDrawableSlot::PARTICLE_EFFECT, // PARTICLE_NOISE_FIELD
146 RSDrawableSlot::FOREGROUND_FILTER, // FLY_OUT_DEGREE
147 RSDrawableSlot::FOREGROUND_FILTER, // FLY_OUT_PARAMS
148 RSDrawableSlot::FOREGROUND_FILTER, // DISTORTION_K
149 RSDrawableSlot::DYNAMIC_DIM, // DYNAMIC_DIM_DEGREE,
150 RSDrawableSlot::BACKGROUND_FILTER, // MAGNIFIER_PARA,
151 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_RADIUS,
152 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_SATURATION,
153 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_BRIGHTNESS,
154 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_MASK_COLOR,
155 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_COLOR_MODE,
156 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_RADIUS_X,
157 RSDrawableSlot::BACKGROUND_FILTER, // BACKGROUND_BLUR_RADIUS_Y,
158 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS,
159 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_SATURATION,
160 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_BRIGHTNESS,
161 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_MASK_COLOR,
162 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_COLOR_MODE,
163 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS_X,
164 RSDrawableSlot::COMPOSITING_FILTER, // FOREGROUND_BLUR_RADIUS_Y,
165 RSDrawableSlot::FOREGROUND_FILTER, // ATTRACTION_FRACTION
166 RSDrawableSlot::FOREGROUND_FILTER, // ATTRACTION_DSTPOINT
167 RSDrawableSlot::INVALID, // CUSTOM
168 RSDrawableSlot::INVALID, // EXTENDED
169 RSDrawableSlot::TRANSITION, // TRANSITION
170 RSDrawableSlot::BACKGROUND_STYLE, // BACKGROUND_STYLE
171 RSDrawableSlot::CONTENT_STYLE, // CONTENT_STYLE
172 RSDrawableSlot::FOREGROUND_STYLE, // FOREGROUND_STYLE
173 RSDrawableSlot::OVERLAY, // OVERLAY_STYLE
174 RSDrawableSlot::INVALID, // NODE_MODIFIER
175 RSDrawableSlot::ENV_FOREGROUND_COLOR, // ENV_FOREGROUND_COLOR
176 RSDrawableSlot::ENV_FOREGROUND_COLOR_STRATEGY, // ENV_FOREGROUND_COLOR_STRATEGY
177 RSDrawableSlot::INVALID, // GEOMETRYTRANS
178 RSDrawableSlot::CUSTOM_CLIP_TO_FRAME, // CUSTOM_CLIP_TO_FRAME,
179 RSDrawableSlot::INVALID, // HDR_BRIGHTNESS
180 RSDrawableSlot::BACKGROUND_FILTER, // BEHIND_WINDOW_FILTER_ENABLED
181 RSDrawableSlot::BACKGROUND_FILTER, // BEHIND_WINDOW_FILTER_RADIUS
182 RSDrawableSlot::BACKGROUND_FILTER, // BEHIND_WINDOW_FILTER_SATURATION
183 RSDrawableSlot::BACKGROUND_FILTER, // BEHIND_WINDOW_FILTER_BRIGHTNESS
184 RSDrawableSlot::BACKGROUND_FILTER, // BEHIND_WINDOW_FILTER_MASK_COLOR
185 RSDrawableSlot::CHILDREN, // CHILDREN
186 };
187
188 // Check if g_propertyToDrawableLut size match and is fully initialized (the last element should not be default value)
189 static_assert(g_propertyToDrawableLut.size() == static_cast<size_t>(RSModifierType::MAX_RS_MODIFIER_TYPE));
190 static_assert(g_propertyToDrawableLut.back() != RSDrawableSlot {});
191
192 // Randomly check some LUT index and value
193 static_assert(g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::USE_EFFECT)] == RSDrawableSlot::USE_EFFECT);
194 static_assert(
195 g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::FOREGROUND_COLOR)] == RSDrawableSlot::FOREGROUND_COLOR);
196 static_assert(
197 g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::CLIP_TO_FRAME)] == RSDrawableSlot::CLIP_TO_FRAME);
198 static_assert(
199 g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::USE_SHADOW_BATCHING)] == RSDrawableSlot::CHILDREN);
200 static_assert(g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::TRANSITION)] == RSDrawableSlot::TRANSITION);
201 static_assert(g_propertyToDrawableLut[static_cast<size_t>(RSModifierType::CHILDREN)] == RSDrawableSlot::CHILDREN);
202
203 template<RSModifierType type>
ModifierGenerator(const RSRenderNode & node)204 static inline RSDrawable::Ptr ModifierGenerator(const RSRenderNode& node)
205 {
206 return RSCustomModifierDrawable::OnGenerate(node, type);
207 }
208
209 // NOTE: This LUT should always the same size as RSDrawableSlot
210 // index = RSDrawableSlotType, value = DrawableGenerator
211 constexpr int GEN_LUT_SIZE = static_cast<int>(RSDrawableSlot::MAX);
212 static const std::array<RSDrawable::Generator, GEN_LUT_SIZE> g_drawableGeneratorLut = {
213 nullptr, // SAVE_ALL
214
215 // Bounds Geometry
216 RSMaskDrawable::OnGenerate, // MASK,
217 ModifierGenerator<RSModifierType::TRANSITION>, // TRANSITION,
218 RSEnvFGColorDrawable::OnGenerate, // ENV_FOREGROUND_COLOR,
219 RSShadowDrawable::OnGenerate, // SHADOW,
220 RSForegroundFilterDrawable::OnGenerate, // FOREGROUND_FILTER
221 RSOutlineDrawable::OnGenerate, // OUTLINE,
222
223 // BG properties in Bounds Clip
224 nullptr, // BG_SAVE_BOUNDS,
225 nullptr, // CLIP_TO_BOUNDS,
226 RSBeginBlenderDrawable::OnGenerate, // BLENDER,
227 RSBackgroundColorDrawable::OnGenerate, // BACKGROUND_COLOR,
228 RSBackgroundShaderDrawable::OnGenerate, // BACKGROUND_SHADER,
229 RSBackgroundImageDrawable::OnGenerate, // BACKGROUND_IMAGE,
230 RSBackgroundFilterDrawable::OnGenerate, // BACKGROUND_FILTER,
231 RSUseEffectDrawable::OnGenerate, // USE_EFFECT,
232 ModifierGenerator<RSModifierType::BACKGROUND_STYLE>, // BACKGROUND_STYLE,
233 RSDynamicLightUpDrawable::OnGenerate, // DYNAMIC_LIGHT_UP,
234 RSEnvFGColorStrategyDrawable::OnGenerate, // ENV_FOREGROUND_COLOR_STRATEGY,
235 nullptr, // BG_RESTORE_BOUNDS,
236
237 // Frame Geometry
238 nullptr, // SAVE_FRAME,
239 RSFrameOffsetDrawable::OnGenerate, // FRAME_OFFSET,
240 RSClipToFrameDrawable::OnGenerate, // CLIP_TO_FRAME,
241 RSCustomClipToFrameDrawable::OnGenerate, // CUSTOM_CLIP_TO_FRAME,
242 ModifierGenerator<RSModifierType::CONTENT_STYLE>, // CONTENT_STYLE,
243 RSChildrenDrawable::OnGenerate, // CHILDREN,
244 ModifierGenerator<RSModifierType::FOREGROUND_STYLE>, // FOREGROUND_STYLE,
245 nullptr, // RESTORE_FRAME,
246
247 // FG properties in Bounds clip
248 nullptr, // FG_SAVE_BOUNDS,
249 nullptr, // FG_CLIP_TO_BOUNDS,
250 RSBinarizationDrawable::OnGenerate, // BINARIZATION,
251 RSColorFilterDrawable::OnGenerate, // COLOR_FILTER,
252 RSLightUpEffectDrawable::OnGenerate, // LIGHT_UP_EFFECT,
253 RSDynamicDimDrawable::OnGenerate, // DYNAMIC_DIM,
254 RSCompositingFilterDrawable::OnGenerate, // COMPOSITING_FILTER,
255 RSForegroundColorDrawable::OnGenerate, // FOREGROUND_COLOR,
256 nullptr, // FG_RESTORE_BOUNDS,
257
258 // No clip (unless ClipToBounds is set)
259 RSPointLightDrawable::OnGenerate, // POINT_LIGHT,
260 RSBorderDrawable::OnGenerate, // BORDER,
261 ModifierGenerator<RSModifierType::OVERLAY_STYLE>, // OVERLAY,
262 RSParticleDrawable::OnGenerate, // PARTICLE_EFFECT,
263 RSPixelStretchDrawable::OnGenerate, // PIXEL_STRETCH,
264
265 // Restore state
266 RSEndBlenderDrawable::OnGenerate, // RESTORE_BLENDER,
267 RSForegroundFilterRestoreDrawable::OnGenerate, // RESTORE_FOREGROUND_FILTER
268 nullptr, // RESTORE_ALL,
269 };
270
271 enum DrawableVecStatus : uint8_t {
272 CLIP_TO_BOUNDS = 1 << 0,
273 BG_BOUNDS_PROPERTY = 1 << 1,
274 FG_BOUNDS_PROPERTY = 1 << 2,
275 ENV_CHANGED = 1 << 3,
276 // Used by skip logic in RSRenderNode::UpdateDisplayList
277 FRAME_NOT_EMPTY = 1 << 4,
278 NODE_NOT_EMPTY = 1 << 5,
279
280 // masks
281 BOUNDS_MASK = CLIP_TO_BOUNDS | BG_BOUNDS_PROPERTY | FG_BOUNDS_PROPERTY,
282 FRAME_MASK = FRAME_NOT_EMPTY,
283 OTHER_MASK = ENV_CHANGED,
284 };
285
HasPropertyDrawableInRange(const RSDrawable::Vec & drawableVec,RSDrawableSlot begin,RSDrawableSlot end)286 inline static bool HasPropertyDrawableInRange(
287 const RSDrawable::Vec& drawableVec, RSDrawableSlot begin, RSDrawableSlot end) noexcept
288 {
289 // Note: the loop range is [begin, end], both end is included.
290 auto beginIt = drawableVec.begin() + static_cast<size_t>(begin);
291 auto endIt = drawableVec.begin() + static_cast<size_t>(end) + 1;
292 return std::any_of(beginIt, endIt, [](const auto& Ptr) { return Ptr != nullptr; });
293 }
294
CalculateDrawableVecStatus(RSRenderNode & node,const RSDrawable::Vec & drawableVec)295 static uint8_t CalculateDrawableVecStatus(RSRenderNode& node, const RSDrawable::Vec& drawableVec)
296 {
297 uint8_t result = 0;
298 bool nodeNotEmpty = false;
299 auto& properties = node.GetRenderProperties();
300
301 // ClipToBounds if either 1. is surface node, 2. has explicit clip properties, 3. has blend mode
302 bool shouldClipToBounds = node.IsInstanceOf<RSSurfaceRenderNode>() || properties.GetClipToBounds() ||
303 properties.GetClipToRRect() || properties.GetClipBounds() != nullptr ||
304 properties.GetColorBlendMode() != static_cast<int>(RSColorBlendMode::NONE) ||
305 properties.IsFgBrightnessValid();
306 if (shouldClipToBounds) {
307 result |= DrawableVecStatus::CLIP_TO_BOUNDS;
308 }
309
310 if (HasPropertyDrawableInRange(
311 drawableVec, RSDrawableSlot::CONTENT_BEGIN, RSDrawableSlot::CONTENT_END)) {
312 nodeNotEmpty = true;
313 result |= DrawableVecStatus::FRAME_NOT_EMPTY;
314 }
315
316 if (HasPropertyDrawableInRange(
317 drawableVec, RSDrawableSlot::BG_PROPERTIES_BEGIN, RSDrawableSlot::BG_PROPERTIES_END)) {
318 result |= DrawableVecStatus::BG_BOUNDS_PROPERTY;
319 nodeNotEmpty = true;
320 }
321 if (HasPropertyDrawableInRange(
322 drawableVec, RSDrawableSlot::FG_PROPERTIES_BEGIN, RSDrawableSlot::FG_PROPERTIES_END)) {
323 result |= DrawableVecStatus::FG_BOUNDS_PROPERTY;
324 nodeNotEmpty = true;
325 }
326
327 nodeNotEmpty = nodeNotEmpty ||
328 HasPropertyDrawableInRange(
329 drawableVec, RSDrawableSlot::TRANSITION_PROPERTIES_BEGIN, RSDrawableSlot::TRANSITION_PROPERTIES_END) ||
330 HasPropertyDrawableInRange(
331 drawableVec, RSDrawableSlot::EXTRA_PROPERTIES_BEGIN, RSDrawableSlot::EXTRA_PROPERTIES_END);
332 if (nodeNotEmpty) {
333 // Set NODE_NOT_EMPTY flag if any drawable (include frame/bg/fg/transition/extra) is set
334 result |= DrawableVecStatus::NODE_NOT_EMPTY;
335 }
336
337 // Foreground color & Background Effect & Blend Mode should be processed here
338 if (drawableVec[static_cast<size_t>(RSDrawableSlot::ENV_FOREGROUND_COLOR)] ||
339 drawableVec[static_cast<size_t>(RSDrawableSlot::ENV_FOREGROUND_COLOR_STRATEGY)] ||
340 drawableVec[static_cast<size_t>(RSDrawableSlot::BLENDER)] ||
341 (node.GetType() == RSRenderNodeType::EFFECT_NODE &&
342 drawableVec[static_cast<size_t>(RSDrawableSlot::BACKGROUND_FILTER)])) {
343 result |= DrawableVecStatus::ENV_CHANGED;
344 }
345
346 return result;
347 }
348
SaveRestoreHelper(RSDrawable::Vec & drawableVec,RSDrawableSlot slot1,RSDrawableSlot slot2,RSPaintFilterCanvas::SaveType type=RSPaintFilterCanvas::kCanvas)349 inline static void SaveRestoreHelper(RSDrawable::Vec& drawableVec, RSDrawableSlot slot1, RSDrawableSlot slot2,
350 RSPaintFilterCanvas::SaveType type = RSPaintFilterCanvas::kCanvas)
351 {
352 if (type == RSPaintFilterCanvas::kNone) {
353 return;
354 }
355 if (type == RSPaintFilterCanvas::kCanvas) {
356 auto count = std::make_shared<uint32_t>(std::numeric_limits<uint32_t>::max());
357 drawableVec[static_cast<size_t>(slot1)] = std::make_unique<RSSaveDrawable>(count);
358 drawableVec[static_cast<size_t>(slot2)] = std::make_unique<RSRestoreDrawable>(count);
359 } else {
360 auto status = std::make_shared<RSPaintFilterCanvas::SaveStatus>();
361 drawableVec[static_cast<size_t>(slot1)] = std::make_unique<RSCustomSaveDrawable>(status, type);
362 drawableVec[static_cast<size_t>(slot2)] = std::make_unique<RSCustomRestoreDrawable>(status);
363 }
364 }
365
OptimizeBoundsSaveRestore(RSRenderNode & node,RSDrawable::Vec & drawableVec,uint8_t flags)366 static void OptimizeBoundsSaveRestore(RSRenderNode& node, RSDrawable::Vec& drawableVec, uint8_t flags)
367 {
368 // Erase existing save/clip/restore before re-generating
369 constexpr static std::array boundsSlotsToErase = {
370 RSDrawableSlot::BG_SAVE_BOUNDS,
371 RSDrawableSlot::CLIP_TO_BOUNDS,
372 RSDrawableSlot::BG_RESTORE_BOUNDS,
373 RSDrawableSlot::FG_SAVE_BOUNDS,
374 RSDrawableSlot::FG_CLIP_TO_BOUNDS,
375 RSDrawableSlot::FG_RESTORE_BOUNDS,
376 };
377 for (auto& slot : boundsSlotsToErase) {
378 drawableVec[static_cast<size_t>(slot)] = nullptr;
379 }
380
381 if (flags & DrawableVecStatus::CLIP_TO_BOUNDS) {
382 // case 1: ClipToBounds set.
383 // add one clip, and reuse SAVE_ALL and RESTORE_ALL.
384 drawableVec[static_cast<size_t>(RSDrawableSlot::CLIP_TO_BOUNDS)] = RSClipToBoundsDrawable::OnGenerate(node);
385 return;
386 }
387
388 if ((flags & DrawableVecStatus::BG_BOUNDS_PROPERTY) && (flags & DrawableVecStatus::FG_BOUNDS_PROPERTY)) {
389 // case 2: ClipToBounds not set and we have bounds properties both BG and FG.
390 // add two sets of save/clip/restore before & after content.
391
392 // part 1: before children
393 SaveRestoreHelper(drawableVec, RSDrawableSlot::BG_SAVE_BOUNDS, RSDrawableSlot::BG_RESTORE_BOUNDS,
394 RSPaintFilterCanvas::kCanvas);
395 drawableVec[static_cast<size_t>(RSDrawableSlot::CLIP_TO_BOUNDS)] = RSClipToBoundsDrawable::OnGenerate(node);
396
397 // part 2: after children, add aliases
398 drawableVec[static_cast<size_t>(RSDrawableSlot::FG_SAVE_BOUNDS)] =
399 drawableVec[static_cast<size_t>(RSDrawableSlot::BG_SAVE_BOUNDS)];
400 drawableVec[static_cast<size_t>(RSDrawableSlot::FG_CLIP_TO_BOUNDS)] =
401 drawableVec[static_cast<size_t>(RSDrawableSlot::CLIP_TO_BOUNDS)];
402 drawableVec[static_cast<size_t>(RSDrawableSlot::FG_RESTORE_BOUNDS)] =
403 drawableVec[static_cast<size_t>(RSDrawableSlot::BG_RESTORE_BOUNDS)];
404 return;
405 }
406
407 if (flags & DrawableVecStatus::BG_BOUNDS_PROPERTY) {
408 // case 3: ClipToBounds not set and we have background bounds properties.
409 SaveRestoreHelper(drawableVec, RSDrawableSlot::BG_SAVE_BOUNDS, RSDrawableSlot::BG_RESTORE_BOUNDS,
410 RSPaintFilterCanvas::kCanvas);
411
412 drawableVec[static_cast<size_t>(RSDrawableSlot::CLIP_TO_BOUNDS)] = RSClipToBoundsDrawable::OnGenerate(node);
413 return;
414 }
415
416 if (flags & DrawableVecStatus::FG_BOUNDS_PROPERTY) {
417 // case 4: ClipToBounds not set and we have foreground bounds properties.
418 SaveRestoreHelper(drawableVec, RSDrawableSlot::FG_SAVE_BOUNDS, RSDrawableSlot::FG_RESTORE_BOUNDS,
419 RSPaintFilterCanvas::kCanvas);
420
421 drawableVec[static_cast<size_t>(RSDrawableSlot::FG_CLIP_TO_BOUNDS)] = RSClipToBoundsDrawable::OnGenerate(node);
422 return;
423 }
424 // case 5: ClipToBounds not set and no bounds properties, no need to save/clip/restore.
425 // nothing to do
426 }
427
OptimizeFrameSaveRestore(RSRenderNode & node,RSDrawable::Vec & drawableVec,uint8_t flags)428 static void OptimizeFrameSaveRestore(RSRenderNode& node, RSDrawable::Vec& drawableVec, uint8_t flags)
429 {
430 constexpr static std::array frameSlotsToErase = {
431 RSDrawableSlot::SAVE_FRAME,
432 RSDrawableSlot::RESTORE_FRAME,
433 };
434 // Erase existing save/clip/restore before re-generating
435 for (auto& slot : frameSlotsToErase) {
436 drawableVec[static_cast<size_t>(slot)] = nullptr;
437 }
438
439 if (flags & DrawableVecStatus::FRAME_NOT_EMPTY) {
440 SaveRestoreHelper(
441 drawableVec, RSDrawableSlot::SAVE_FRAME, RSDrawableSlot::RESTORE_FRAME, RSPaintFilterCanvas::kCanvas);
442 }
443 }
444
OptimizeGlobalSaveRestore(RSRenderNode & node,RSDrawable::Vec & drawableVec,uint8_t flags)445 static void OptimizeGlobalSaveRestore(RSRenderNode& node, RSDrawable::Vec& drawableVec, uint8_t flags)
446 {
447 constexpr static std::array globalSlotsToErase = {
448 RSDrawableSlot::SAVE_ALL,
449 RSDrawableSlot::RESTORE_ALL,
450 };
451 // Erase existing save/clip/restore before re-generating
452 for (auto& slot : globalSlotsToErase) {
453 drawableVec[static_cast<size_t>(slot)] = nullptr;
454 }
455
456 // Parent will do canvas save/restore, we don't need to do it again
457 uint8_t saveType = RSPaintFilterCanvas::SaveType::kNone;
458 if (flags & DrawableVecStatus::ENV_CHANGED) {
459 // If we change env(fg color, effect, blendMode etc), we need to save env
460 saveType |= RSPaintFilterCanvas::SaveType::kEnv;
461 }
462
463 if (saveType == RSPaintFilterCanvas::SaveType::kNone) {
464 return;
465 }
466 // add save/restore with needed type
467 SaveRestoreHelper(drawableVec, RSDrawableSlot::SAVE_ALL, RSDrawableSlot::RESTORE_ALL,
468 static_cast<RSPaintFilterCanvas::SaveType>(saveType));
469 }
470
471 constexpr std::array boundsDirtyTypes = {
472 RSDrawableSlot::MASK,
473 RSDrawableSlot::SHADOW,
474 RSDrawableSlot::OUTLINE,
475 RSDrawableSlot::FOREGROUND_FILTER,
476 RSDrawableSlot::CLIP_TO_BOUNDS,
477 RSDrawableSlot::BACKGROUND_COLOR,
478 RSDrawableSlot::BACKGROUND_SHADER,
479 RSDrawableSlot::BACKGROUND_IMAGE,
480 RSDrawableSlot::ENV_FOREGROUND_COLOR_STRATEGY,
481 RSDrawableSlot::FRAME_OFFSET,
482 RSDrawableSlot::FG_CLIP_TO_BOUNDS,
483 RSDrawableSlot::FOREGROUND_COLOR,
484 RSDrawableSlot::POINT_LIGHT,
485 RSDrawableSlot::BORDER,
486 RSDrawableSlot::PIXEL_STRETCH,
487 RSDrawableSlot::RESTORE_FOREGROUND_FILTER,
488 };
489 constexpr std::array frameDirtyTypes = {
490 RSDrawableSlot::CLIP_TO_FRAME,
491 RSDrawableSlot::COMPOSITING_FILTER,
492 };
493 constexpr std::array borderDirtyTypes = {
494 RSDrawableSlot::BACKGROUND_COLOR,
495 RSDrawableSlot::BACKGROUND_SHADER,
496 RSDrawableSlot::BACKGROUND_IMAGE,
497 };
498 constexpr std::array bgfilterDirtyTypes = {
499 RSDrawableSlot::PIXEL_STRETCH,
500 };
501 constexpr std::array stretchDirtyTypes = {
502 RSDrawableSlot::BACKGROUND_FILTER,
503 };
504 const std::unordered_set<RSDrawableSlot> fuzeStretchBlurSafeList = {
505 RSDrawableSlot::BG_RESTORE_BOUNDS,
506 RSDrawableSlot::SAVE_FRAME,
507 RSDrawableSlot::RESTORE_FRAME,
508 RSDrawableSlot::FG_SAVE_BOUNDS,
509 RSDrawableSlot::FG_RESTORE_BOUNDS,
510 };
511 template<std::size_t SIZE>
MarkAffectedSlots(const std::array<RSDrawableSlot,SIZE> & affectedSlots,const RSDrawable::Vec & drawableVec,std::unordered_set<RSDrawableSlot> & dirtySlots)512 inline void MarkAffectedSlots(const std::array<RSDrawableSlot, SIZE>& affectedSlots, const RSDrawable::Vec& drawableVec,
513 std::unordered_set<RSDrawableSlot>& dirtySlots)
514 {
515 for (auto slot : affectedSlots) {
516 if (drawableVec[static_cast<size_t>(slot)]) {
517 dirtySlots.emplace(slot);
518 }
519 }
520 }
521 } // namespace
522
CalculateDirtySlots(const ModifierDirtyTypes & dirtyTypes,const Vec & drawableVec)523 std::unordered_set<RSDrawableSlot> RSDrawable::CalculateDirtySlots(
524 const ModifierDirtyTypes& dirtyTypes, const Vec& drawableVec)
525 {
526 // Step 1.1: calculate dirty slots by looking up g_propertyToDrawableLut
527 std::unordered_set<RSDrawableSlot> dirtySlots;
528 for (size_t type = 0; type < static_cast<size_t>(RSModifierType::MAX_RS_MODIFIER_TYPE); type++) {
529 if (!dirtyTypes.test(type)) {
530 continue;
531 }
532 auto dirtySlot = g_propertyToDrawableLut[type];
533 if (dirtySlot != RSDrawableSlot::INVALID) {
534 dirtySlots.emplace(dirtySlot);
535 }
536 }
537
538 // Step 1.2: expand dirty slots by rules
539 // if bounds or cornerRadius changed, mark affected drawables as dirty
540 if (dirtyTypes.test(static_cast<size_t>(RSModifierType::BOUNDS)) ||
541 dirtyTypes.test(static_cast<size_t>(RSModifierType::CORNER_RADIUS)) ||
542 dirtyTypes.test(static_cast<size_t>(RSModifierType::CLIP_BOUNDS))) {
543 MarkAffectedSlots(boundsDirtyTypes, drawableVec, dirtySlots);
544 }
545
546 if (dirtyTypes.test(static_cast<size_t>(RSModifierType::SHADOW_MASK)) || dirtySlots.count(RSDrawableSlot::SHADOW)) {
547 dirtySlots.emplace(RSDrawableSlot::SHADOW);
548 dirtySlots.emplace(RSDrawableSlot::FOREGROUND_FILTER);
549 }
550
551 if (dirtyTypes.test(static_cast<size_t>(RSModifierType::FRAME_GRAVITY))) {
552 dirtySlots.emplace(RSDrawableSlot::CONTENT_STYLE);
553 dirtySlots.emplace(RSDrawableSlot::FOREGROUND_STYLE);
554 }
555
556 // if frame changed, mark affected drawables as dirty
557 if (dirtySlots.count(RSDrawableSlot::FRAME_OFFSET)) {
558 MarkAffectedSlots(frameDirtyTypes, drawableVec, dirtySlots);
559 }
560
561 // if border changed, mark affected drawables as dirty
562 if (dirtySlots.count(RSDrawableSlot::BORDER)) {
563 MarkAffectedSlots(borderDirtyTypes, drawableVec, dirtySlots);
564 }
565
566 // PLANNING: merge these restore operations with RESTORE_ALL drawable
567 if (dirtySlots.count(RSDrawableSlot::FOREGROUND_FILTER)) {
568 dirtySlots.emplace(RSDrawableSlot::RESTORE_FOREGROUND_FILTER);
569 }
570
571 // if pixel stretch changed, mark affected drawables as dirty
572 if (dirtySlots.count(RSDrawableSlot::PIXEL_STRETCH)) {
573 MarkAffectedSlots(stretchDirtyTypes, drawableVec, dirtySlots);
574 }
575 // if background filter changed, mark affected drawables as dirty
576 if (dirtySlots.count(RSDrawableSlot::BACKGROUND_FILTER)) {
577 MarkAffectedSlots(bgfilterDirtyTypes, drawableVec, dirtySlots);
578 }
579
580 return dirtySlots;
581 }
582
UpdateDirtySlots(const RSRenderNode & node,Vec & drawableVec,std::unordered_set<RSDrawableSlot> & dirtySlots)583 bool RSDrawable::UpdateDirtySlots(
584 const RSRenderNode& node, Vec& drawableVec, std::unordered_set<RSDrawableSlot>& dirtySlots)
585 {
586 // Step 2: Update or generate all dirty slots
587 bool drawableAddedOrRemoved = false;
588
589 for (const auto& slot : dirtySlots) {
590 if (auto& drawable = drawableVec[static_cast<size_t>(slot)]) {
591 // If the slot is already created, call OnUpdate
592 if (!drawable->OnUpdate(node)) {
593 // If the slot is no longer needed, destroy it
594 drawable.reset();
595 drawableAddedOrRemoved = true;
596 }
597 } else if (auto& generator = g_drawableGeneratorLut[static_cast<int>(slot)]) {
598 // If the slot is not created, call OnGenerate
599 if (auto drawable = generator(node)) {
600 drawableVec[static_cast<size_t>(slot)] = std::move(drawable);
601 drawableAddedOrRemoved = true;
602 }
603 }
604 }
605 // If at this point the child node happens to be null, and the scenario involves deleting the child node
606 // when the parent node is not on the tree, it is necessary to manually mark drawableAddedOrRemoved as true.
607 if (!drawableAddedOrRemoved && dirtySlots.count(RSDrawableSlot::CHILDREN) &&
608 drawableVec[static_cast<int8_t>(RSDrawableSlot::CHILDREN)] == nullptr) {
609 drawableAddedOrRemoved = true;
610 }
611
612 return drawableAddedOrRemoved;
613 }
614
FuzeDrawableSlots(const RSRenderNode & node,Vec & drawableVec)615 bool RSDrawable::FuzeDrawableSlots(const RSRenderNode& node, Vec& drawableVec)
616 {
617 // fuze the pixel stretch with MESA blur
618 if (!RSSystemProperties::GetMESABlurFuzedEnabled() ||
619 !drawableVec[static_cast<size_t>(RSDrawableSlot::BACKGROUND_FILTER)] ||
620 !drawableVec[static_cast<size_t>(RSDrawableSlot::PIXEL_STRETCH)]) {
621 return false;
622 }
623
624 auto &filterDrawable = drawableVec[static_cast<size_t>(RSDrawableSlot::BACKGROUND_FILTER)];
625 auto bgFilterDrawable = std::static_pointer_cast<RSBackgroundFilterDrawable>(filterDrawable);
626 bgFilterDrawable->RemovePixelStretch();
627
628 auto &stretchDrawable = drawableVec[static_cast<size_t>(RSDrawableSlot::PIXEL_STRETCH)];
629 auto pixelStretchDrawable = std::static_pointer_cast<RSPixelStretchDrawable>(stretchDrawable);
630 pixelStretchDrawable->OnUpdate(node);
631
632 size_t start = static_cast<size_t>(RSDrawableSlot::BACKGROUND_FILTER) + 1;
633 size_t end = static_cast<size_t>(RSDrawableSlot::PIXEL_STRETCH);
634 // We do not fuze if drawableSlots between BACKGROUND_FILTER and PIXEL_STRETCH exist
635 for (size_t ptr = start; ptr < end; ptr++) {
636 if (!fuzeStretchBlurSafeList.count(static_cast<RSDrawableSlot>(ptr)) && drawableVec[ptr]) {
637 return false;
638 }
639 }
640 if (bgFilterDrawable->FuzePixelStretch(node)) {
641 float INFTY = std::numeric_limits<float>::infinity();
642 pixelStretchDrawable->SetPixelStretch(Vector4f{ INFTY, INFTY, INFTY, INFTY });
643 return true;
644 }
645
646 return false;
647 }
648
UpdateSaveRestore(RSRenderNode & node,Vec & drawableVec,uint8_t & drawableVecStatus)649 void RSDrawable::UpdateSaveRestore(RSRenderNode& node, Vec& drawableVec, uint8_t& drawableVecStatus)
650 {
651 // ====================================================================
652 // Step 3: Universal save/clip/restore optimization
653
654 // Step 3.1: calculate new drawable map status
655 auto drawableVecStatusNew = CalculateDrawableVecStatus(node, drawableVec);
656
657 uint8_t changedBits = drawableVecStatus ^ drawableVecStatusNew;
658 if (changedBits == 0) {
659 // nothing to do
660 return;
661 }
662
663 // Step 3.2: update save/clip/restore for changed types
664 if (changedBits & BOUNDS_MASK) {
665 // update bounds save/clip if need
666 OptimizeBoundsSaveRestore(node, drawableVec, drawableVecStatusNew);
667 }
668 if (changedBits & FRAME_MASK) {
669 // update frame save/clip if need
670 OptimizeFrameSaveRestore(node, drawableVec, drawableVecStatusNew);
671 }
672 if (changedBits & OTHER_MASK) {
673 // update global save/clip if need
674 OptimizeGlobalSaveRestore(node, drawableVec, drawableVecStatusNew);
675 }
676
677 drawableVecStatus = drawableVecStatusNew;
678 }
679 } // namespace OHOS::Rosen
680