• 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 <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