1 /*
2 * Copyright (c) 2023 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 #include "pipeline/sk_resource_manager.h"
16
17 #include "rs_trace.h"
18 #include "platform/common/rs_log.h"
19 #include "platform/common/rs_system_properties.h"
20 #include "pipeline/rs_task_dispatcher.h"
21
22 namespace OHOS::Rosen {
23 #ifdef ROSEN_OHOS
24 constexpr uint32_t MAX_CHECK_SIZE = 20; // empirical value
25 #endif
Instance()26 SKResourceManager& SKResourceManager::Instance()
27 {
28 static SKResourceManager instance;
29 return instance;
30 }
31
32 // LCOV_EXCL_START
HoldResource(const std::shared_ptr<Drawing::Image> & img)33 void SKResourceManager::HoldResource(const std::shared_ptr<Drawing::Image> &img)
34 {
35 #ifdef ROSEN_OHOS
36 if (RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
37 return;
38 }
39 auto tid = gettid();
40 if (!RSTaskDispatcher::GetInstance().HasRegisteredTask(tid)) {
41 return;
42 }
43 std::scoped_lock<std::recursive_mutex> lock(mutex_);
44 if (images_.find(tid) != images_.end()) {
45 images_[tid]->HoldResource(img);
46 } else {
47 std::shared_ptr<Drawing::ResourceHolder> holder = std::make_shared<Drawing::ResourceHolder>();
48 holder->HoldResource(img);
49 images_.emplace(tid, holder);
50 }
51 #endif
52 }
53
HoldResource(std::shared_ptr<Drawing::Surface> surface)54 void SKResourceManager::HoldResource(std::shared_ptr<Drawing::Surface> surface)
55 {
56 #ifdef ROSEN_OHOS
57 if (RSSystemProperties::GetGpuApiType() == GpuApiType::DDGR) {
58 return;
59 }
60 auto tid = gettid();
61 if (!RSTaskDispatcher::GetInstance().HasRegisteredTask(tid)) {
62 return;
63 }
64 std::scoped_lock<std::recursive_mutex> lock(mutex_);
65 if (std::any_of(skSurfaces_[tid].cbegin(), skSurfaces_[tid].cend(),
66 [&surface](const std::shared_ptr<Drawing::Surface>& skSurface) {return skSurface.get() == surface.get(); })) {
67 return;
68 }
69 skSurfaces_[tid].push_back(surface);
70 #endif
71 }
72 // LCOV_EXCL_STOP
73
74 #if defined(RS_ENABLE_GL) || defined(RS_ENABLE_VK)
DeleteSharedTextureContext(void * context)75 void SKResourceManager::DeleteSharedTextureContext(void* context)
76 {
77 SharedTextureContext* cleanupHelper = static_cast<SharedTextureContext*>(context);
78 if (cleanupHelper != nullptr) {
79 delete cleanupHelper;
80 cleanupHelper = nullptr;
81 }
82 }
83 #endif
84
HaveReleaseableResourceCheck(const std::list<std::shared_ptr<Drawing::Surface>> & list)85 bool SKResourceManager::HaveReleaseableResourceCheck(const std::list<std::shared_ptr<Drawing::Surface>> &list)
86 {
87 #ifdef ROSEN_OHOS
88 if (list.empty()) {
89 return false;
90 }
91 if (list.size() > MAX_CHECK_SIZE) {
92 /* to avoid this function taking too long, return true directly,
93 * which means resources may need to be released
94 */
95 return true;
96 }
97 for (auto& surface : list) {
98 if (surface.unique()) {
99 return true;
100 }
101 }
102 return false;
103 #else
104 return false;
105 #endif
106 }
107
108
ReleaseResource()109 void SKResourceManager::ReleaseResource()
110 {
111 #ifdef ROSEN_OHOS
112 RS_TRACE_FUNC();
113 std::scoped_lock<std::recursive_mutex> lock(mutex_);
114 for (auto& images : images_) {
115 if (images.second->HaveReleaseableResourceCheck()) {
116 RSTaskDispatcher::GetInstance().PostTask(images.first, [this]() {
117 auto tid = gettid();
118 std::scoped_lock<std::recursive_mutex> lock(mutex_);
119 images_[tid]->ReleaseResource();
120 });
121 }
122 }
123
124 for (auto& skSurface : skSurfaces_) {
125 if (HaveReleaseableResourceCheck(skSurface.second)) {
126 RSTaskDispatcher::GetInstance().PostTask(skSurface.first, [this]() {
127 auto tid = gettid();
128 std::scoped_lock<std::recursive_mutex> lock(mutex_);
129 size_t size = skSurfaces_[tid].size();
130 while (size-- > 0) {
131 #ifdef RS_ENABLE_PREFETCH
132 size_t prefetchStep = 2;
133 if (size > prefetchStep) {
134 __builtin_prefetch(&*(++(++skSurfaces_[tid].begin())), 0, 1);
135 }
136 #endif
137 auto surface = skSurfaces_[tid].front();
138 skSurfaces_[tid].pop_front();
139 if (surface == nullptr) {
140 continue;
141 }
142 if (surface.unique()) {
143 surface = nullptr;
144 } else {
145 skSurfaces_[tid].push_back(surface);
146 }
147 }
148 });
149 }
150 }
151 #endif
152 }
153 } // OHOS::Rosen