1 /*
2 * Copyright (c) 2025 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_allocator.h"
17
18 #include "common/rs_optional_trace.h"
19 #include "pipeline/rs_render_node_gc.h"
20 #include "platform/common/rs_log.h"
21
22 namespace OHOS {
23 namespace Rosen {
24 namespace {
25 constexpr uint32_t NODE_ALLOCATOR_LIMIT = 512;
26 constexpr uint32_t DRAWABLE_ALLOCATOR_LIMIT = 512;
27 }
28
Instance()29 RSRenderNodeAllocator& RSRenderNodeAllocator::Instance()
30 {
31 static RSRenderNodeAllocator instance;
32 return instance;
33 }
34
AddNodeToAllocator(RSRenderNode * ptr)35 bool RSRenderNodeAllocator::AddNodeToAllocator(RSRenderNode* ptr)
36 {
37 if (ptr == nullptr || ptr->GetType() != RSRenderNodeType::CANVAS_NODE) {
38 return false;
39 }
40
41 nodeAllocatorSpinlock_.lock();
42 if (nodeAllocator_.size() >= NODE_ALLOCATOR_LIMIT) {
43 nodeAllocatorSpinlock_.unlock();
44 RS_OPTIONAL_TRACE_NAME("AddNodeToAllocator nodeAllocator is full.");
45 return false;
46 }
47 ptr->~RSRenderNode();
48 nodeAllocator_.push(ptr);
49 RS_LOGD("AddNodeToAllocator, pool size:%{public}zu", nodeAllocator_.size());
50 nodeAllocatorSpinlock_.unlock();
51 return true;
52 }
53
AddDrawableToAllocator(RSRenderNodeAllocator::DrawablePtr ptr)54 bool RSRenderNodeAllocator::AddDrawableToAllocator(RSRenderNodeAllocator::DrawablePtr ptr)
55 {
56 if (ptr == nullptr || ptr->GetNodeType() != RSRenderNodeType::CANVAS_NODE) {
57 return false;
58 }
59
60 if (ptr->GetDrawableType() != RSRenderNodeDrawableType::CANVAS_NODE_DRAWABLE) {
61 RS_LOGI("AddDrawableToAllocator, not canvas node drawable.");
62 return false;
63 }
64 drawableAllocatorSpinlock_.lock();
65 if (drawableAllocator_.size() >= DRAWABLE_ALLOCATOR_LIMIT) {
66 drawableAllocatorSpinlock_.unlock();
67 RS_OPTIONAL_TRACE_NAME("AddDrawableToAllocator drawableAllocator is full.");
68 return false;
69 }
70 ptr->~RSRenderNodeDrawableAdapter();
71 drawableAllocator_.push(ptr);
72 RS_LOGD("AddDrawableToAllocator, pool size:%{public}zu", drawableAllocator_.size());
73 drawableAllocatorSpinlock_.unlock();
74 return true;
75 }
76
CreateRSCanvasRenderNode(NodeId id,const std::weak_ptr<RSContext> & context,bool isTextureExportNode)77 std::shared_ptr<RSCanvasRenderNode> RSRenderNodeAllocator::CreateRSCanvasRenderNode(NodeId id,
78 const std::weak_ptr<RSContext>& context, bool isTextureExportNode)
79 {
80 nodeAllocatorSpinlock_.lock();
81 if (nodeAllocator_.empty()) {
82 nodeAllocatorSpinlock_.unlock();
83 RS_OPTIONAL_TRACE_NAME("CreateRSCanvasRenderNode nodeAllocator is empty.");
84 return std::shared_ptr<RSCanvasRenderNode>(new RSCanvasRenderNode(id,
85 context, isTextureExportNode), RSRenderNodeGC::NodeDestructor);
86 }
87 auto front = nodeAllocator_.front();
88 nodeAllocator_.pop();
89 nodeAllocatorSpinlock_.unlock();
90 RS_LOGD("CreateRSCanvasRenderNode in pool, pool size:%{public}zu, id:%{public}" PRIu64 "",
91 nodeAllocator_.size(), id);
92 return std::shared_ptr<RSCanvasRenderNode>(new (front)RSCanvasRenderNode(id,
93 context, isTextureExportNode), RSRenderNodeGC::NodeDestructor);
94 }
95
CreateRSRenderNodeDrawable(std::shared_ptr<const RSRenderNode> node,std::function<RSRenderNodeAllocator::DrawablePtr (std::shared_ptr<const RSRenderNode> node,RSRenderNodeAllocator::DrawablePtr front)> generator)96 RSRenderNodeAllocator::DrawablePtr RSRenderNodeAllocator::CreateRSRenderNodeDrawable(
97 std::shared_ptr<const RSRenderNode> node,
98 std::function<RSRenderNodeAllocator::DrawablePtr(std::shared_ptr<const RSRenderNode> node,
99 RSRenderNodeAllocator::DrawablePtr front)> generator)
100 {
101 drawableAllocatorSpinlock_.lock();
102 if (drawableAllocator_.empty()) {
103 drawableAllocatorSpinlock_.unlock();
104 RS_OPTIONAL_TRACE_NAME("CreateRSRenderNodeDrawable drawableAllocator is empty.");
105 return generator(node, nullptr);
106 }
107 auto front = drawableAllocator_.front();
108 drawableAllocator_.pop();
109 RS_LOGD("CreateRSRenderNodeDrawable in pool, pool size:%{public}zu", nodeAllocator_.size());
110 drawableAllocatorSpinlock_.unlock();
111 return generator(node, front);
112 }
113
114 } // namespace Rosen
115 } // namespace OHOS