1 /*
2 * Copyright (c) 2025 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 "modifier_ng/rs_modifier_ng.h"
17
18 #include "sandbox_utils.h"
19
20 #include "command/rs_node_command.h"
21 #include "modifier/rs_property.h"
22 #include "modifier_ng/rs_render_modifier_ng.h"
23 #include "platform/common/rs_log.h"
24 #include "ui/rs_node.h"
25
26 namespace OHOS::Rosen::ModifierNG {
27 constexpr int PID_SHIFT = 32;
28
29 static const std::unordered_map<RSPropertyType, ThresholdType> g_propertyTypeToThresholdTypeMap = {
30 { RSPropertyType::INVALID, ThresholdType::DEFAULT },
31 { RSPropertyType::BOUNDS, ThresholdType::LAYOUT },
32 { RSPropertyType::FRAME, ThresholdType::LAYOUT },
33 { RSPropertyType::POSITION_Z, ThresholdType::LAYOUT },
34 { RSPropertyType::POSITION_Z_APPLICABLE_CAMERA3D, ThresholdType::ZERO },
35 { RSPropertyType::PIVOT, ThresholdType::FINE },
36 { RSPropertyType::PIVOT_Z, ThresholdType::FINE },
37 { RSPropertyType::QUATERNION, ThresholdType::FINE },
38 { RSPropertyType::ROTATION, ThresholdType::FINE },
39 { RSPropertyType::ROTATION_X, ThresholdType::FINE },
40 { RSPropertyType::ROTATION_Y, ThresholdType::FINE },
41 { RSPropertyType::CAMERA_DISTANCE, ThresholdType::COARSE },
42 { RSPropertyType::SCALE, ThresholdType::FINE },
43 { RSPropertyType::SCALE_Z, ThresholdType::FINE },
44 { RSPropertyType::SKEW, ThresholdType::FINE },
45 { RSPropertyType::PERSP, ThresholdType::FINE },
46 { RSPropertyType::TRANSLATE, ThresholdType::LAYOUT },
47 { RSPropertyType::TRANSLATE_Z, ThresholdType::LAYOUT },
48 { RSPropertyType::SUBLAYER_TRANSFORM, ThresholdType::DEFAULT },
49 { RSPropertyType::CORNER_RADIUS, ThresholdType::MEDIUM },
50 { RSPropertyType::ALPHA, ThresholdType::COARSE },
51 { RSPropertyType::ALPHA_OFFSCREEN, ThresholdType::ZERO },
52 { RSPropertyType::FOREGROUND_COLOR, ThresholdType::COLOR },
53 { RSPropertyType::BACKGROUND_COLOR, ThresholdType::COLOR },
54 { RSPropertyType::BACKGROUND_SHADER, ThresholdType::ZERO },
55 { RSPropertyType::BACKGROUND_SHADER_PROGRESS, ThresholdType::FINE },
56 { RSPropertyType::BG_IMAGE, ThresholdType::ZERO },
57 { RSPropertyType::BG_IMAGE_INNER_RECT, ThresholdType::LAYOUT },
58 { RSPropertyType::BG_IMAGE_WIDTH, ThresholdType::LAYOUT },
59 { RSPropertyType::BG_IMAGE_HEIGHT, ThresholdType::LAYOUT },
60 { RSPropertyType::BG_IMAGE_POSITION_X, ThresholdType::LAYOUT },
61 { RSPropertyType::BG_IMAGE_POSITION_Y, ThresholdType::LAYOUT },
62 { RSPropertyType::BG_IMAGE_RECT, ThresholdType::DEFAULT },
63 { RSPropertyType::BORDER_COLOR, ThresholdType::COLOR },
64 { RSPropertyType::BORDER_WIDTH, ThresholdType::LAYOUT },
65 { RSPropertyType::BORDER_STYLE, ThresholdType::ZERO },
66 { RSPropertyType::BORDER_DASH_WIDTH, ThresholdType::ZERO },
67 { RSPropertyType::BORDER_DASH_GAP, ThresholdType::ZERO },
68 { RSPropertyType::BACKGROUND_FILTER, ThresholdType::DEFAULT },
69 { RSPropertyType::LINEAR_GRADIENT_BLUR_PARA, ThresholdType::ZERO },
70 { RSPropertyType::DYNAMIC_LIGHT_UP_RATE, ThresholdType::COARSE },
71 { RSPropertyType::DYNAMIC_LIGHT_UP_DEGREE, ThresholdType::COARSE },
72 { RSPropertyType::FG_BRIGHTNESS_RATES, ThresholdType::COARSE },
73 { RSPropertyType::FG_BRIGHTNESS_SATURATION, ThresholdType::COARSE },
74 { RSPropertyType::FG_BRIGHTNESS_POSCOEFF, ThresholdType::COARSE },
75 { RSPropertyType::FG_BRIGHTNESS_NEGCOEFF, ThresholdType::COARSE },
76 { RSPropertyType::FG_BRIGHTNESS_FRACTION, ThresholdType::COARSE },
77 { RSPropertyType::FG_BRIGHTNESS_HDR, ThresholdType::ZERO },
78 { RSPropertyType::BG_BRIGHTNESS_RATES, ThresholdType::COARSE },
79 { RSPropertyType::BG_BRIGHTNESS_SATURATION, ThresholdType::COARSE },
80 { RSPropertyType::BG_BRIGHTNESS_POSCOEFF, ThresholdType::COARSE },
81 { RSPropertyType::BG_BRIGHTNESS_NEGCOEFF, ThresholdType::COARSE },
82 { RSPropertyType::BG_BRIGHTNESS_FRACTION, ThresholdType::COARSE },
83 { RSPropertyType::FRAME_GRAVITY, ThresholdType::ZERO },
84 { RSPropertyType::CLIP_RRECT, ThresholdType::MEDIUM },
85 { RSPropertyType::CLIP_BOUNDS, ThresholdType::ZERO },
86 { RSPropertyType::CLIP_TO_BOUNDS, ThresholdType::ZERO },
87 { RSPropertyType::CLIP_TO_FRAME, ThresholdType::ZERO },
88 { RSPropertyType::VISIBLE, ThresholdType::ZERO },
89 { RSPropertyType::SHADOW_COLOR, ThresholdType::COLOR },
90 { RSPropertyType::SHADOW_OFFSET_X, ThresholdType::LAYOUT },
91 { RSPropertyType::SHADOW_OFFSET_Y, ThresholdType::LAYOUT },
92 { RSPropertyType::SHADOW_ALPHA, ThresholdType::COARSE },
93 { RSPropertyType::SHADOW_ELEVATION, ThresholdType::COARSE },
94 { RSPropertyType::SHADOW_RADIUS, ThresholdType::LAYOUT },
95 { RSPropertyType::SHADOW_PATH, ThresholdType::ZERO },
96 { RSPropertyType::SHADOW_MASK, ThresholdType::ZERO },
97 { RSPropertyType::SHADOW_COLOR_STRATEGY, ThresholdType::ZERO },
98 { RSPropertyType::MASK, ThresholdType::ZERO },
99 { RSPropertyType::SPHERIZE, ThresholdType::MEDIUM },
100 { RSPropertyType::LIGHT_UP_EFFECT_DEGREE, ThresholdType::COARSE },
101 { RSPropertyType::PIXEL_STRETCH_SIZE, ThresholdType::COARSE },
102 { RSPropertyType::PIXEL_STRETCH_PERCENT, ThresholdType::FINE },
103 { RSPropertyType::PIXEL_STRETCH_TILE_MODE, ThresholdType::ZERO },
104 { RSPropertyType::USE_EFFECT, ThresholdType::ZERO },
105 { RSPropertyType::USE_EFFECT_TYPE, ThresholdType::ZERO },
106 { RSPropertyType::COLOR_BLEND_MODE, ThresholdType::ZERO },
107 { RSPropertyType::COLOR_BLEND_APPLY_TYPE, ThresholdType::ZERO },
108 { RSPropertyType::SANDBOX, ThresholdType::LAYOUT },
109 { RSPropertyType::GRAY_SCALE, ThresholdType::COARSE },
110 { RSPropertyType::BRIGHTNESS, ThresholdType::COARSE },
111 { RSPropertyType::CONTRAST, ThresholdType::COARSE },
112 { RSPropertyType::SATURATE, ThresholdType::COARSE },
113 { RSPropertyType::SEPIA, ThresholdType::COARSE },
114 { RSPropertyType::INVERT, ThresholdType::COARSE },
115 { RSPropertyType::AIINVERT, ThresholdType::COARSE },
116 { RSPropertyType::SYSTEMBAREFFECT, ThresholdType::ZERO },
117 { RSPropertyType::WATER_RIPPLE_PROGRESS, ThresholdType::COARSE },
118 { RSPropertyType::WATER_RIPPLE_PARAMS, ThresholdType::ZERO },
119 { RSPropertyType::HUE_ROTATE, ThresholdType::COARSE },
120 { RSPropertyType::COLOR_BLEND, ThresholdType::COLOR },
121 { RSPropertyType::PARTICLE, ThresholdType::ZERO },
122 { RSPropertyType::SHADOW_IS_FILLED, ThresholdType::ZERO },
123 { RSPropertyType::OUTLINE_COLOR, ThresholdType::COLOR },
124 { RSPropertyType::OUTLINE_WIDTH, ThresholdType::LAYOUT },
125 { RSPropertyType::OUTLINE_STYLE, ThresholdType::ZERO },
126 { RSPropertyType::OUTLINE_DASH_WIDTH, ThresholdType::ZERO },
127 { RSPropertyType::OUTLINE_DASH_GAP, ThresholdType::ZERO },
128 { RSPropertyType::OUTLINE_RADIUS, ThresholdType::MEDIUM },
129 { RSPropertyType::GREY_COEF, ThresholdType::COARSE },
130 { RSPropertyType::LIGHT_INTENSITY, ThresholdType::COARSE },
131 { RSPropertyType::LIGHT_COLOR, ThresholdType::COARSE },
132 { RSPropertyType::LIGHT_POSITION, ThresholdType::LAYOUT },
133 { RSPropertyType::ILLUMINATED_BORDER_WIDTH, ThresholdType::COARSE },
134 { RSPropertyType::ILLUMINATED_TYPE, ThresholdType::ZERO },
135 { RSPropertyType::BLOOM, ThresholdType::COARSE },
136 { RSPropertyType::FOREGROUND_EFFECT_RADIUS, ThresholdType::COARSE },
137 { RSPropertyType::USE_SHADOW_BATCHING, ThresholdType::ZERO },
138 { RSPropertyType::MOTION_BLUR_PARA, ThresholdType::ZERO },
139 { RSPropertyType::PARTICLE_EMITTER_UPDATER, ThresholdType::ZERO },
140 { RSPropertyType::PARTICLE_NOISE_FIELD, ThresholdType::ZERO },
141 { RSPropertyType::FLY_OUT_DEGREE, ThresholdType::COARSE },
142 { RSPropertyType::FLY_OUT_PARAMS, ThresholdType::ZERO },
143 { RSPropertyType::DISTORTION_K, ThresholdType::COARSE },
144 { RSPropertyType::DYNAMIC_DIM_DEGREE, ThresholdType::COARSE },
145 { RSPropertyType::MAGNIFIER_PARA, ThresholdType::ZERO },
146 { RSPropertyType::BACKGROUND_BLUR_RADIUS, ThresholdType::COARSE },
147 { RSPropertyType::BACKGROUND_BLUR_SATURATION, ThresholdType::COARSE },
148 { RSPropertyType::BACKGROUND_BLUR_BRIGHTNESS, ThresholdType::COARSE },
149 { RSPropertyType::BACKGROUND_BLUR_MASK_COLOR, ThresholdType::COLOR },
150 { RSPropertyType::BACKGROUND_BLUR_COLOR_MODE, ThresholdType::ZERO },
151 { RSPropertyType::BACKGROUND_BLUR_RADIUS_X, ThresholdType::COARSE },
152 { RSPropertyType::BACKGROUND_BLUR_RADIUS_Y, ThresholdType::COARSE },
153 { RSPropertyType::BG_BLUR_DISABLE_SYSTEM_ADAPTATION, ThresholdType::ZERO },
154 { RSPropertyType::ALWAYS_SNAPSHOT, ThresholdType::ZERO },
155 { RSPropertyType::FOREGROUND_BLUR_RADIUS, ThresholdType::COARSE },
156 { RSPropertyType::FOREGROUND_BLUR_SATURATION, ThresholdType::COARSE },
157 { RSPropertyType::FOREGROUND_BLUR_BRIGHTNESS, ThresholdType::COARSE },
158 { RSPropertyType::FOREGROUND_BLUR_MASK_COLOR, ThresholdType::COLOR },
159 { RSPropertyType::FOREGROUND_BLUR_COLOR_MODE, ThresholdType::ZERO },
160 { RSPropertyType::FOREGROUND_BLUR_RADIUS_X, ThresholdType::COARSE },
161 { RSPropertyType::FOREGROUND_BLUR_RADIUS_Y, ThresholdType::COARSE },
162 { RSPropertyType::FG_BLUR_DISABLE_SYSTEM_ADAPTATION, ThresholdType::ZERO },
163 { RSPropertyType::ATTRACTION_FRACTION, ThresholdType::MEDIUM },
164 { RSPropertyType::ATTRACTION_DSTPOINT, ThresholdType::MEDIUM },
165 { RSPropertyType::CUSTOM, ThresholdType::DEFAULT },
166 { RSPropertyType::TRANSITION_STYLE, ThresholdType::DEFAULT },
167 { RSPropertyType::BACKGROUND_STYLE, ThresholdType::DEFAULT },
168 { RSPropertyType::CONTENT_STYLE, ThresholdType::DEFAULT },
169 { RSPropertyType::FOREGROUND_STYLE, ThresholdType::DEFAULT },
170 { RSPropertyType::OVERLAY_STYLE, ThresholdType::DEFAULT },
171 { RSPropertyType::NODE_MODIFIER, ThresholdType::DEFAULT },
172 { RSPropertyType::ENV_FOREGROUND_COLOR, ThresholdType::DEFAULT },
173 { RSPropertyType::ENV_FOREGROUND_COLOR_STRATEGY, ThresholdType::DEFAULT },
174 { RSPropertyType::CUSTOM_CLIP_TO_FRAME, ThresholdType::DEFAULT },
175 { RSPropertyType::HDR_BRIGHTNESS, ThresholdType::DEFAULT },
176 { RSPropertyType::HDR_UI_BRIGHTNESS, ThresholdType::COARSE },
177 { RSPropertyType::HDR_BRIGHTNESS_FACTOR, ThresholdType::COARSE },
178 { RSPropertyType::BEHIND_WINDOW_FILTER_RADIUS, ThresholdType::COARSE },
179 { RSPropertyType::BEHIND_WINDOW_FILTER_SATURATION, ThresholdType::COARSE },
180 { RSPropertyType::BEHIND_WINDOW_FILTER_BRIGHTNESS, ThresholdType::COARSE },
181 { RSPropertyType::BEHIND_WINDOW_FILTER_MASK_COLOR, ThresholdType::COARSE },
182 { RSPropertyType::SHADOW_BLENDER_PARAMS, ThresholdType::ZERO },
183 { RSPropertyType::CHILDREN, ThresholdType::DEFAULT }
184 };
185
GenerateModifierId()186 ModifierId RSModifier::GenerateModifierId()
187 {
188 static pid_t pid_ = GetRealPid();
189 static std::atomic<uint32_t> currentId_ = 1;
190
191 auto currentId = currentId_.fetch_add(1, std::memory_order_relaxed);
192 if (currentId == UINT32_MAX) {
193 RS_LOGE("Modifier Id overflow");
194 }
195
196 return ((ModifierId)pid_ << PID_SHIFT) | currentId;
197 }
198
AttachProperty(const std::shared_ptr<RSPropertyBase> & property)199 void RSModifier::AttachProperty(const std::shared_ptr<RSPropertyBase>& property)
200 {
201 if (property == nullptr) {
202 RS_LOGE("Failed to attach property, property is null.");
203 return;
204 }
205 property->SetIsCustom(IsCustom());
206 property->AttachModifier(shared_from_this());
207 if (node_.expired()) {
208 return;
209 }
210 property->target_ = node_;
211 if (IsCustom()) {
212 property->MarkCustomModifierDirty();
213 }
214 }
215
AttachProperty(RSPropertyType type,std::shared_ptr<RSPropertyBase> property)216 void RSModifier::AttachProperty(RSPropertyType type, std::shared_ptr<RSPropertyBase> property)
217 {
218 if (property == nullptr) {
219 RS_LOGE("Failed to attach property with type %{public}d, property is null!", static_cast<int32_t>(type));
220 return;
221 }
222
223 property->SetPropertyTypeNG(type);
224 // replace existing property if any
225 properties_[type] = property;
226 SetPropertyThresholdType(type, property);
227
228 auto node = node_.lock();
229 if (!node) {
230 // not attached yet
231 return;
232 }
233 auto shouldSetOption = node->motionPathOption_ != nullptr && property->IsPathAnimatable();
234 if (shouldSetOption) {
235 property->SetMotionPathOption(node->motionPathOption_);
236 }
237 property->Attach(*node, weak_from_this());
238 MarkNodeDirty();
239 std::shared_ptr<RSRenderPropertyBase> renderProperty = property->GetRenderProperty();
240 std::unique_ptr<RSCommand> command =
241 std::make_unique<RSModifierNGAttachProperty>(node->GetId(), id_, GetType(), type, renderProperty);
242 node->AddCommand(command, node->IsRenderServiceNode(), node->GetFollowType(), node->GetId());
243 if (node->NeedForcedSendToRemote()) {
244 std::unique_ptr<RSCommand> cmdForRemote =
245 std::make_unique<RSModifierNGAttachProperty>(node->GetId(), id_, GetType(), type, renderProperty);
246 node->AddCommand(cmdForRemote, true, node->GetFollowType(), node->GetId());
247 }
248 }
249
DetachProperty(RSPropertyType type)250 void RSModifier::DetachProperty(RSPropertyType type)
251 {
252 auto it = properties_.find(type);
253 if (it == properties_.end()) {
254 return;
255 }
256 auto property = it->second;
257 properties_.erase(it);
258 // actually do the detach
259 property->Detach();
260 auto node = node_.lock();
261 if (!node) {
262 // not attached yet
263 return;
264 }
265 std::unique_ptr<RSCommand> command =
266 std::make_unique<RSModifierNGDetachProperty>(node->GetId(), id_, GetType(), type);
267 node->AddCommand(command, node->IsRenderServiceNode());
268 }
269
SetPropertyThresholdType(RSPropertyType type,std::shared_ptr<RSPropertyBase> property)270 void RSModifier::SetPropertyThresholdType(RSPropertyType type, std::shared_ptr<RSPropertyBase> property)
271 {
272 auto it = g_propertyTypeToThresholdTypeMap.find(type);
273 if (it == g_propertyTypeToThresholdTypeMap.end()) {
274 RS_LOGE("RSPropertyType is not exist! type: %{public}d", static_cast<int32_t>(type));
275 return;
276 }
277 if (it->second != ThresholdType::DEFAULT) {
278 property->SetThresholdType(it->second);
279 }
280 }
281
OnAttach(RSNode & node)282 void RSModifier::OnAttach(RSNode& node)
283 {
284 node_ = node.weak_from_this();
285 if (properties_.empty()) {
286 return;
287 }
288 auto weakPtr = weak_from_this();
289 for (auto& [_, property] : properties_) {
290 auto shouldSetOption = node.motionPathOption_ != nullptr && property->IsPathAnimatable();
291 if (shouldSetOption) {
292 property->SetMotionPathOption(node.motionPathOption_);
293 }
294 property->Attach(node, weakPtr);
295 }
296 MarkNodeDirty();
297 }
298
OnDetach()299 void RSModifier::OnDetach()
300 {
301 node_.reset();
302 for (auto& [_, property] : properties_) {
303 property->Detach();
304 }
305 MarkNodeDirty();
306 }
307
SetDirty(bool isDirty,const std::shared_ptr<RSModifierManager> & modifierManager)308 void RSModifier::SetDirty(bool isDirty, const std::shared_ptr<RSModifierManager>& modifierManager)
309 {
310 if (isDirty_ == isDirty) {
311 // not changed
312 return;
313 }
314 isDirty_ = isDirty;
315
316 if (!isDirty_) {
317 // not dirty
318 return;
319 }
320
321 if (modifierManager == nullptr) {
322 RS_LOGE("multi-instance, Modifier manager is null while mark modifier dirty Id: %{public}" PRIu64 "!", GetId());
323 return;
324 }
325 modifierManager->AddModifier(shared_from_this());
326 }
327
CreateRenderModifier()328 std::shared_ptr<RSRenderModifier> RSModifier::CreateRenderModifier()
329 {
330 const auto& constructor = RSRenderModifier::ConstructorLUT_[static_cast<uint16_t>(GetType())];
331 if (constructor == nullptr) {
332 return nullptr;
333 }
334 auto renderModifier = constructor();
335 renderModifier->id_ = id_;
336 for (auto& [type, property] : properties_) {
337 if (property == nullptr) {
338 RS_LOGE("RSModifier::CreateRenderModifier property is null! type: %{public}d", static_cast<int32_t>(type));
339 continue;
340 }
341 renderModifier->properties_.emplace(type, property->GetRenderProperty());
342 }
343 // this function is only called before marshalling, no need to actually attach properties
344 return renderModifier;
345 }
346 } // namespace OHOS::Rosen::ModifierNG
347