• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "pixel_map_program_manager.h"
17 #include <memory>
18 
19 #undef LOG_TAG
20 #define LOG_TAG "PixelMapProgramManager"
21 
22 namespace OHOS {
23 namespace Media {
24 static const int MAX_GL_INSTANCE_NUM = 8;
25 constexpr int32_t MAX_CONTEXT_EXPIRED_TIME_SEC = 120;
26 constexpr int32_t MIN_CONTEXT_EXPIRED_TIME_SEC = 10;
27 static vector<PixelMapGLPostProcProgram *> g_availInstances;
28 static std::mutex g_contextMutex;
29 static std::mutex g_shaderBuildMutex;
30 static std::atomic<int> g_nowInstanceNum = 0;
31 static std::atomic<bool> g_destroyThreadIsRunning = false;
32 static std::atomic<long> g_lastTouchInstanceTime = 0;
33 static std::condition_variable g_dataCond;
34 
PixelMapProgramManager()35 PixelMapProgramManager::PixelMapProgramManager() noexcept
36 {
37 }
38 
~PixelMapProgramManager()39 PixelMapProgramManager::~PixelMapProgramManager() noexcept
40 {
41 }
42 
GetInstance()43 PixelMapProgramManager &PixelMapProgramManager::GetInstance() noexcept
44 {
45     static PixelMapProgramManager instance;
46     return instance;
47 }
48 
GetProgram()49 PixelMapGLPostProcProgram* PixelMapProgramManager::GetProgram()
50 {
51     ImageTrace imageTrace("PixelMapProgramManager::GetProgram");
52     PixelMapGLPostProcProgram *program = nullptr;
53     std::unique_lock<std::mutex> locker(g_contextMutex);
54     struct timespec tv;
55     clock_gettime(CLOCK_MONOTONIC, &tv);
56     g_lastTouchInstanceTime = tv.tv_sec;
57     if (g_availInstances.size() > 0) {
58         program = g_availInstances.back();
59         g_availInstances.pop_back();
60     }
61     if (program != nullptr) {
62         return program;
63     }
64     if (g_nowInstanceNum >= MAX_GL_INSTANCE_NUM) {
65         int num = g_nowInstanceNum;
66         while (program == nullptr) {
67             if (g_dataCond.wait_for(locker, std::chrono::seconds(1)) == std::cv_status::timeout) {
68                 IMAGE_LOGE("slr_gpu %{public}s GetInstance failed for wait timeout(%{public}d)", __func__, num);
69                 return nullptr;
70             }
71             if (g_availInstances.size() > 0) {
72                 program = g_availInstances.back();
73                 g_availInstances.pop_back();
74             }
75         }
76     } else {
77         g_nowInstanceNum++;
78         locker.unlock();
79         program = new PixelMapGLPostProcProgram();
80         if (!program->Init()) {
81             std::unique_lock<std::mutex> locker(g_contextMutex);
82             g_nowInstanceNum--;
83             delete program;
84             program = nullptr;
85         } else {
86             int num = g_nowInstanceNum;
87             IMAGE_LOGI("slr_gpu %{public}s new instance(%{public}d)", __func__, num);
88         }
89     }
90     return program;
91 }
92 
ReleaseInstance(PixelMapGLPostProcProgram * program)93 void PixelMapProgramManager::ReleaseInstance(PixelMapGLPostProcProgram *program)
94 {
95     {
96         std::unique_lock<std::mutex> locker(g_contextMutex);
97         g_availInstances.push_back(program);
98     }
99     g_dataCond.notify_one();
100     bool oldValue = false;
101     if (g_destroyThreadIsRunning.compare_exchange_weak(oldValue, true, std::memory_order_relaxed)) {
102         std::thread destroyInstanceThread(PixelMapProgramManager::DestoryInstanceThreadFunc);
103         destroyInstanceThread.detach();
104     }
105 }
106 
DestoryInstanceThreadFunc()107 void PixelMapProgramManager::DestoryInstanceThreadFunc()
108 {
109     while (g_nowInstanceNum != 0) {
110         struct timespec tv;
111         clock_gettime(CLOCK_MONOTONIC, &tv);
112         long expiredTime = tv.tv_sec - g_lastTouchInstanceTime;
113         if (expiredTime < 0) {
114             expiredTime = 0;
115         }
116 
117         if (g_nowInstanceNum > 1) {
118             if (expiredTime < MIN_CONTEXT_EXPIRED_TIME_SEC * (MAX_GL_INSTANCE_NUM + 1 - g_nowInstanceNum)) {
119                 sleep(MIN_CONTEXT_EXPIRED_TIME_SEC);
120                 continue;
121             }
122         } else {
123             if (expiredTime < MAX_CONTEXT_EXPIRED_TIME_SEC) {
124                 sleep(MAX_CONTEXT_EXPIRED_TIME_SEC);
125                 continue;
126             }
127         }
128         DestroyOneInstance();
129     }
130     g_destroyThreadIsRunning = false;
131 }
132 
DestroyOneInstance()133 void PixelMapProgramManager::DestroyOneInstance()
134 {
135     std::unique_lock<std::mutex> locker(g_contextMutex);
136     PixelMapGLPostProcProgram *instance = nullptr;
137     if (g_availInstances.size() > 0) {
138         instance = g_availInstances.back();
139         g_availInstances.pop_back();
140         g_nowInstanceNum--;
141         if (instance != nullptr) delete instance;
142     }
143     int num = g_nowInstanceNum;
144     IMAGE_LOGE("slr_gpu %{public}s destroy opengl context(%{public}d)", __func__, num);
145 }
146 
BuildShader()147 bool PixelMapProgramManager::BuildShader()
148 {
149     return PixelMapGLPostProcProgram::BuildShader();
150 }
151 
ExecutProgram(PixelMapGLPostProcProgram * program)152 bool PixelMapProgramManager::ExecutProgram(PixelMapGLPostProcProgram *program)
153 {
154     if (program == nullptr) {
155         IMAGE_LOGE("slr_gpu ExecutProgram program is nullptr");
156         return false;
157     }
158     bool ret = program->Execute();
159     if (!ret) {
160         IMAGE_LOGE("slr_gpu ExecutProgram failed");
161         {
162             std::unique_lock<std::mutex> locker(g_contextMutex);
163             g_nowInstanceNum--;
164         }
165         delete program;
166         program = nullptr;
167         return false;
168     }
169     ReleaseInstance(program);
170     return ret;
171 }
172 } // namespace Media
173 } // namespace OHOS