1 /*
2 * Copyright (c) 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 "property/rs_property_drawable.h"
17
18 #include "pipeline/rs_render_node.h"
19 #include "platform/common/rs_log.h"
20 #include "property/rs_properties.h"
21 #include "property/rs_property_drawable_bounds_geometry.h"
22 #include "property/rs_property_drawable_frame_geometry.h"
23 #include "property/rs_property_drawable_utilities.h"
24
25 namespace OHOS::Rosen {
26 namespace {
27 template<RSModifierType T>
CustomModifierAdapter(const RSRenderContent &)28 inline RSModifierDrawable::DrawablePtr CustomModifierAdapter(const RSRenderContent&)
29 {
30 return std::make_unique<RSModifierDrawable>(T);
31 }
32
GenerateAlias(RSPropertyDrawableSlot slot)33 inline RSPropertyDrawable::DrawablePtr GenerateAlias(RSPropertyDrawableSlot slot)
34 {
35 return std::make_unique<RSAliasDrawable>(slot);
36 }
37
GenerateSaveRestore(RSPaintFilterCanvas::SaveType type=RSPaintFilterCanvas::kCanvas)38 inline std::pair<RSPropertyDrawable::DrawablePtr, RSPropertyDrawable::DrawablePtr> GenerateSaveRestore(
39 RSPaintFilterCanvas::SaveType type = RSPaintFilterCanvas::kCanvas)
40 {
41 if (type == RSPaintFilterCanvas::kNone) {
42 return {};
43 } else if (type == RSPaintFilterCanvas::kCanvas) {
44 auto count = std::make_shared<uint32_t>(0);
45 return { std::make_unique<RSSaveDrawable>(count), std::make_unique<RSRestoreDrawable>(count) };
46 } else {
47 auto status = std::make_shared<RSPaintFilterCanvas::SaveStatus>();
48 return { std::make_unique<RSCustomSaveDrawable>(status, type),
49 std::make_unique<RSCustomRestoreDrawable>(status) };
50 }
51 }
52
SaveRestoreHelper(RSPropertyDrawable::DrawableVec & drawableVec,RSPropertyDrawableSlot slot1,RSPropertyDrawableSlot slot2,RSPaintFilterCanvas::SaveType saveType)53 inline void SaveRestoreHelper(RSPropertyDrawable::DrawableVec& drawableVec, RSPropertyDrawableSlot slot1,
54 RSPropertyDrawableSlot slot2, RSPaintFilterCanvas::SaveType saveType)
55 {
56 std::tie(drawableVec[static_cast<size_t>(slot1)], drawableVec[static_cast<size_t>(slot2)]) =
57 GenerateSaveRestore(saveType);
58 }
59
60 // key = RSModifierType, value = RSPropertyDrawableType
61 static const std::unordered_map<RSModifierType, RSPropertyDrawableSlot> g_propertyToDrawableLut = {
62 { RSModifierType::INVALID, RSPropertyDrawableSlot::INVALID },
63 { RSModifierType::BOUNDS, RSPropertyDrawableSlot::BOUNDS_MATRIX },
64 { RSModifierType::FRAME, RSPropertyDrawableSlot::FRAME_OFFSET },
65 { RSModifierType::POSITION_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
66 { RSModifierType::POSITION_Z_APPLICABLE_CAMERA3D, RSPropertyDrawableSlot::BOUNDS_MATRIX },
67 { RSModifierType::PIVOT, RSPropertyDrawableSlot::BOUNDS_MATRIX },
68 { RSModifierType::PIVOT_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
69 { RSModifierType::QUATERNION, RSPropertyDrawableSlot::BOUNDS_MATRIX },
70 { RSModifierType::ROTATION, RSPropertyDrawableSlot::BOUNDS_MATRIX },
71 { RSModifierType::ROTATION_X, RSPropertyDrawableSlot::BOUNDS_MATRIX },
72 { RSModifierType::ROTATION_Y, RSPropertyDrawableSlot::BOUNDS_MATRIX },
73 { RSModifierType::CAMERA_DISTANCE, RSPropertyDrawableSlot::BOUNDS_MATRIX },
74 { RSModifierType::SCALE, RSPropertyDrawableSlot::BOUNDS_MATRIX },
75 { RSModifierType::SCALE_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
76 { RSModifierType::SKEW, RSPropertyDrawableSlot::BOUNDS_MATRIX },
77 { RSModifierType::PERSP, RSPropertyDrawableSlot::BOUNDS_MATRIX },
78 { RSModifierType::TRANSLATE, RSPropertyDrawableSlot::BOUNDS_MATRIX },
79 { RSModifierType::TRANSLATE_Z, RSPropertyDrawableSlot::BOUNDS_MATRIX },
80 { RSModifierType::SUBLAYER_TRANSFORM, RSPropertyDrawableSlot::INVALID },
81 { RSModifierType::CORNER_RADIUS, RSPropertyDrawableSlot::INVALID },
82 { RSModifierType::ALPHA, RSPropertyDrawableSlot::ALPHA },
83 { RSModifierType::ALPHA_OFFSCREEN, RSPropertyDrawableSlot::ALPHA },
84 { RSModifierType::FOREGROUND_COLOR, RSPropertyDrawableSlot::FOREGROUND_COLOR },
85 { RSModifierType::BACKGROUND_COLOR, RSPropertyDrawableSlot::BACKGROUND_COLOR },
86 { RSModifierType::BG_BRIGHTNESS_RATES, RSPropertyDrawableSlot::BACKGROUND_COLOR },
87 { RSModifierType::BG_BRIGHTNESS_SATURATION, RSPropertyDrawableSlot::BACKGROUND_COLOR },
88 { RSModifierType::BG_BRIGHTNESS_POSCOEFF, RSPropertyDrawableSlot::BACKGROUND_COLOR },
89 { RSModifierType::BG_BRIGHTNESS_NEGCOEFF, RSPropertyDrawableSlot::BACKGROUND_COLOR },
90 { RSModifierType::BG_BRIGHTNESS_FRACTION, RSPropertyDrawableSlot::BACKGROUND_COLOR },
91 { RSModifierType::BACKGROUND_SHADER, RSPropertyDrawableSlot::BACKGROUND_SHADER },
92 { RSModifierType::BG_IMAGE, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
93 { RSModifierType::BG_IMAGE_WIDTH, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
94 { RSModifierType::BG_IMAGE_HEIGHT, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
95 { RSModifierType::BG_IMAGE_POSITION_X, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
96 { RSModifierType::BG_IMAGE_POSITION_Y, RSPropertyDrawableSlot::BACKGROUND_IMAGE },
97 { RSModifierType::SURFACE_BG_COLOR, RSPropertyDrawableSlot::INVALID },
98 { RSModifierType::BORDER_COLOR, RSPropertyDrawableSlot::BORDER },
99 { RSModifierType::BORDER_WIDTH, RSPropertyDrawableSlot::BORDER },
100 { RSModifierType::BORDER_STYLE, RSPropertyDrawableSlot::BORDER },
101 { RSModifierType::BORDER_DASH_WIDTH, RSPropertyDrawableSlot::BORDER },
102 { RSModifierType::BORDER_DASH_GAP, RSPropertyDrawableSlot::BORDER },
103 { RSModifierType::FILTER, RSPropertyDrawableSlot::COMPOSITING_FILTER },
104 { RSModifierType::BACKGROUND_FILTER, RSPropertyDrawableSlot::BACKGROUND_FILTER },
105 { RSModifierType::LINEAR_GRADIENT_BLUR_PARA, RSPropertyDrawableSlot::COMPOSITING_FILTER },
106 { RSModifierType::FOREGROUND_EFFECT_RADIUS, RSPropertyDrawableSlot::FOREGROUND_FILTER },
107 { RSModifierType::MOTION_BLUR_PARA, RSPropertyDrawableSlot::FOREGROUND_FILTER },
108 { RSModifierType::FLY_OUT_DEGREE, RSPropertyDrawableSlot::FOREGROUND_FILTER },
109 { RSModifierType::FLY_OUT_PARAMS, RSPropertyDrawableSlot::FOREGROUND_FILTER },
110 { RSModifierType::DISTORTION_K, RSPropertyDrawableSlot::FOREGROUND_FILTER },
111 { RSModifierType::MAGNIFIER_PARA, RSPropertyDrawableSlot::BACKGROUND_FILTER },
112 { RSModifierType::DYNAMIC_LIGHT_UP_RATE, RSPropertyDrawableSlot::DYNAMIC_LIGHT_UP },
113 { RSModifierType::DYNAMIC_LIGHT_UP_DEGREE, RSPropertyDrawableSlot::DYNAMIC_LIGHT_UP },
114 { RSModifierType::FRAME_GRAVITY, RSPropertyDrawableSlot::FRAME_OFFSET },
115 { RSModifierType::CLIP_RRECT, RSPropertyDrawableSlot::CLIP_TO_BOUNDS },
116 { RSModifierType::CLIP_BOUNDS, RSPropertyDrawableSlot::CLIP_TO_BOUNDS },
117 { RSModifierType::CLIP_TO_BOUNDS, RSPropertyDrawableSlot::CLIP_TO_BOUNDS },
118 { RSModifierType::CLIP_TO_FRAME, RSPropertyDrawableSlot::CLIP_TO_FRAME },
119 { RSModifierType::VISIBLE, RSPropertyDrawableSlot::INVALID },
120 { RSModifierType::SHADOW_COLOR, RSPropertyDrawableSlot::SHADOW },
121 { RSModifierType::SHADOW_OFFSET_X, RSPropertyDrawableSlot::SHADOW },
122 { RSModifierType::SHADOW_OFFSET_Y, RSPropertyDrawableSlot::SHADOW },
123 { RSModifierType::SHADOW_ALPHA, RSPropertyDrawableSlot::SHADOW },
124 { RSModifierType::SHADOW_ELEVATION, RSPropertyDrawableSlot::SHADOW },
125 { RSModifierType::SHADOW_RADIUS, RSPropertyDrawableSlot::SHADOW },
126 { RSModifierType::SHADOW_PATH, RSPropertyDrawableSlot::SHADOW },
127 { RSModifierType::SHADOW_MASK, RSPropertyDrawableSlot::SHADOW },
128 { RSModifierType::MASK, RSPropertyDrawableSlot::MASK },
129 { RSModifierType::SPHERIZE, RSPropertyDrawableSlot::INVALID },
130 { RSModifierType::LIGHT_UP_EFFECT, RSPropertyDrawableSlot::LIGHT_UP_EFFECT },
131 { RSModifierType::AIINVERT, RSPropertyDrawableSlot::BINARIZATION },
132 { RSModifierType::SYSTEMBAREFFECT, RSPropertyDrawableSlot::BACKGROUND_FILTER },
133 { RSModifierType::WATER_RIPPLE_PROGRESS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
134 { RSModifierType::WATER_RIPPLE_PARAMS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
135 { RSModifierType::PIXEL_STRETCH, RSPropertyDrawableSlot::PIXEL_STRETCH },
136 { RSModifierType::PIXEL_STRETCH_PERCENT, RSPropertyDrawableSlot::PIXEL_STRETCH },
137 { RSModifierType::PIXEL_STRETCH_TILE_MODE, RSPropertyDrawableSlot::PIXEL_STRETCH },
138 { RSModifierType::USE_EFFECT, RSPropertyDrawableSlot::USE_EFFECT },
139 { RSModifierType::SANDBOX, RSPropertyDrawableSlot::BOUNDS_MATRIX },
140 { RSModifierType::GRAY_SCALE, RSPropertyDrawableSlot::COLOR_FILTER },
141 { RSModifierType::BRIGHTNESS, RSPropertyDrawableSlot::COLOR_FILTER },
142 { RSModifierType::CONTRAST, RSPropertyDrawableSlot::COLOR_FILTER },
143 { RSModifierType::SATURATE, RSPropertyDrawableSlot::COLOR_FILTER },
144 { RSModifierType::SEPIA, RSPropertyDrawableSlot::COLOR_FILTER },
145 { RSModifierType::INVERT, RSPropertyDrawableSlot::COLOR_FILTER },
146 { RSModifierType::HUE_ROTATE, RSPropertyDrawableSlot::COLOR_FILTER },
147 { RSModifierType::COLOR_BLEND, RSPropertyDrawableSlot::COLOR_FILTER },
148 { RSModifierType::PARTICLE, RSPropertyDrawableSlot::PARTICLE_EFFECT },
149 { RSModifierType::SHADOW_IS_FILLED, RSPropertyDrawableSlot::INVALID },
150 { RSModifierType::OUTLINE_COLOR, RSPropertyDrawableSlot::OUTLINE },
151 { RSModifierType::OUTLINE_WIDTH, RSPropertyDrawableSlot::OUTLINE },
152 { RSModifierType::OUTLINE_STYLE, RSPropertyDrawableSlot::OUTLINE },
153 { RSModifierType::OUTLINE_DASH_WIDTH, RSPropertyDrawableSlot::OUTLINE },
154 { RSModifierType::OUTLINE_DASH_GAP, RSPropertyDrawableSlot::OUTLINE },
155 { RSModifierType::OUTLINE_RADIUS, RSPropertyDrawableSlot::OUTLINE },
156 { RSModifierType::USE_SHADOW_BATCHING, RSPropertyDrawableSlot::INVALID },
157 { RSModifierType::FG_BRIGHTNESS_RATES, RSPropertyDrawableSlot::BLEND_MODE },
158 { RSModifierType::FG_BRIGHTNESS_SATURATION, RSPropertyDrawableSlot::BLEND_MODE },
159 { RSModifierType::FG_BRIGHTNESS_POSCOEFF, RSPropertyDrawableSlot::BLEND_MODE },
160 { RSModifierType::FG_BRIGHTNESS_NEGCOEFF, RSPropertyDrawableSlot::BLEND_MODE },
161 { RSModifierType::FG_BRIGHTNESS_FRACTION, RSPropertyDrawableSlot::BLEND_MODE },
162 { RSModifierType::COLOR_BLEND_MODE, RSPropertyDrawableSlot::BLEND_MODE },
163 { RSModifierType::COLOR_BLEND_APPLY_TYPE, RSPropertyDrawableSlot::BLEND_MODE },
164 { RSModifierType::LIGHT_INTENSITY, RSPropertyDrawableSlot::POINT_LIGHT },
165 { RSModifierType::LIGHT_COLOR, RSPropertyDrawableSlot::POINT_LIGHT },
166 { RSModifierType::LIGHT_POSITION, RSPropertyDrawableSlot::POINT_LIGHT },
167 { RSModifierType::ILLUMINATED_TYPE, RSPropertyDrawableSlot::POINT_LIGHT },
168 { RSModifierType::BLOOM, RSPropertyDrawableSlot::POINT_LIGHT },
169 { RSModifierType::BACKGROUND_BLUR_RADIUS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
170 { RSModifierType::BACKGROUND_BLUR_SATURATION, RSPropertyDrawableSlot::BACKGROUND_FILTER },
171 { RSModifierType::BACKGROUND_BLUR_BRIGHTNESS, RSPropertyDrawableSlot::BACKGROUND_FILTER },
172 { RSModifierType::BACKGROUND_BLUR_MASK_COLOR, RSPropertyDrawableSlot::BACKGROUND_FILTER },
173 { RSModifierType::BACKGROUND_BLUR_COLOR_MODE, RSPropertyDrawableSlot::BACKGROUND_FILTER },
174 { RSModifierType::BACKGROUND_BLUR_RADIUS_X, RSPropertyDrawableSlot::BACKGROUND_FILTER },
175 { RSModifierType::BACKGROUND_BLUR_RADIUS_Y, RSPropertyDrawableSlot::BACKGROUND_FILTER },
176 { RSModifierType::FOREGROUND_BLUR_RADIUS, RSPropertyDrawableSlot::COMPOSITING_FILTER },
177 { RSModifierType::FOREGROUND_BLUR_SATURATION, RSPropertyDrawableSlot::COMPOSITING_FILTER },
178 { RSModifierType::FOREGROUND_BLUR_BRIGHTNESS, RSPropertyDrawableSlot::COMPOSITING_FILTER },
179 { RSModifierType::FOREGROUND_BLUR_MASK_COLOR, RSPropertyDrawableSlot::COMPOSITING_FILTER },
180 { RSModifierType::FOREGROUND_BLUR_COLOR_MODE, RSPropertyDrawableSlot::COMPOSITING_FILTER },
181 { RSModifierType::FOREGROUND_BLUR_RADIUS_X, RSPropertyDrawableSlot::COMPOSITING_FILTER },
182 { RSModifierType::FOREGROUND_BLUR_RADIUS_Y, RSPropertyDrawableSlot::COMPOSITING_FILTER },
183 { RSModifierType::ATTRACTION_FRACTION, RSPropertyDrawableSlot::INVALID },
184 { RSModifierType::ATTRACTION_DSTPOINT, RSPropertyDrawableSlot::INVALID },
185 { RSModifierType::CUSTOM, RSPropertyDrawableSlot::INVALID },
186 { RSModifierType::EXTENDED, RSPropertyDrawableSlot::INVALID },
187 { RSModifierType::TRANSITION, RSPropertyDrawableSlot::TRANSITION },
188 { RSModifierType::BACKGROUND_STYLE, RSPropertyDrawableSlot::BACKGROUND_STYLE },
189 { RSModifierType::CONTENT_STYLE, RSPropertyDrawableSlot::CONTENT_STYLE },
190 { RSModifierType::FOREGROUND_STYLE, RSPropertyDrawableSlot::FOREGROUND_STYLE },
191 { RSModifierType::OVERLAY_STYLE, RSPropertyDrawableSlot::OVERLAY },
192 { RSModifierType::NODE_MODIFIER, RSPropertyDrawableSlot::INVALID },
193 { RSModifierType::ENV_FOREGROUND_COLOR, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR },
194 { RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY, RSPropertyDrawableSlot::ENV_FOREGROUND_COLOR_STRATEGY },
195 { RSModifierType::CUSTOM_CLIP_TO_FRAME, RSPropertyDrawableSlot::CUSTOM_CLIP_TO_FRAME },
196 { RSModifierType::HDR_BRIGHTNESS, RSPropertyDrawableSlot::INVALID },
197 { RSModifierType::PARTICLE_EMITTER_UPDATER, RSPropertyDrawableSlot::PARTICLE_EFFECT },
198 { RSModifierType::PARTICLE_NOISE_FIELD, RSPropertyDrawableSlot::PARTICLE_EFFECT },
199 { RSModifierType::DYNAMIC_DIM_DEGREE, RSPropertyDrawableSlot::DYNAMIC_DIM },
200 { RSModifierType::GEOMETRYTRANS, RSPropertyDrawableSlot::INVALID },
201 };
202
203 // NOTE: This LUT should always the same size as RSPropertyDrawableSlot
204 // index = RSPropertyDrawableType, value = DrawableGenerator
205 constexpr int LUT_SIZE = static_cast<int>(RSPropertyDrawableSlot::MAX);
206 static const std::array<RSPropertyDrawable::DrawableGenerator, LUT_SIZE> g_drawableGeneratorLut = {
207 nullptr, // INVALID = 0
208 nullptr, // SAVE_ALL
209
210 // Bounds Geometry
211 nullptr, // BOUNDS_MATRIX
212 RSAlphaDrawable::Generate, // ALPHA
213 RSMaskDrawable::Generate, // MASK
214 CustomModifierAdapter<RSModifierType::TRANSITION>, // TRANSITION
215 CustomModifierAdapter<RSModifierType::ENV_FOREGROUND_COLOR>, // ENV_FOREGROUND_COLOR
216 RSShadowDrawable::Generate, // SHADOW
217 RSForegroundFilterDrawable::Generate, // FOREGROUND_FILTER
218 RSOutlineDrawable::Generate, // OUTLINE
219
220 // BG properties in Bounds Clip
221 nullptr, // BG_SAVE_BOUNDS
222 nullptr, // CLIP_TO_BOUNDS
223 BlendSaveDrawableGenerate, // BLEND_MODE
224 RSBackgroundColorDrawable::Generate, // BACKGROUND_COLOR
225 RSBackgroundShaderDrawable::Generate, // BACKGROUND_SHADER
226 RSBackgroundImageDrawable::Generate, // BACKGROUND_IMAGE
227 RSBackgroundFilterDrawable::Generate, // BACKGROUND_FILTER
228 RSEffectDataApplyDrawable::Generate, // USE_EFFECT
229 CustomModifierAdapter<RSModifierType::BACKGROUND_STYLE>, // BACKGROUND_STYLE
230 RSDynamicLightUpDrawable::Generate, // DYNAMIC_LIGHT_UP
231 CustomModifierAdapter<RSModifierType::ENV_FOREGROUND_COLOR_STRATEGY>, // ENV_FOREGROUND_COLOR_STRATEGY
232 nullptr, // BG_RESTORE_BOUNDS
233
234 // Frame Geometry
235 nullptr, // SAVE_FRAME
236 nullptr, // FRAME_OFFSET
237 RSClipFrameDrawable::Generate, // CLIP_TO_FRAME
238 CustomModifierAdapter<RSModifierType::CUSTOM_CLIP_TO_FRAME>, // CUSTOM_CLIP_TO_FRAME
239 CustomModifierAdapter<RSModifierType::CONTENT_STYLE>, // CONTENT_STYLE
240 nullptr, // CHILDREN
241 CustomModifierAdapter<RSModifierType::FOREGROUND_STYLE>, // FOREGROUND_STYLE
242 nullptr, // RESTORE_FRAME
243
244 // FG properties in Bounds clip
245 nullptr, // FG_SAVE_BOUNDS
246 nullptr, // EXTRA_CLIP_TO_BOUNDS
247 RSBinarizationDrawable::Generate, // BINARIZATION,
248 RSColorFilterDrawable::Generate, // COLOR_FILTER
249 RSDynamicDimDrawable::Generate, // DYNAMIC_DIM
250 RSLightUpEffectDrawable::Generate, // LIGHT_UP_EFFECT
251 RSCompositingFilterDrawable::Generate, // COMPOSITING_FILTER
252 RSForegroundColorDrawable::Generate, // FOREGROUND_COLOR
253 nullptr, // FG_RESTORE_BOUNDS
254
255 // No clip (unless ClipToBounds is set)
256 RSPointLightDrawable::Generate, // POINT_LIGHT
257 RSBorderDrawable::Generate, // BORDER
258 CustomModifierAdapter<RSModifierType::OVERLAY_STYLE>, // OVERLAY
259 RSParticleDrawable::Generate, // PARTICLE_EFFECT
260 RSPixelStretchDrawable::Generate, // PIXEL_STRETCH
261
262 BlendRestoreDrawableGenerate, // RESTORE_BLEND
263 RSForegroundFilterRestoreDrawable::Generate, // RESTORE_FOREGROUND_FILTER
264 nullptr, // RESTORE_ALL
265 };
266
267 enum DrawableVecStatus : uint8_t {
268 CLIP_TO_BOUNDS = 1 << 0,
269 BG_BOUNDS_PROPERTY = 1 << 1,
270 FG_BOUNDS_PROPERTY = 1 << 2,
271 CLIP_TO_FRAME = 1 << 3,
272 FRAME_PROPERTY = 1 << 4,
273 HAS_CHILDREN = 1 << 5,
274 BOUNDS_MASK = CLIP_TO_BOUNDS | BG_BOUNDS_PROPERTY | FG_BOUNDS_PROPERTY,
275 FRAME_MASK = CLIP_TO_FRAME | FRAME_PROPERTY | HAS_CHILDREN,
276 };
277 } // namespace
278
GenerateDirtySlots(const RSProperties & properties,const ModifierDirtyTypes & dirtyTypes)279 std::unordered_set<RSPropertyDrawableSlot> RSPropertyDrawable::GenerateDirtySlots(
280 const RSProperties& properties, const ModifierDirtyTypes& dirtyTypes)
281 {
282 // Step 1.1: collect dirty slots
283 std::unordered_set<RSPropertyDrawableSlot> dirtySlots;
284 for (uint8_t type = 0; type < static_cast<size_t>(RSModifierType::MAX_RS_MODIFIER_TYPE); type++) {
285 if (dirtyTypes[type]) {
286 auto it = g_propertyToDrawableLut.find(static_cast<RSModifierType>(type));
287 if (it == g_propertyToDrawableLut.end() || it->second == RSPropertyDrawableSlot::INVALID) {
288 continue;
289 }
290 dirtySlots.emplace(it->second);
291 }
292 }
293
294 // Step 1.2: expand dirty slots if needed
295 if (dirtyTypes.test(static_cast<size_t>(RSModifierType::BOUNDS))) {
296 if (properties.GetPixelStretch().has_value()) {
297 dirtySlots.emplace(RSPropertyDrawableSlot::PIXEL_STRETCH);
298 }
299 if (properties.GetBorder() != nullptr) {
300 dirtySlots.emplace(RSPropertyDrawableSlot::BORDER);
301 }
302 if (properties.GetOutline() != nullptr) {
303 dirtySlots.emplace(RSPropertyDrawableSlot::OUTLINE);
304 }
305 // PLANNING: add other slots: ClipToFrame, ColorFilter
306 }
307 if (dirtyTypes.test(static_cast<size_t>(RSModifierType::CORNER_RADIUS))) {
308 // border may should be updated with corner radius
309 if (properties.GetBorder() != nullptr) {
310 dirtySlots.emplace(RSPropertyDrawableSlot::BORDER);
311 }
312
313 if (properties.GetOutline() != nullptr) {
314 dirtySlots.emplace(RSPropertyDrawableSlot::OUTLINE);
315 }
316 }
317 if (dirtySlots.count(RSPropertyDrawableSlot::BLEND_MODE)) {
318 // BlendMode Restore should be regenerated with BlendMode
319 dirtySlots.emplace(RSPropertyDrawableSlot::RESTORE_BLEND_MODE);
320 }
321 if (dirtySlots.count(RSPropertyDrawableSlot::FOREGROUND_FILTER)) {
322 // ForegroundFilter Restore should be regenerated with ForegroundFilter
323 dirtySlots.emplace(RSPropertyDrawableSlot::RESTORE_FOREGROUND_FILTER);
324 }
325
326 return dirtySlots;
327 }
328
UpdateDrawableVec(const RSRenderContent & content,DrawableVec & drawableVec,std::unordered_set<RSPropertyDrawableSlot> & dirtySlots)329 bool RSPropertyDrawable::UpdateDrawableVec(
330 const RSRenderContent& content, DrawableVec& drawableVec, std::unordered_set<RSPropertyDrawableSlot>& dirtySlots)
331 {
332 if (dirtySlots.empty()) {
333 return false;
334 }
335 // ====================================================================
336 // Step 2.1: re-generate drawables for all dirty slots
337 auto drawableSlotChanged = false;
338 for (const auto& slot : dirtySlots) {
339 auto& origDrawable = drawableVec[static_cast<size_t>(slot)];
340 if (origDrawable != nullptr && origDrawable->Update(content)) {
341 continue;
342 }
343 auto& generator = g_drawableGeneratorLut[static_cast<int>(slot)];
344 if (!generator) {
345 continue;
346 }
347 auto drawable = generator(content);
348 if (bool(origDrawable) != bool(drawable)) {
349 // drawable slot changed (nullptr to non-nullptr or vice versa)
350 drawableSlotChanged = true;
351 }
352 origDrawable = std::move(drawable);
353 }
354
355 // Step 2.2: post-generate hooks (PLANNING: refactor this into a separate function)
356
357 // Temporary fix, change of clipToBounds should trigger UpdateSaveRestore
358 if (!drawableSlotChanged && dirtySlots.count(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)) {
359 drawableSlotChanged = true;
360 }
361
362 return drawableSlotChanged;
363 }
364
365 namespace {
HasPropertyDrawableInRange(const RSPropertyDrawable::DrawableVec & drawableVec,RSPropertyDrawableSlot begin,RSPropertyDrawableSlot end)366 inline bool HasPropertyDrawableInRange(
367 const RSPropertyDrawable::DrawableVec& drawableVec, RSPropertyDrawableSlot begin, RSPropertyDrawableSlot end)
368 {
369 return std::any_of(drawableVec.begin() + static_cast<size_t>(begin), drawableVec.begin() + static_cast<size_t>(end),
370 [](const auto& drawablePtr) { return drawablePtr != nullptr; });
371 }
372
CalculateDrawableVecStatus(RSRenderContent & content,const RSPropertyDrawable::DrawableVec & drawableVec)373 uint8_t CalculateDrawableVecStatus(RSRenderContent& content, const RSPropertyDrawable::DrawableVec& drawableVec)
374 {
375 uint8_t result = 0;
376 auto& properties = content.GetRenderProperties();
377
378 // color blend mode has implicit dependency on clipToBounds
379 if (properties.GetClipToBounds() || properties.GetClipToRRect() || properties.GetClipBounds() != nullptr ||
380 properties.GetColorBlendMode()) {
381 result |= DrawableVecStatus::CLIP_TO_BOUNDS;
382 }
383 if (properties.GetClipToFrame()) {
384 result |= DrawableVecStatus::CLIP_TO_FRAME;
385 }
386
387 if (HasPropertyDrawableInRange(
388 drawableVec, RSPropertyDrawableSlot::BG_PROPERTIES_BEGIN, RSPropertyDrawableSlot::BG_PROPERTIES_END)) {
389 result |= DrawableVecStatus::BG_BOUNDS_PROPERTY;
390 }
391 if (HasPropertyDrawableInRange(
392 drawableVec, RSPropertyDrawableSlot::FG_PROPERTIES_BEGIN, RSPropertyDrawableSlot::FG_PROPERTIES_END)) {
393 result |= DrawableVecStatus::FG_BOUNDS_PROPERTY;
394 }
395 if (HasPropertyDrawableInRange(drawableVec, RSPropertyDrawableSlot::CONTENT_PROPERTIES_BEGIN,
396 RSPropertyDrawableSlot::CONTENT_PROPERTIES_END)) {
397 result |= DrawableVecStatus::FRAME_PROPERTY;
398 }
399
400 return result;
401 }
402
403 constexpr std::array boundsSlotsToErase = {
404 RSPropertyDrawableSlot::BG_SAVE_BOUNDS,
405 RSPropertyDrawableSlot::CLIP_TO_BOUNDS,
406 RSPropertyDrawableSlot::BG_RESTORE_BOUNDS,
407 RSPropertyDrawableSlot::FG_SAVE_BOUNDS,
408 RSPropertyDrawableSlot::FG_CLIP_TO_BOUNDS,
409 RSPropertyDrawableSlot::FG_RESTORE_BOUNDS,
410 };
411
412 constexpr std::array frameSlotsToErase = {
413 RSPropertyDrawableSlot::SAVE_FRAME,
414 RSPropertyDrawableSlot::RESTORE_FRAME,
415 };
416
OptimizeBoundsSaveRestore(RSRenderContent & content,RSPropertyDrawable::DrawableVec & drawableVec,uint8_t flags)417 void OptimizeBoundsSaveRestore(RSRenderContent& content, RSPropertyDrawable::DrawableVec& drawableVec, uint8_t flags)
418 {
419 // Erase existing save/clip/restore before re-generating
420 for (auto& slot : boundsSlotsToErase) {
421 drawableVec[static_cast<size_t>(slot)] = nullptr;
422 }
423
424 if (flags & DrawableVecStatus::CLIP_TO_BOUNDS) {
425 // case 1: ClipToBounds set.
426 // add one clip, and reuse SAVE_ALL and RESTORE_ALL.
427 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)] =
428 RSClipBoundsDrawable::Generate(content);
429 return;
430 }
431
432 if ((flags & DrawableVecStatus::BG_BOUNDS_PROPERTY) && (flags & DrawableVecStatus::FG_BOUNDS_PROPERTY)) {
433 // case 2: ClipToBounds not set and we have bounds properties both BG and FG.
434 // add two sets of save/clip/restore before & after content.
435
436 // part 1: before children
437 SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::BG_SAVE_BOUNDS,
438 RSPropertyDrawableSlot::BG_RESTORE_BOUNDS, RSPaintFilterCanvas::kCanvas);
439 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)] =
440 RSClipBoundsDrawable::Generate(content);
441
442 // part 2: after children, add aliases
443 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_SAVE_BOUNDS)] =
444 GenerateAlias(RSPropertyDrawableSlot::BG_SAVE_BOUNDS);
445 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_CLIP_TO_BOUNDS)] =
446 GenerateAlias(RSPropertyDrawableSlot::CLIP_TO_BOUNDS);
447 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_RESTORE_BOUNDS)] =
448 GenerateAlias(RSPropertyDrawableSlot::BG_RESTORE_BOUNDS);
449 return;
450 }
451
452 if (flags & DrawableVecStatus::BG_BOUNDS_PROPERTY) {
453 // case 3: ClipToBounds not set and we have background bounds properties.
454 SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::BG_SAVE_BOUNDS,
455 RSPropertyDrawableSlot::BG_RESTORE_BOUNDS, RSPaintFilterCanvas::kCanvas);
456
457 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::CLIP_TO_BOUNDS)] =
458 RSClipBoundsDrawable::Generate(content);
459 return;
460 }
461
462 if (flags & DrawableVecStatus::FG_BOUNDS_PROPERTY) {
463 // case 4: ClipToBounds not set and we have foreground bounds properties.
464 SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::FG_SAVE_BOUNDS,
465 RSPropertyDrawableSlot::FG_RESTORE_BOUNDS, RSPaintFilterCanvas::kCanvas);
466
467 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FG_CLIP_TO_BOUNDS)] =
468 RSClipBoundsDrawable::Generate(content);
469 return;
470 }
471 // case 5: ClipToBounds not set and no bounds properties, no need to save/clip/restore.
472 // nothing to do
473 }
474
OptimizeFrameSaveRestore(RSRenderContent & content,RSPropertyDrawable::DrawableVec & drawableVec,uint8_t flags)475 void OptimizeFrameSaveRestore(RSRenderContent& content, RSPropertyDrawable::DrawableVec& drawableVec, uint8_t flags)
476 {
477 // Erase existing save/clip/restore before re-generating
478 for (auto& slot : frameSlotsToErase) {
479 drawableVec[static_cast<size_t>(slot)] = nullptr;
480 }
481
482 // PLANNING: if both clipToFrame and clipToBounds are set, and frame == bounds, we don't need an extra clip
483 if (flags & DrawableVecStatus::FRAME_PROPERTY) {
484 // save/restore
485 SaveRestoreHelper(drawableVec, RSPropertyDrawableSlot::SAVE_FRAME,
486 RSPropertyDrawableSlot::RESTORE_FRAME, RSPaintFilterCanvas::kCanvas);
487 } else {
488 // no need to save/clip/restore
489 }
490 }
491 } // namespace
492
InitializeSaveRestore(const RSRenderContent & content,DrawableVec & drawableVec)493 void RSPropertyDrawable::InitializeSaveRestore(const RSRenderContent& content, DrawableVec& drawableVec)
494 {
495 SaveRestoreHelper(
496 drawableVec, RSPropertyDrawableSlot::SAVE_ALL, RSPropertyDrawableSlot::RESTORE_ALL, RSPaintFilterCanvas::kAll);
497 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::BOUNDS_MATRIX)] =
498 RSBoundsGeometryDrawable::Generate(content);
499 drawableVec[static_cast<size_t>(RSPropertyDrawableSlot::FRAME_OFFSET)] = RSFrameGeometryDrawable::Generate(content);
500 }
501
UpdateSaveRestore(RSRenderContent & content,DrawableVec & drawableVec,uint8_t & drawableVecStatus)502 void RSPropertyDrawable::UpdateSaveRestore(
503 RSRenderContent& content, DrawableVec& drawableVec, uint8_t& drawableVecStatus)
504 {
505 // ====================================================================
506 // Step 3: Universal save/clip/restore optimization
507
508 // calculate new drawable map status
509 auto drawableVecStatusNew = CalculateDrawableVecStatus(content, drawableVec);
510
511 // calculate changed bits
512 uint8_t changedBits = drawableVecStatus ^ drawableVecStatusNew;
513 if (changedBits & BOUNDS_MASK) {
514 // update bounds save/clip if need
515 OptimizeBoundsSaveRestore(content, drawableVec, drawableVecStatusNew);
516 }
517 if (changedBits & FRAME_MASK) {
518 // update frame save/clip if need
519 OptimizeFrameSaveRestore(content, drawableVec, drawableVecStatusNew);
520 }
521 drawableVecStatus = drawableVecStatusNew;
522 }
523
524 } // namespace OHOS::Rosen
525