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