1 /*
2 * Copyright (c) 2021 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 "ui/rs_base_node.h"
17
18 #include <algorithm>
19 #include <sstream>
20
21 #include "command/rs_base_node_command.h"
22 #include "pipeline/rs_node_map.h"
23 #include "platform/common/rs_log.h"
24 #include "transaction/rs_transaction_proxy.h"
25 #include "ui/rs_canvas_node.h"
26 #include "ui/rs_display_node.h"
27 #include "ui/rs_root_node.h"
28 #include "ui/rs_surface_node.h"
29 #include "ui/rs_texture_node.h"
30
31 namespace OHOS {
32 namespace Rosen {
33
GenerateId()34 NodeId RSBaseNode::GenerateId()
35 {
36 static pid_t pid_ = getpid();
37 static std::atomic<uint32_t> currentId_ = 0;
38
39 ++currentId_;
40 if (currentId_ == UINT32_MAX) {
41 // [PLANNING]:process the overflow situations
42 ROSEN_LOGE("Node Id overflow");
43 }
44
45 // concat two 32-bit numbers to one 64-bit number
46 return ((NodeId)pid_ << 32) | currentId_;
47 }
48
RSBaseNode(bool isRenderServiceNode)49 RSBaseNode::RSBaseNode(bool isRenderServiceNode) : id_(GenerateId()), isRenderServiceNode_(isRenderServiceNode) {}
50
~RSBaseNode()51 RSBaseNode::~RSBaseNode()
52 {
53 RemoveFromTree();
54 RSNodeMap::MutableInstance().UnregisterNode(id_);
55 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeDestroy>(id_);
56 auto transactionProxy = RSTransactionProxy::GetInstance();
57 if (transactionProxy != nullptr) {
58 transactionProxy->AddCommand(command, IsRenderServiceNode());
59 }
60 }
61
AddChild(SharedPtr child,int index)62 void RSBaseNode::AddChild(SharedPtr child, int index)
63 {
64 if (child == nullptr) {
65 ROSEN_LOGE("RSBaseNode::AddChild, child is nullptr");
66 return;
67 }
68 NodeId childId = child->GetId();
69 if (child->parent_ != 0) {
70 child->RemoveFromTree();
71 }
72
73 if (index < 0 || index >= static_cast<int>(children_.size())) {
74 children_.push_back(childId);
75 } else {
76 children_.insert(children_.begin() + index, childId);
77 }
78 child->SetParent(id_);
79 child->OnAddChildren();
80 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeAddChild>(id_, childId, index);
81 auto transactionProxy = RSTransactionProxy::GetInstance();
82 if (transactionProxy != nullptr) {
83 transactionProxy->AddCommand(command, IsRenderServiceNode());
84 }
85 }
86
RemoveChild(SharedPtr child)87 void RSBaseNode::RemoveChild(SharedPtr child)
88 {
89 if (child == nullptr || child->parent_ != id_) {
90 ROSEN_LOGE("RSBaseNode::RemoveChild, child is nullptr");
91 return;
92 }
93 NodeId childId = child->GetId();
94 RemoveChildById(childId);
95 child->OnRemoveChildren();
96 child->SetParent(0);
97
98 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeRemoveChild>(id_, childId);
99 auto transactionProxy = RSTransactionProxy::GetInstance();
100 if (transactionProxy != nullptr) {
101 transactionProxy->AddCommand(command, IsRenderServiceNode());
102 }
103 }
104
RemoveChildById(NodeId childId)105 void RSBaseNode::RemoveChildById(NodeId childId)
106 {
107 auto itr = std::find(children_.begin(), children_.end(), childId);
108 if (itr != children_.end()) {
109 children_.erase(itr);
110 }
111 }
112
RemoveFromTree()113 void RSBaseNode::RemoveFromTree()
114 {
115 if (auto parentPtr = RSNodeMap::Instance().GetNode(parent_)) {
116 parentPtr->RemoveChildById(id_);
117 OnRemoveChildren();
118 SetParent(0);
119 }
120 // always send Remove-From-Tree command
121 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeRemoveFromTree>(id_);
122 auto transactionProxy = RSTransactionProxy::GetInstance();
123 if (transactionProxy != nullptr) {
124 transactionProxy->AddCommand(command, IsRenderServiceNode());
125 }
126 }
127
ClearChildren()128 void RSBaseNode::ClearChildren()
129 {
130 for (auto child : children_) {
131 if (auto childPtr = RSNodeMap::Instance().GetNode(child)) {
132 childPtr->SetParent(0);
133 }
134 }
135 children_.clear();
136
137 std::unique_ptr<RSCommand> command = std::make_unique<RSBaseNodeClearChild>(id_);
138 auto transactionProxy = RSTransactionProxy::GetInstance();
139 if (transactionProxy != nullptr) {
140 transactionProxy->AddCommand(command, IsRenderServiceNode());
141 }
142 }
143
SetParent(NodeId parentId)144 void RSBaseNode::SetParent(NodeId parentId)
145 {
146 parent_ = parentId;
147 }
148
GetParent()149 RSBaseNode::SharedPtr RSBaseNode::GetParent()
150 {
151 return RSNodeMap::Instance().GetNode(parent_);
152 }
153
DumpNode(int depth) const154 std::string RSBaseNode::DumpNode(int depth) const
155 {
156 std::stringstream ss;
157 auto it = RSUINodeTypeStrs.find(GetType());
158 if (it == RSUINodeTypeStrs.end()) {
159 return "";
160 }
161 ss << it->second << "[" << std::to_string(id_) << "] child[";
162 for (auto child : children_) {
163 ss << std::to_string(child) << " ";
164 }
165 ss << "]";
166 return ss.str();
167 }
168
169 template<typename T>
IsInstanceOf()170 bool RSBaseNode::IsInstanceOf()
171 {
172 constexpr uint32_t targetType = static_cast<uint32_t>(T::Type);
173 return (static_cast<uint32_t>(GetType()) & targetType) == targetType;
174 }
175
176 // explicit instantiation with all rendernode types
177 template bool RSBaseNode::IsInstanceOf<RSBaseNode>();
178 template bool RSBaseNode::IsInstanceOf<RSDisplayNode>();
179 template bool RSBaseNode::IsInstanceOf<RSNode>();
180 template bool RSBaseNode::IsInstanceOf<RSSurfaceNode>();
181 template bool RSBaseNode::IsInstanceOf<RSCanvasNode>();
182 template bool RSBaseNode::IsInstanceOf<RSRootNode>();
183 template bool RSBaseNode::IsInstanceOf<RSTextureNode>();
184
185 } // namespace Rosen
186 } // namespace OHOS
187