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 <stack>
17
18 #include "foundation/graphic/graphic_2d/utils/log/rs_trace.h"
19 #include "rs_profiler.h"
20 #include "rs_profiler_json.h"
21 #include "rs_profiler_log.h"
22 #include "rs_profiler_network.h"
23 #include "rs_profiler_utils.h"
24
25 #include "common/rs_obj_geometry.h"
26 #include "params/rs_render_params.h"
27 #include "pipeline/rs_context.h"
28 #include "pipeline/rs_root_render_node.h"
29 #include "pipeline/rs_screen_render_node.h"
30 #include "pipeline/rs_logical_display_render_node.h"
31 #include "pipeline/rs_surface_handler.h"
32 #include "pipeline/rs_surface_render_node.h"
33
34 namespace OHOS::Rosen {
35
DumpNode(const RSRenderNode & node,JsonWriter & out,bool clearMockFlag,bool absRoot,bool isSorted)36 void RSProfiler::DumpNode(const RSRenderNode& node, JsonWriter& out, bool clearMockFlag, bool absRoot, bool isSorted)
37 {
38 out.PushObject();
39 DumpNodeBaseInfo(node, out, clearMockFlag);
40 if (absRoot) {
41 DumpNodeAbsoluteProperties(node, out);
42 } else {
43 DumpNodeProperties(node.GetRenderProperties(), out);
44 }
45 DumpNodeOptionalFlags(node, out);
46 DumpNodeDrawCmdModifiers(node, out);
47 DumpNodeAnimations(node.animationManager_, out);
48 DumpNodeChildrenListUpdate(node, out);
49
50 auto& children = out["children"];
51 children.PushArray();
52
53 if (!isSorted) {
54 for (auto& child : node.GetChildrenList()) {
55 if (auto lockedChild = child.lock(); lockedChild) {
56 DumpNode(*lockedChild, children, clearMockFlag, false, isSorted);
57 }
58 }
59 } else if (auto sortedChildren = node.GetSortedChildren()) {
60 for (auto& child : *sortedChildren) {
61 if (child) {
62 DumpNode(*child, children, clearMockFlag, false, isSorted);
63 }
64 }
65 }
66
67 children.PopArray();
68 out.PopObject();
69 }
70
DumpOffscreen(RSContext & context,JsonWriter & rootOffscreen,bool useMockPid,pid_t pid)71 void RSProfiler::DumpOffscreen(RSContext& context, JsonWriter& rootOffscreen, bool useMockPid, pid_t pid)
72 {
73 rootOffscreen.PushObject();
74 rootOffscreen["type"] = std::string("OFF_SCREEN");
75 auto& children = rootOffscreen["children"];
76 children.PushArray();
77
78 const auto& map = context.GetMutableNodeMap();
79 map.TraversalNodes([&pid, &children, &useMockPid](const std::shared_ptr<RSBaseRenderNode>& node) {
80 if (node == nullptr) {
81 return;
82 }
83 const auto parent = node->GetParent().lock();
84 if (!parent && (!pid || pid == Utils::ExtractPid(node->GetId()))) {
85 DumpNode(*node, children, useMockPid, pid > 0, false);
86 }
87 });
88
89 children.PopArray();
90 rootOffscreen.PopObject();
91 }
92
AdjustNodeId(NodeId nodeId,bool clearMockFlag)93 NodeId RSProfiler::AdjustNodeId(NodeId nodeId, bool clearMockFlag)
94 {
95 if (clearMockFlag) {
96 constexpr int shift = 30 + 32;
97 constexpr uint64_t mask = (uint64_t)1 << shift;
98 return nodeId & ~mask;
99 }
100 return nodeId;
101 }
102
DumpNodeAbsoluteProperties(const RSRenderNode & node,JsonWriter & out)103 void RSProfiler::DumpNodeAbsoluteProperties(const RSRenderNode& node, JsonWriter& out)
104 {
105 std::stack<RSRenderNode::SharedPtr> parentStack;
106 // trace back to top parent
107 auto parent = node.GetParent().lock();
108 while (parent) {
109 parentStack.push(parent);
110 if (parent->GetType() == RSRenderNodeType::SCREEN_NODE) {
111 break;
112 }
113 parent = parent->GetParent().lock();
114 }
115 // calc absolute position from top parent to current node
116 float upperLeftX = .0f;
117 float upperLeftY = .0f;
118 float scaleX = 1.0f;
119 float scaleY = 1.0f;
120 auto accParent = [&](RSRenderNode::SharedPtr node) {
121 if (node) {
122 const auto& prop = node->GetRenderProperties();
123 upperLeftX += std::isfinite(prop.GetBoundsPositionX()) ? prop.GetBoundsPositionX() : 0.0f;
124 upperLeftY += std::isfinite(prop.GetBoundsPositionY()) ? prop.GetBoundsPositionY() : 0.0f;
125 scaleX *= std::isfinite(prop.GetScaleX()) ? prop.GetScaleX() : 1.0f;
126 scaleY *= std::isfinite(prop.GetScaleY()) ? prop.GetScaleY() : 1.0f;
127 }
128 };
129 while (!parentStack.empty()) {
130 auto parentNode = parentStack.top();
131 accParent(parentNode);
132 parentStack.pop();
133 }
134
135 // write result into json
136 auto& json = out["Properties"];
137 const auto& prop = node.GetRenderProperties();
138 json.PushObject();
139 json["Bounds"] = { prop.GetBoundsPositionX() + upperLeftX, prop.GetBoundsPositionY() + upperLeftY,
140 prop.GetBoundsWidth(), prop.GetBoundsHeight() };
141 json["Frame"] = { prop.GetFramePositionX(), prop.GetFramePositionY(), prop.GetFrameWidth(), prop.GetFrameHeight() };
142 if (!prop.GetVisible()) {
143 json["IsVisible"] = false;
144 }
145 json["ScaleX"] = prop.GetScaleX() * scaleX;
146 json["ScaleY"] = prop.GetScaleY() * scaleY;
147 DumpNodePropertiesNonSpatial(prop, json);
148 json.PopObject();
149 }
150
DumpNodeBaseInfo(const RSRenderNode & node,JsonWriter & out,bool clearMockFlag)151 void RSProfiler::DumpNodeBaseInfo(const RSRenderNode& node, JsonWriter& out, bool clearMockFlag)
152 {
153 std::string type;
154 node.DumpNodeType(node.GetType(), type);
155 out["type"] = type;
156 out["id"] = AdjustNodeId(node.GetId(), clearMockFlag);
157 out["instanceRootNodeId"] = AdjustNodeId(node.GetInstanceRootNodeId(), clearMockFlag);
158 out["firstLevelNodeId"] = AdjustNodeId(node.GetFirstLevelNodeId(), clearMockFlag);
159 DumpNodeSubsurfaces(node, out);
160 auto sharedTrans = node.GetSharedTransitionParam();
161 if (sharedTrans) {
162 out["SharedTransitionParam"] =
163 std::to_string(sharedTrans->inNodeId_) + " -> " + std::to_string(sharedTrans->outNodeId_);
164 }
165 if (node.IsSuggestedDrawInGroup()) {
166 const auto& renderParams = const_cast<RSRenderNode&>(node).GetStagingRenderParams();
167 out["nodeGroup"] = static_cast<int>(node.nodeGroupType_);
168 out["nodeGroupReuseCache"] = renderParams ? static_cast<int>(!renderParams->GetNeedUpdateCache()) : 0;
169 }
170 if (node.GetUifirstRootNodeId() != INVALID_NODEID) {
171 out["uifirstRootNodeId"] = AdjustNodeId(node.GetUifirstRootNodeId(), clearMockFlag);
172 }
173 DumpNodeSubClassNode(node, out);
174 }
175
DumpNodeSubsurfaces(const RSRenderNode & node,JsonWriter & out)176 void RSProfiler::DumpNodeSubsurfaces(const RSRenderNode& node, JsonWriter& out)
177 {
178 if (auto surface = node.ReinterpretCastTo<RSSurfaceRenderNode>(); surface && surface->HasSubSurfaceNodes()) {
179 auto& subsurface = out["subsurface"];
180 subsurface.PushArray();
181 for (auto [id, _] : surface->GetChildSubSurfaceNodes()) {
182 subsurface.Append(id);
183 }
184 subsurface.PopArray();
185 }
186 }
187
DumpNodeSubClassNode(const RSRenderNode & node,JsonWriter & out)188 void RSProfiler::DumpNodeSubClassNode(const RSRenderNode& node, JsonWriter& out)
189 {
190 auto& subclass = out["subclass"];
191 subclass.PushObject();
192 if (node.GetType() == RSRenderNodeType::SURFACE_NODE) {
193 auto& surfaceNode = static_cast<const RSSurfaceRenderNode&>(node);
194 auto p = node.parent_.lock();
195 subclass["Parent"] = p ? p->GetId() : uint64_t(0);
196 subclass["Name"] = surfaceNode.GetName();
197 const auto surfaceHandler = surfaceNode.GetRSSurfaceHandler();
198 out["hasConsumer"] = surfaceHandler ? surfaceHandler->HasConsumer() : false;
199 std::string contextAlpha = std::to_string(surfaceNode.contextAlpha_);
200 std::string propertyAlpha = std::to_string(surfaceNode.GetRenderProperties().GetAlpha());
201 subclass["Alpha"] = propertyAlpha + " (include ContextAlpha: " + contextAlpha + ")";
202 subclass["Visible"] = std::to_string(surfaceNode.GetRenderProperties().GetVisible()) + " " +
203 surfaceNode.GetVisibleRegion().GetRegionInfo();
204 subclass["Opaque"] = surfaceNode.GetOpaqueRegion().GetRegionInfo();
205 subclass["OcclusionBg"] = std::to_string((surfaceNode.GetAbilityBgAlpha()));
206 const auto specialLayerManager = surfaceNode.GetSpecialLayerMgr();
207 subclass["SpecialLayer"] = std::to_string(specialLayerManager.Get());
208 } else if (node.GetType() == RSRenderNodeType::ROOT_NODE) {
209 auto& rootNode = static_cast<const RSRootRenderNode&>(node);
210 subclass["Visible"] = rootNode.GetRenderProperties().GetVisible();
211 subclass["Size"] = { rootNode.GetRenderProperties().GetFrameWidth(),
212 rootNode.GetRenderProperties().GetFrameHeight() };
213 subclass["EnableRender"] = rootNode.GetEnableRender();
214 } else if (node.GetType() == RSRenderNodeType::LOGICAL_DISPLAY_NODE) {
215 auto& displayNode = static_cast<const RSLogicalDisplayRenderNode&>(node);
216 subclass["skipLayer"] = displayNode.GetSecurityDisplay();
217 }
218 subclass.PopObject();
219 }
220
DumpNodeOptionalFlags(const RSRenderNode & node,JsonWriter & out)221 void RSProfiler::DumpNodeOptionalFlags(const RSRenderNode& node, JsonWriter& out)
222 {
223 if (node.GetBootAnimation()) {
224 out["GetBootAnimation"] = true;
225 }
226 if (node.isContainBootAnimation_) {
227 out["isContainBootAnimation_"] = true;
228 }
229 if (node.dirtyStatus_ != RSRenderNode::NodeDirty::CLEAN) {
230 out["isNodeDirty"] = static_cast<int>(node.dirtyStatus_);
231 }
232 if (node.GetRenderProperties().IsDirty()) {
233 out["isPropertyDirty"] = true;
234 }
235 if (node.isSubTreeDirty_) {
236 out["isSubTreeDirty"] = true;
237 }
238 if (node.IsPureContainer()) {
239 out["IsPureContainer"] = true;
240 }
241 }
242
Hex(uint32_t value)243 static std::string Hex(uint32_t value)
244 {
245 std::stringstream sstream;
246 sstream << std::hex << value;
247 return sstream.str();
248 }
249
DumpNodeDrawCmdModifiers(const RSRenderNode & node,JsonWriter & out)250 void RSProfiler::DumpNodeDrawCmdModifiers(const RSRenderNode& node, JsonWriter& out)
251 {
252 if (node.modifiersNG_.empty()) {
253 return;
254 }
255
256 auto& modifiersJson = out["DrawCmdModifiers"];
257 modifiersJson.PushArray();
258 for (uint16_t type = 0; type < ModifierNG::MODIFIER_TYPE_COUNT; type++) {
259 if (type < static_cast<uint16_t>(ModifierNG::RSModifierType::TRANSITION_STYLE) &&
260 type != static_cast<uint16_t>(ModifierNG::RSModifierType::CLIP_TO_FRAME)) {
261 continue;
262 }
263 auto& slot = node.modifiersNG_[type];
264 if (slot.empty()) {
265 continue;
266 }
267 modifiersJson.PushObject();
268 modifiersJson["type"] = type;
269 auto& modifierDesc = modifiersJson["modifiers"];
270 modifierDesc.PushArray();
271 for (auto modifier : slot) {
272 if (modifier != nullptr) {
273 DumpNodeDrawCmdModifier(node, modifierDesc, modifier);
274 }
275 }
276 modifiersJson.PopArray();
277 modifiersJson.PopObject();
278 }
279 modifiersJson.PopArray();
280 }
281
DumpNodeDrawCmdModifier(const RSRenderNode & node,JsonWriter & out,std::shared_ptr<ModifierNG::RSRenderModifier> modifier)282 void RSProfiler::DumpNodeDrawCmdModifier(
283 const RSRenderNode& node, JsonWriter& out, std::shared_ptr<ModifierNG::RSRenderModifier> modifier)
284 {
285 if (modifier->IsCustom()) {
286 auto propertyType = ModifierNG::ModifierTypeConvertor::GetPropertyType(modifier->GetType());
287 auto drawCmdList = modifier->Getter<Drawing::DrawCmdListPtr>(propertyType, nullptr);
288 auto propertyStr = drawCmdList ? drawCmdList->GetOpsWithDesc() : "";
289 size_t pos = 0;
290 size_t oldpos = 0;
291 out.PushObject();
292 auto& property = out["drawCmdList"];
293 property.PushArray();
294 while ((pos = propertyStr.find('\n', oldpos)) != std::string::npos) {
295 property.Append(propertyStr.substr(oldpos, pos - oldpos));
296 oldpos = pos + 1;
297 }
298 property.PopArray();
299 out.PopObject();
300 } else if (modifier->GetType() == ModifierNG::RSModifierType::ENV_FOREGROUND_COLOR) {
301 if (modifier->HasProperty(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR)) {
302 auto value = modifier->Getter(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR, Color());
303 out.PushObject();
304 out["ENV_FOREGROUND_COLOR"] = "#" + Hex(value.AsRgbaInt()) + " (RGBA)";
305 out.PopObject();
306 }
307 if (modifier->HasProperty(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR_STRATEGY)) {
308 out.PushObject();
309 out["ENV_FOREGROUND_COLOR_STRATEGY"] =
310 modifier->Getter(ModifierNG::RSPropertyType::ENV_FOREGROUND_COLOR_STRATEGY, 0);
311 out.PopObject();
312 }
313 } else if (modifier->GetType() == ModifierNG::RSModifierType::CLIP_TO_FRAME) {
314 if (modifier->HasProperty(ModifierNG::RSPropertyType::CUSTOM_CLIP_TO_FRAME)) {
315 auto property = modifier->GetProperty(ModifierNG::RSPropertyType::CUSTOM_CLIP_TO_FRAME);
316 if (property != nullptr) {
317 std::string str;
318 property->Dump(str);
319 out.PushObject();
320 out["CUSTOM_CLIP_TO_FRAME"] = str;
321 out.PopObject();
322 }
323 }
324 } else if (modifier->GetType() == ModifierNG::RSModifierType::HDR_BRIGHTNESS) {
325 if (modifier->HasProperty(ModifierNG::RSPropertyType::HDR_BRIGHTNESS)) {
326 out.PushObject();
327 out["HDR_BRIGHTNESS"] = modifier->Getter(ModifierNG::RSPropertyType::HDR_BRIGHTNESS, 1.f);
328 out.PopObject();
329 }
330 }
331 }
332
DumpNodeProperties(const RSProperties & properties,JsonWriter & out)333 void RSProfiler::DumpNodeProperties(const RSProperties& properties, JsonWriter& out)
334 {
335 auto& json = out["Properties"];
336 json.PushObject();
337 json["Bounds"] = { properties.GetBoundsPositionX(), properties.GetBoundsPositionY(), properties.GetBoundsWidth(),
338 properties.GetBoundsHeight() };
339 json["Frame"] = { properties.GetFramePositionX(), properties.GetFramePositionY(), properties.GetFrameWidth(),
340 properties.GetFrameHeight() };
341
342 if (!properties.GetVisible()) {
343 json["IsVisible"] = false;
344 }
345 DumpNodePropertiesTransform(properties, json);
346 DumpNodePropertiesNonSpatial(properties, json);
347 json.PopObject();
348 }
349
DumpNodePropertiesClip(const RSProperties & properties,JsonWriter & out)350 void RSProfiler::DumpNodePropertiesClip(const RSProperties& properties, JsonWriter& out)
351 {
352 if (properties.clipToBounds_) {
353 out["ClipToBounds"] = true;
354 }
355 if (properties.clipToFrame_) {
356 out["ClipToFrame"] = true;
357 }
358 }
359
DumpNodePropertiesTransform(const RSProperties & properties,JsonWriter & out)360 void RSProfiler::DumpNodePropertiesTransform(const RSProperties& properties, JsonWriter& out)
361 {
362 if (!ROSEN_EQ(properties.GetPositionZ(), 0.f)) {
363 out["PositionZ"] = properties.GetPositionZ();
364 }
365 RSTransform defaultTransform;
366 Vector2f pivot = properties.GetPivot();
367 if ((!ROSEN_EQ(pivot[0], defaultTransform.pivotX_) || !ROSEN_EQ(pivot[1], defaultTransform.pivotY_))) {
368 out["Pivot"] = { pivot[0], pivot[1] };
369 }
370 if (!ROSEN_EQ(properties.GetRotation(), defaultTransform.rotation_)) {
371 out["Rotation"] = properties.GetRotation();
372 }
373 if (!ROSEN_EQ(properties.GetRotationX(), defaultTransform.rotationX_)) {
374 out["RotationX"] = properties.GetRotationX();
375 }
376 if (!ROSEN_EQ(properties.GetRotationY(), defaultTransform.rotationY_)) {
377 out["RotationY"] = properties.GetRotationY();
378 }
379 if (!ROSEN_EQ(properties.GetTranslateX(), defaultTransform.translateX_)) {
380 out["TranslateX"] = properties.GetTranslateX();
381 }
382 if (!ROSEN_EQ(properties.GetTranslateY(), defaultTransform.translateY_)) {
383 out["TranslateY"] = properties.GetTranslateY();
384 }
385 if (!ROSEN_EQ(properties.GetTranslateZ(), defaultTransform.translateZ_)) {
386 out["TranslateZ"] = properties.GetTranslateZ();
387 }
388 if (!ROSEN_EQ(properties.GetScaleX(), defaultTransform.scaleX_)) {
389 out["ScaleX"] = properties.GetScaleX();
390 }
391 if (!ROSEN_EQ(properties.GetScaleY(), defaultTransform.scaleY_)) {
392 out["ScaleY"] = properties.GetScaleY();
393 }
394 }
395
DumpNodePropertiesNonSpatial(const RSProperties & properties,JsonWriter & out)396 void RSProfiler::DumpNodePropertiesNonSpatial(const RSProperties& properties, JsonWriter& out)
397 {
398 DumpNodePropertiesClip(properties, out);
399 DumpNodePropertiesDecoration(properties, out);
400 DumpNodePropertiesShadow(properties, out);
401 DumpNodePropertiesEffects(properties, out);
402 DumpNodePropertiesColor(properties, out);
403 }
404
DumpNodePropertiesDecoration(const RSProperties & properties,JsonWriter & out)405 void RSProfiler::DumpNodePropertiesDecoration(const RSProperties& properties, JsonWriter& out)
406 {
407 if (!properties.GetCornerRadius().IsZero()) {
408 out["CornerRadius"] = { properties.GetCornerRadius().x_, properties.GetCornerRadius().y_,
409 properties.GetCornerRadius().z_, properties.GetCornerRadius().w_ };
410 }
411 if (properties.pixelStretch_.has_value()) {
412 auto& pixelStretch = out["PixelStretch"];
413 pixelStretch.PushObject();
414 pixelStretch["left"] = properties.pixelStretch_->x_;
415 pixelStretch["top"] = properties.pixelStretch_->y_;
416 pixelStretch["right"] = properties.pixelStretch_->z_;
417 pixelStretch["bottom"] = properties.pixelStretch_->w_;
418 pixelStretch.PopObject();
419 }
420 if (!ROSEN_EQ(properties.GetAlpha(), 1.f)) {
421 out["Alpha"] = properties.GetAlpha();
422 }
423 if (!ROSEN_EQ(properties.GetSpherize(), 0.f)) {
424 out["Spherize"] = properties.GetSpherize();
425 }
426 if (!ROSEN_EQ(properties.GetForegroundColor(), RgbPalette::Transparent())) {
427 out["ForegroundColor"] = "#" + Hex(properties.GetForegroundColor().AsArgbInt()) + " (ARGB)";
428 }
429 if (!ROSEN_EQ(properties.GetBackgroundColor(), RgbPalette::Transparent())) {
430 out["BackgroundColor"] = "#" + Hex(properties.GetBackgroundColor().AsArgbInt()) + " (ARGB)";
431 }
432 Decoration defaultDecoration;
433 if ((!ROSEN_EQ(properties.GetBgImagePositionX(), defaultDecoration.bgImageRect_.left_) ||
434 !ROSEN_EQ(properties.GetBgImagePositionY(), defaultDecoration.bgImageRect_.top_) ||
435 !ROSEN_EQ(properties.GetBgImageWidth(), defaultDecoration.bgImageRect_.width_) ||
436 !ROSEN_EQ(properties.GetBgImageHeight(), defaultDecoration.bgImageRect_.height_))) {
437 out["BgImage"] = { properties.GetBgImagePositionX(), properties.GetBgImagePositionY(),
438 properties.GetBgImageWidth(), properties.GetBgImageHeight() };
439 }
440 }
441
DumpNodePropertiesShadow(const RSProperties & properties,JsonWriter & out)442 void RSProfiler::DumpNodePropertiesShadow(const RSProperties& properties, JsonWriter& out)
443 {
444 if (!ROSEN_EQ(properties.GetShadowColor(), Color(DEFAULT_SPOT_COLOR))) {
445 out["ShadowColor"] = "#" + Hex(properties.GetShadowColor().AsArgbInt()) + " (ARGB)";
446 }
447 if (!ROSEN_EQ(properties.GetShadowOffsetX(), DEFAULT_SHADOW_OFFSET_X)) {
448 out["ShadowOffsetX"] = properties.GetShadowOffsetX();
449 }
450 if (!ROSEN_EQ(properties.GetShadowOffsetY(), DEFAULT_SHADOW_OFFSET_Y)) {
451 out["ShadowOffsetY"] = properties.GetShadowOffsetY();
452 }
453 if (!ROSEN_EQ(properties.GetShadowAlpha(), 0.f)) {
454 out["ShadowAlpha"] = properties.GetShadowAlpha();
455 }
456 if (!ROSEN_EQ(properties.GetShadowElevation(), 0.f)) {
457 out["ShadowElevation"] = properties.GetShadowElevation();
458 }
459 if (!ROSEN_EQ(properties.GetShadowRadius(), 0.f)) {
460 out["ShadowRadius"] = properties.GetShadowRadius();
461 }
462 if (!ROSEN_EQ(properties.GetShadowIsFilled(), false)) {
463 out["ShadowIsFilled"] = properties.GetShadowIsFilled();
464 }
465 }
466
DumpNodePropertiesEffects(const RSProperties & properties,JsonWriter & out)467 void RSProfiler::DumpNodePropertiesEffects(const RSProperties& properties, JsonWriter& out)
468 {
469 if (properties.border_ && properties.border_->HasBorder()) {
470 out["Border"] = properties.border_->ToString();
471 }
472 auto filter = properties.GetFilter();
473 if (filter && filter->IsValid()) {
474 out["Filter"] = filter->GetDescription();
475 }
476 auto backgroundFilter = properties.GetBackgroundFilter();
477 if (backgroundFilter && backgroundFilter->IsValid()) {
478 out["BackgroundFilter"] = backgroundFilter->GetDescription();
479 }
480 auto foregroundFilterCache = properties.GetForegroundFilterCache();
481 if (foregroundFilterCache && foregroundFilterCache->IsValid()) {
482 out["ForegroundFilter"] = foregroundFilterCache->GetDescription();
483 }
484 if (properties.outline_ && properties.outline_->HasBorder()) {
485 out["Outline"] = properties.outline_->ToString();
486 }
487 if (!ROSEN_EQ(properties.GetFrameGravity(), Gravity::DEFAULT)) {
488 out["FrameGravity"] = static_cast<int>(properties.GetFrameGravity());
489 }
490 if (properties.GetUseEffect()) {
491 out["GetUseEffect"] = true;
492 }
493 auto grayScale = properties.GetGrayScale();
494 if (grayScale.has_value() && !ROSEN_EQ(*grayScale, 0.f)) {
495 out["GrayScale"] = *grayScale;
496 }
497 if (!ROSEN_EQ(properties.GetLightUpEffect(), 1.f)) {
498 out["LightUpEffect"] = properties.GetLightUpEffect();
499 }
500 auto dynamicLightUpRate = properties.GetDynamicLightUpRate();
501 if (dynamicLightUpRate.has_value() && !ROSEN_EQ(*dynamicLightUpRate, 0.f)) {
502 out["DynamicLightUpRate"] = *dynamicLightUpRate;
503 }
504 auto dynamicLightUpDegree = properties.GetDynamicLightUpDegree();
505 if (dynamicLightUpDegree.has_value() && !ROSEN_EQ(*dynamicLightUpDegree, 0.f)) {
506 out["DynamicLightUpDegree"] = *dynamicLightUpDegree;
507 }
508 }
509
DumpNodePropertiesColor(const RSProperties & properties,JsonWriter & out)510 void RSProfiler::DumpNodePropertiesColor(const RSProperties& properties, JsonWriter& out)
511 {
512 auto brightness = properties.GetBrightness();
513 if (brightness.has_value() && !ROSEN_EQ(*brightness, 1.f)) {
514 out["Brightness"] = *brightness;
515 }
516 auto contrast = properties.GetContrast();
517 if (contrast.has_value() && !ROSEN_EQ(*contrast, 1.f)) {
518 out["Contrast"] = *contrast;
519 }
520 auto saturate = properties.GetSaturate();
521 if (saturate.has_value() && !ROSEN_EQ(*saturate, 1.f)) {
522 out["Saturate"] = *saturate;
523 }
524 auto sepia = properties.GetSepia();
525 if (sepia.has_value() && !ROSEN_EQ(*sepia, 0.f)) {
526 out["Sepia"] = *sepia;
527 }
528 auto invert = properties.GetInvert();
529 if (invert.has_value() && !ROSEN_EQ(*invert, 0.f)) {
530 out["Invert"] = *invert;
531 }
532 auto hueRotate = properties.GetHueRotate();
533 if (hueRotate.has_value() && !ROSEN_EQ(*hueRotate, 0.f)) {
534 out["HueRotate"] = *hueRotate;
535 }
536 auto colorBlend = properties.GetColorBlend();
537 if (colorBlend.has_value() && !ROSEN_EQ(*colorBlend, RgbPalette::Transparent())) {
538 out["ColorBlend"] = "#" + Hex(colorBlend->AsArgbInt()) + " (ARGB)";
539 }
540 if (!ROSEN_EQ(properties.GetColorBlendMode(), 0)) {
541 out["skblendmode"] = properties.GetColorBlendMode() - 1;
542 out["blendType"] = properties.GetColorBlendApplyType();
543 }
544 }
545
DumpNodeAnimations(const RSAnimationManager & animationManager,JsonWriter & out)546 void RSProfiler::DumpNodeAnimations(const RSAnimationManager& animationManager, JsonWriter& out)
547 {
548 if (animationManager.animations_.empty()) {
549 return;
550 }
551 auto& animations = out["RSAnimationManager"];
552 animations.PushArray();
553 for (auto [id, animation] : animationManager.animations_) {
554 if (animation) {
555 DumpNodeAnimation(*animation, animations);
556 }
557 }
558 animations.PopArray();
559 }
560
DumpNodeAnimation(const RSRenderAnimation & animation,JsonWriter & out)561 void RSProfiler::DumpNodeAnimation(const RSRenderAnimation& animation, JsonWriter& out)
562 {
563 out.PushObject();
564 out["id"] = animation.id_;
565 std::string type;
566 animation.DumpAnimationInfo(type);
567 out["type"] = type;
568 out["AnimationState"] = static_cast<int>(animation.state_);
569 out["Duration"] = animation.animationFraction_.GetDuration();
570 out["StartDelay"] = animation.animationFraction_.GetStartDelay();
571 out["Speed"] = animation.animationFraction_.GetSpeed();
572 out["RepeatCount"] = animation.animationFraction_.GetRepeatCount();
573 out["AutoReverse"] = animation.animationFraction_.GetAutoReverse();
574 out["Direction"] = animation.animationFraction_.GetDirection();
575 out["FillMode"] = static_cast<int>(animation.animationFraction_.GetFillMode());
576 out["RepeatCallbackEnable"] = animation.animationFraction_.GetRepeatCallbackEnable();
577 out["FrameRateRange_min"] = animation.animationFraction_.GetFrameRateRange().min_;
578 out["FrameRateRange_max"] = animation.animationFraction_.GetFrameRateRange().max_;
579 out["FrameRateRange_prefered"] = animation.animationFraction_.GetFrameRateRange().preferred_;
580 out.PopObject();
581 }
582
DumpNodeChildrenListUpdate(const RSRenderNode & node,JsonWriter & out)583 void RSProfiler::DumpNodeChildrenListUpdate(const RSRenderNode& node, JsonWriter& out)
584 {
585 if (!node.isFullChildrenListValid_) {
586 auto& childrenUpdate = out["children update"];
587 childrenUpdate.PushObject();
588 childrenUpdate["current count"] = node.fullChildrenList_ ? node.fullChildrenList_->size() : 0;
589 std::string expected = std::to_string(node.GetSortedChildren()->size());
590 if (!node.disappearingChildren_.empty()) {
591 childrenUpdate["disappearing count"] = node.disappearingChildren_.size();
592 expected += " + " + std::to_string(node.disappearingChildren_.size());
593 }
594 childrenUpdate["expected count"] = expected;
595 childrenUpdate.PopObject();
596 }
597 }
598
599 } // namespace OHOS::Rosen