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