blob: 7c7d165c04fe6331b7c70f748df9e8e0bcdbc975 [file] [log] [blame]
Ana Krulec9bc9dc62020-02-26 12:16:40 -08001/*
2 * Copyright 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define ATRACE_TAG ATRACE_TAG_GRAPHICS
18
19#include "RenderEngineThreaded.h"
20
21#include <sched.h>
22#include <chrono>
23#include <future>
24
25#include <android-base/stringprintf.h>
Ana Krulec15f7cf32020-05-12 11:57:42 -070026#include <private/gui/SyncFeatures.h>
Ana Krulec9bc9dc62020-02-26 12:16:40 -080027#include <utils/Trace.h>
28
29#include "gl/GLESRenderEngine.h"
30
31using namespace std::chrono_literals;
32
33namespace android {
34namespace renderengine {
35namespace threaded {
36
Alec Mouri0d995102021-02-24 16:53:38 -080037std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory,
38 RenderEngineType type) {
39 return std::make_unique<RenderEngineThreaded>(std::move(factory), type);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080040}
41
Alec Mouri0d995102021-02-24 16:53:38 -080042RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type)
43 : RenderEngine(type) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080044 ATRACE_CALL();
45
46 std::lock_guard lockThread(mThreadMutex);
Ana Krulec15f7cf32020-05-12 11:57:42 -070047 mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080048}
49
50RenderEngineThreaded::~RenderEngineThreaded() {
51 {
52 std::lock_guard lock(mThreadMutex);
53 mRunning = false;
54 mCondition.notify_one();
55 }
56
57 if (mThread.joinable()) {
58 mThread.join();
59 }
60}
61
62// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070063void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080064 ATRACE_CALL();
65
66 struct sched_param param = {0};
67 param.sched_priority = 2;
68 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
69 ALOGE("Couldn't set SCHED_FIFO");
70 }
71
Ana Krulec15f7cf32020-05-12 11:57:42 -070072 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080073
74 std::unique_lock<std::mutex> lock(mThreadMutex);
75 pthread_setname_np(pthread_self(), mThreadName);
76
77 while (mRunning) {
78 if (!mFunctionCalls.empty()) {
79 auto task = mFunctionCalls.front();
80 mFunctionCalls.pop();
81 task(*mRenderEngine);
82 }
83 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
84 return !mRunning || !mFunctionCalls.empty();
85 });
86 }
87}
88
89void RenderEngineThreaded::primeCache() const {
90 std::promise<void> resultPromise;
91 std::future<void> resultFuture = resultPromise.get_future();
92 {
93 std::lock_guard lock(mThreadMutex);
94 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
95 ATRACE_NAME("REThreaded::primeCache");
96 instance.primeCache();
97 resultPromise.set_value();
98 });
99 }
100 mCondition.notify_one();
101 resultFuture.wait();
102}
103
104void RenderEngineThreaded::dump(std::string& result) {
105 std::promise<std::string> resultPromise;
106 std::future<std::string> resultFuture = resultPromise.get_future();
107 {
108 std::lock_guard lock(mThreadMutex);
109 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
110 ATRACE_NAME("REThreaded::dump");
111 std::string localResult = result;
112 instance.dump(localResult);
113 resultPromise.set_value(std::move(localResult));
114 });
115 }
116 mCondition.notify_one();
117 // Note: This is an rvalue.
118 result.assign(resultFuture.get());
119}
120
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800121void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
122 std::promise<void> resultPromise;
123 std::future<void> resultFuture = resultPromise.get_future();
124 {
125 std::lock_guard lock(mThreadMutex);
126 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
127 ATRACE_NAME("REThreaded::genTextures");
128 instance.genTextures(count, names);
129 resultPromise.set_value();
130 });
131 }
132 mCondition.notify_one();
133 resultFuture.wait();
134}
135
136void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
137 std::promise<void> resultPromise;
138 std::future<void> resultFuture = resultPromise.get_future();
139 {
140 std::lock_guard lock(mThreadMutex);
141 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
142 ATRACE_NAME("REThreaded::deleteTextures");
143 instance.deleteTextures(count, names);
144 resultPromise.set_value();
145 });
146 }
147 mCondition.notify_one();
148 resultFuture.wait();
149}
150
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800151void RenderEngineThreaded::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ana Krulecdfec8f52021-01-13 12:51:47 -0800152 // This function is designed so it can run asynchronously, so we do not need to wait
153 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800154 {
155 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800156 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800157 ATRACE_NAME("REThreaded::cacheExternalTextureBuffer");
158 instance.cacheExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800159 });
160 }
161 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800162}
163
164void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) {
Ana Krulecdfec8f52021-01-13 12:51:47 -0800165 // This function is designed so it can run asynchronously, so we do not need to wait
166 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800167 {
168 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800169 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800170 ATRACE_NAME("REThreaded::unbindExternalTextureBuffer");
171 instance.unbindExternalTextureBuffer(bufferId);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800172 });
173 }
174 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800175}
176
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800177size_t RenderEngineThreaded::getMaxTextureSize() const {
178 std::promise<size_t> resultPromise;
179 std::future<size_t> resultFuture = resultPromise.get_future();
180 {
181 std::lock_guard lock(mThreadMutex);
182 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
183 ATRACE_NAME("REThreaded::getMaxTextureSize");
184 size_t size = instance.getMaxTextureSize();
185 resultPromise.set_value(size);
186 });
187 }
188 mCondition.notify_one();
189 return resultFuture.get();
190}
191
192size_t RenderEngineThreaded::getMaxViewportDims() const {
193 std::promise<size_t> resultPromise;
194 std::future<size_t> resultFuture = resultPromise.get_future();
195 {
196 std::lock_guard lock(mThreadMutex);
197 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
198 ATRACE_NAME("REThreaded::getMaxViewportDims");
199 size_t size = instance.getMaxViewportDims();
200 resultPromise.set_value(size);
201 });
202 }
203 mCondition.notify_one();
204 return resultFuture.get();
205}
206
207bool RenderEngineThreaded::isProtected() const {
208 std::promise<bool> resultPromise;
209 std::future<bool> resultFuture = resultPromise.get_future();
210 {
211 std::lock_guard lock(mThreadMutex);
212 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
213 ATRACE_NAME("REThreaded::isProtected");
214 bool returnValue = instance.isProtected();
215 resultPromise.set_value(returnValue);
216 });
217 }
218 mCondition.notify_one();
219 return resultFuture.get();
220}
221
222bool RenderEngineThreaded::supportsProtectedContent() const {
223 std::promise<bool> resultPromise;
224 std::future<bool> resultFuture = resultPromise.get_future();
225 {
226 std::lock_guard lock(mThreadMutex);
227 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
228 ATRACE_NAME("REThreaded::supportsProtectedContent");
229 bool returnValue = instance.supportsProtectedContent();
230 resultPromise.set_value(returnValue);
231 });
232 }
233 mCondition.notify_one();
234 return resultFuture.get();
235}
236
237bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
238 std::promise<bool> resultPromise;
239 std::future<bool> resultFuture = resultPromise.get_future();
240 {
241 std::lock_guard lock(mThreadMutex);
242 mFunctionCalls.push(
243 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
244 ATRACE_NAME("REThreaded::useProtectedContext");
245 bool returnValue = instance.useProtectedContext(useProtectedContext);
246 resultPromise.set_value(returnValue);
247 });
248 }
249 mCondition.notify_one();
250 return resultFuture.get();
251}
252
Alec Mouri368e1582020-08-13 10:14:29 -0700253bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800254 std::promise<bool> resultPromise;
255 std::future<bool> resultFuture = resultPromise.get_future();
256 {
257 std::lock_guard lock(mThreadMutex);
Alec Mouri368e1582020-08-13 10:14:29 -0700258 mFunctionCalls.push([&resultPromise, mode](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800259 ATRACE_NAME("REThreaded::cleanupPostRender");
Alec Mouri368e1582020-08-13 10:14:29 -0700260 bool returnValue = instance.cleanupPostRender(mode);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800261 resultPromise.set_value(returnValue);
262 });
263 }
264 mCondition.notify_one();
265 return resultFuture.get();
266}
267
268status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
269 const std::vector<const LayerSettings*>& layers,
270 const sp<GraphicBuffer>& buffer,
271 const bool useFramebufferCache,
272 base::unique_fd&& bufferFence,
273 base::unique_fd* drawFence) {
274 std::promise<status_t> resultPromise;
275 std::future<status_t> resultFuture = resultPromise.get_future();
276 {
277 std::lock_guard lock(mThreadMutex);
278 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
279 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
280 ATRACE_NAME("REThreaded::drawLayers");
281 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
282 std::move(bufferFence), drawFence);
283 resultPromise.set_value(status);
284 });
285 }
286 mCondition.notify_one();
287 return resultFuture.get();
288}
289
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200290void RenderEngineThreaded::cleanFramebufferCache() {
291 std::promise<void> resultPromise;
292 std::future<void> resultFuture = resultPromise.get_future();
293 {
294 std::lock_guard lock(mThreadMutex);
295 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
296 ATRACE_NAME("REThreaded::cleanFramebufferCache");
297 instance.cleanFramebufferCache();
298 resultPromise.set_value();
299 });
300 }
301 mCondition.notify_one();
302 resultFuture.wait();
303}
304
Alec Mourid6f09462020-12-07 11:18:17 -0800305int RenderEngineThreaded::getContextPriority() {
306 std::promise<int> resultPromise;
307 std::future<int> resultFuture = resultPromise.get_future();
308 {
309 std::lock_guard lock(mThreadMutex);
310 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
311 ATRACE_NAME("REThreaded::getContextPriority");
312 int priority = instance.getContextPriority();
313 resultPromise.set_value(priority);
314 });
315 }
316 mCondition.notify_one();
317 return resultFuture.get();
318}
319
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500320bool RenderEngineThreaded::supportsBackgroundBlur() {
321 std::promise<bool> resultPromise;
322 std::future<bool> resultFuture = resultPromise.get_future();
323 {
324 std::lock_guard lock(mThreadMutex);
325 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
326 ATRACE_NAME("REThreaded::supportsBackgroundBlur");
327 bool returnValue = instance.supportsBackgroundBlur();
328 resultPromise.set_value(returnValue);
329 });
330 }
331 mCondition.notify_one();
332 return resultFuture.get();
333}
334
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800335} // namespace threaded
336} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700337} // namespace android