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