• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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