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 "pipeline/rs_render_node_gc.h"
17
18 #include "params/rs_render_params.h"
19 #include "pipeline/rs_render_node.h"
20 #include "rs_trace.h"
21
22 namespace OHOS {
23 namespace Rosen {
Instance()24 RSRenderNodeGC& RSRenderNodeGC::Instance()
25 {
26 static RSRenderNodeGC instance;
27 return instance;
28 }
29
NodeDestructor(RSRenderNode * ptr)30 void RSRenderNodeGC::NodeDestructor(RSRenderNode* ptr)
31 {
32 RSRenderNodeGC::Instance().NodeDestructorInner(ptr);
33 }
34
NodeDestructorInner(RSRenderNode * ptr)35 void RSRenderNodeGC::NodeDestructorInner(RSRenderNode* ptr)
36 {
37 std::lock_guard<std::mutex> lock(nodeMutex_);
38 if (nodeBucket_.size() > 0) {
39 auto& bucket = nodeBucket_.back();
40 if (bucket.size() < BUCKET_MAX_SIZE) {
41 bucket.push_back(ptr);
42 } else {
43 nodeBucket_.push({ptr});
44 }
45 } else {
46 nodeBucket_.push({ptr});
47 }
48 }
49
ReleaseNodeBucket()50 void RSRenderNodeGC::ReleaseNodeBucket()
51 {
52 std::vector<RSRenderNode*> toDele;
53 {
54 std::lock_guard<std::mutex> lock(nodeMutex_);
55 if (nodeBucket_.empty()) {
56 return;
57 }
58 toDele.swap(nodeBucket_.front());
59 nodeBucket_.pop();
60 }
61 RS_TRACE_NAME_FMT("ReleaseNodeMemory %zu", toDele.size());
62 for (auto ptr : toDele) {
63 if (ptr) {
64 delete ptr;
65 ptr = nullptr;
66 }
67 }
68 }
69
ReleaseNodeMemory()70 void RSRenderNodeGC::ReleaseNodeMemory()
71 {
72 RS_TRACE_FUNC();
73 {
74 std::lock_guard<std::mutex> lock(nodeMutex_);
75 if (nodeBucket_.empty()) {
76 return;
77 }
78 }
79 if (mainTask_) {
80 auto task = [this]() {
81 if (isEnable_.load() == false) {
82 return;
83 }
84 ReleaseNodeBucket();
85 ReleaseNodeMemory();
86 };
87 mainTask_(task, DELETE_NODE_TASK, 0, AppExecFwk::EventQueue::Priority::IDLE);
88 } else {
89 ReleaseNodeBucket();
90 }
91 }
92
DrawableDestructor(DrawableV2::RSRenderNodeDrawableAdapter * ptr)93 void RSRenderNodeGC::DrawableDestructor(DrawableV2::RSRenderNodeDrawableAdapter* ptr)
94 {
95 RSRenderNodeGC::Instance().DrawableDestructorInner(ptr);
96 }
97
DrawableDestructorInner(DrawableV2::RSRenderNodeDrawableAdapter * ptr)98 void RSRenderNodeGC::DrawableDestructorInner(DrawableV2::RSRenderNodeDrawableAdapter* ptr)
99 {
100 std::lock_guard<std::mutex> lock(drawableMutex_);
101 if (drawableBucket_.size() > 0) {
102 auto& bucket = drawableBucket_.back();
103 if (bucket.size() < BUCKET_MAX_SIZE) {
104 bucket.push_back(ptr);
105 } else {
106 drawableBucket_.push({ptr});
107 }
108 } else {
109 drawableBucket_.push({ptr});
110 }
111 }
112
ReleaseDrawableBucket()113 void RSRenderNodeGC::ReleaseDrawableBucket()
114 {
115 std::vector<DrawableV2::RSRenderNodeDrawableAdapter*> toDele;
116 {
117 std::lock_guard<std::mutex> lock(drawableMutex_);
118 if (drawableBucket_.empty()) {
119 return;
120 }
121 toDele.swap(drawableBucket_.front());
122 drawableBucket_.pop();
123 }
124 RS_TRACE_NAME_FMT("ReleaseDrawableMemory %zu", toDele.size());
125 for (auto ptr : toDele) {
126 if (ptr) {
127 delete ptr;
128 ptr = nullptr;
129 }
130 }
131 }
132
ReleaseDrawableMemory()133 void RSRenderNodeGC::ReleaseDrawableMemory()
134 {
135 {
136 std::lock_guard<std::mutex> lock(drawableMutex_);
137 if (drawableBucket_.empty()) {
138 return;
139 }
140 }
141 if (renderTask_) {
142 auto task = []() {
143 RSRenderNodeGC::Instance().ReleaseDrawableBucket();
144 RSRenderNodeGC::Instance().ReleaseDrawableMemory();
145 };
146 renderTask_(task, DELETE_DRAWABLE_TASK, 0, AppExecFwk::EventQueue::Priority::IDLE);
147 } else {
148 ReleaseDrawableBucket();
149 }
150 }
151
AddToOffTreeNodeBucket(const std::shared_ptr<RSBaseRenderNode> & node)152 void RSRenderNodeGC::AddToOffTreeNodeBucket(const std::shared_ptr<RSBaseRenderNode>& node)
153 {
154 if (offTreeBucket_.size() > 0) {
155 auto& bucket = offTreeBucket_.back();
156 if (bucket.size() < OFF_TREE_BUCKET_MAX_SIZE) {
157 bucket.emplace_back(node);
158 } else {
159 offTreeBucket_.push({node});
160 }
161 } else {
162 offTreeBucket_.push({node});
163 }
164 }
165
ReleaseOffTreeNodeBucket()166 void RSRenderNodeGC::ReleaseOffTreeNodeBucket()
167 {
168 std::vector<std::shared_ptr<RSBaseRenderNode>> toRemove;
169 if (offTreeBucket_.empty()) {
170 return;
171 }
172 toRemove.swap(offTreeBucket_.front());
173 offTreeBucket_.pop();
174 RS_TRACE_NAME_FMT("ReleaseOffTreeNodeBucket %d", toRemove.size());
175 for (const auto& node : toRemove) {
176 if (!node) {
177 continue;
178 }
179 auto parent = node->GetParent().lock();
180 if (parent) {
181 parent->RemoveChildFromFulllist(node->GetId());
182 }
183 node->RemoveFromTree(false);
184 }
185 }
186
ReleaseFromTree()187 void RSRenderNodeGC::ReleaseFromTree()
188 {
189 if (offTreeBucket_.empty()) {
190 return;
191 }
192 if (mainTask_) {
193 auto task = [this]() {
194 if (!isEnable_.load()) {
195 return;
196 }
197 ReleaseOffTreeNodeBucket();
198 ReleaseFromTree();
199 };
200 mainTask_(task, OFF_TREE_TASK, 0, AppExecFwk::EventQueue::Priority::IDLE);
201 } else {
202 ReleaseOffTreeNodeBucket();
203 }
204 }
205
206 } // namespace Rosen
207 } // namespace OHOS
208