blob: ad6171874ddf50685c6697319a04f9a339240c83 [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
Ana Krulec15f7cf32020-05-12 11:57:42 -070037std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory) {
38 return std::make_unique<RenderEngineThreaded>(std::move(factory));
Ana Krulec9bc9dc62020-02-26 12:16:40 -080039}
40
Ana Krulec15f7cf32020-05-12 11:57:42 -070041RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080042 ATRACE_CALL();
43
44 std::lock_guard lockThread(mThreadMutex);
Ana Krulec15f7cf32020-05-12 11:57:42 -070045 mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080046}
47
48RenderEngineThreaded::~RenderEngineThreaded() {
49 {
50 std::lock_guard lock(mThreadMutex);
51 mRunning = false;
52 mCondition.notify_one();
53 }
54
55 if (mThread.joinable()) {
56 mThread.join();
57 }
58}
59
60// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070061void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080062 ATRACE_CALL();
63
64 struct sched_param param = {0};
65 param.sched_priority = 2;
66 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
67 ALOGE("Couldn't set SCHED_FIFO");
68 }
69
Ana Krulec15f7cf32020-05-12 11:57:42 -070070 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080071
72 std::unique_lock<std::mutex> lock(mThreadMutex);
73 pthread_setname_np(pthread_self(), mThreadName);
74
75 while (mRunning) {
76 if (!mFunctionCalls.empty()) {
77 auto task = mFunctionCalls.front();
78 mFunctionCalls.pop();
79 task(*mRenderEngine);
80 }
81 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
82 return !mRunning || !mFunctionCalls.empty();
83 });
84 }
85}
86
87void RenderEngineThreaded::primeCache() const {
88 std::promise<void> resultPromise;
89 std::future<void> resultFuture = resultPromise.get_future();
90 {
91 std::lock_guard lock(mThreadMutex);
92 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
93 ATRACE_NAME("REThreaded::primeCache");
94 instance.primeCache();
95 resultPromise.set_value();
96 });
97 }
98 mCondition.notify_one();
99 resultFuture.wait();
100}
101
102void RenderEngineThreaded::dump(std::string& result) {
103 std::promise<std::string> resultPromise;
104 std::future<std::string> resultFuture = resultPromise.get_future();
105 {
106 std::lock_guard lock(mThreadMutex);
107 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
108 ATRACE_NAME("REThreaded::dump");
109 std::string localResult = result;
110 instance.dump(localResult);
111 resultPromise.set_value(std::move(localResult));
112 });
113 }
114 mCondition.notify_one();
115 // Note: This is an rvalue.
116 result.assign(resultFuture.get());
117}
118
Ana Krulec15f7cf32020-05-12 11:57:42 -0700119bool RenderEngineThreaded::useNativeFenceSync() const {
120 std::promise<bool> resultPromise;
121 std::future<bool> resultFuture = resultPromise.get_future();
122 {
123 std::lock_guard lock(mThreadMutex);
124 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& /*instance*/) {
125 ATRACE_NAME("REThreaded::useNativeFenceSync");
126 bool returnValue = SyncFeatures::getInstance().useNativeFenceSync();
127 resultPromise.set_value(returnValue);
128 });
129 }
130 mCondition.notify_one();
131 return resultFuture.get();
132}
133
134bool RenderEngineThreaded::useWaitSync() const {
135 std::promise<bool> resultPromise;
136 std::future<bool> resultFuture = resultPromise.get_future();
137 {
138 std::lock_guard lock(mThreadMutex);
139 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& /*instance*/) {
140 ATRACE_NAME("REThreaded::useWaitSync");
141 bool returnValue = SyncFeatures::getInstance().useWaitSync();
142 resultPromise.set_value(returnValue);
143 });
144 }
145 mCondition.notify_one();
146 return resultFuture.get();
147}
148
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800149void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
150 std::promise<void> resultPromise;
151 std::future<void> resultFuture = resultPromise.get_future();
152 {
153 std::lock_guard lock(mThreadMutex);
154 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
155 ATRACE_NAME("REThreaded::genTextures");
156 instance.genTextures(count, names);
157 resultPromise.set_value();
158 });
159 }
160 mCondition.notify_one();
161 resultFuture.wait();
162}
163
164void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
165 std::promise<void> resultPromise;
166 std::future<void> resultFuture = resultPromise.get_future();
167 {
168 std::lock_guard lock(mThreadMutex);
169 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
170 ATRACE_NAME("REThreaded::deleteTextures");
171 instance.deleteTextures(count, names);
172 resultPromise.set_value();
173 });
174 }
175 mCondition.notify_one();
176 resultFuture.wait();
177}
178
179void RenderEngineThreaded::bindExternalTextureImage(uint32_t texName, const Image& image) {
180 std::promise<void> resultPromise;
181 std::future<void> resultFuture = resultPromise.get_future();
182 {
183 std::lock_guard lock(mThreadMutex);
184 mFunctionCalls.push(
185 [&resultPromise, texName, &image](renderengine::RenderEngine& instance) {
186 ATRACE_NAME("REThreaded::bindExternalTextureImage");
187 instance.bindExternalTextureImage(texName, image);
188 resultPromise.set_value();
189 });
190 }
191 mCondition.notify_one();
192 resultFuture.wait();
193}
194
195status_t RenderEngineThreaded::bindExternalTextureBuffer(uint32_t texName,
196 const sp<GraphicBuffer>& buffer,
197 const sp<Fence>& fence) {
198 std::promise<status_t> resultPromise;
199 std::future<status_t> resultFuture = resultPromise.get_future();
200 {
201 std::lock_guard lock(mThreadMutex);
202 mFunctionCalls.push(
203 [&resultPromise, texName, &buffer, &fence](renderengine::RenderEngine& instance) {
204 ATRACE_NAME("REThreaded::bindExternalTextureBuffer");
205 status_t status = instance.bindExternalTextureBuffer(texName, buffer, fence);
206 resultPromise.set_value(status);
207 });
208 }
209 mCondition.notify_one();
210 return resultFuture.get();
211}
212
213void RenderEngineThreaded::cacheExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
214 std::promise<void> resultPromise;
215 std::future<void> resultFuture = resultPromise.get_future();
216 {
217 std::lock_guard lock(mThreadMutex);
218 mFunctionCalls.push([&resultPromise, &buffer](renderengine::RenderEngine& instance) {
219 ATRACE_NAME("REThreaded::cacheExternalTextureBuffer");
220 instance.cacheExternalTextureBuffer(buffer);
221 resultPromise.set_value();
222 });
223 }
224 mCondition.notify_one();
225 resultFuture.wait();
226}
227
228void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) {
229 std::promise<void> resultPromise;
230 std::future<void> resultFuture = resultPromise.get_future();
231 {
232 std::lock_guard lock(mThreadMutex);
233 mFunctionCalls.push([&resultPromise, &bufferId](renderengine::RenderEngine& instance) {
234 ATRACE_NAME("REThreaded::unbindExternalTextureBuffer");
235 instance.unbindExternalTextureBuffer(bufferId);
236 resultPromise.set_value();
237 });
238 }
239 mCondition.notify_one();
240 resultFuture.wait();
241}
242
243status_t RenderEngineThreaded::bindFrameBuffer(Framebuffer* framebuffer) {
244 std::promise<status_t> resultPromise;
245 std::future<status_t> resultFuture = resultPromise.get_future();
246 {
247 std::lock_guard lock(mThreadMutex);
248 mFunctionCalls.push([&resultPromise, &framebuffer](renderengine::RenderEngine& instance) {
249 ATRACE_NAME("REThreaded::bindFrameBuffer");
250 status_t status = instance.bindFrameBuffer(framebuffer);
251 resultPromise.set_value(status);
252 });
253 }
254 mCondition.notify_one();
255 return resultFuture.get();
256}
257
258void RenderEngineThreaded::unbindFrameBuffer(Framebuffer* framebuffer) {
259 std::promise<void> resultPromise;
260 std::future<void> resultFuture = resultPromise.get_future();
261 {
262 std::lock_guard lock(mThreadMutex);
263 mFunctionCalls.push([&resultPromise, &framebuffer](renderengine::RenderEngine& instance) {
264 ATRACE_NAME("REThreaded::unbindFrameBuffer");
265 instance.unbindFrameBuffer(framebuffer);
266 resultPromise.set_value();
267 });
268 }
269 mCondition.notify_one();
270 resultFuture.wait();
271}
272
273size_t RenderEngineThreaded::getMaxTextureSize() const {
274 std::promise<size_t> resultPromise;
275 std::future<size_t> resultFuture = resultPromise.get_future();
276 {
277 std::lock_guard lock(mThreadMutex);
278 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
279 ATRACE_NAME("REThreaded::getMaxTextureSize");
280 size_t size = instance.getMaxTextureSize();
281 resultPromise.set_value(size);
282 });
283 }
284 mCondition.notify_one();
285 return resultFuture.get();
286}
287
288size_t RenderEngineThreaded::getMaxViewportDims() const {
289 std::promise<size_t> resultPromise;
290 std::future<size_t> resultFuture = resultPromise.get_future();
291 {
292 std::lock_guard lock(mThreadMutex);
293 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
294 ATRACE_NAME("REThreaded::getMaxViewportDims");
295 size_t size = instance.getMaxViewportDims();
296 resultPromise.set_value(size);
297 });
298 }
299 mCondition.notify_one();
300 return resultFuture.get();
301}
302
303bool RenderEngineThreaded::isProtected() const {
304 std::promise<bool> resultPromise;
305 std::future<bool> resultFuture = resultPromise.get_future();
306 {
307 std::lock_guard lock(mThreadMutex);
308 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
309 ATRACE_NAME("REThreaded::isProtected");
310 bool returnValue = instance.isProtected();
311 resultPromise.set_value(returnValue);
312 });
313 }
314 mCondition.notify_one();
315 return resultFuture.get();
316}
317
318bool RenderEngineThreaded::supportsProtectedContent() const {
319 std::promise<bool> resultPromise;
320 std::future<bool> resultFuture = resultPromise.get_future();
321 {
322 std::lock_guard lock(mThreadMutex);
323 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
324 ATRACE_NAME("REThreaded::supportsProtectedContent");
325 bool returnValue = instance.supportsProtectedContent();
326 resultPromise.set_value(returnValue);
327 });
328 }
329 mCondition.notify_one();
330 return resultFuture.get();
331}
332
333bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
334 std::promise<bool> resultPromise;
335 std::future<bool> resultFuture = resultPromise.get_future();
336 {
337 std::lock_guard lock(mThreadMutex);
338 mFunctionCalls.push(
339 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
340 ATRACE_NAME("REThreaded::useProtectedContext");
341 bool returnValue = instance.useProtectedContext(useProtectedContext);
342 resultPromise.set_value(returnValue);
343 });
344 }
345 mCondition.notify_one();
346 return resultFuture.get();
347}
348
349Framebuffer* RenderEngineThreaded::getFramebufferForDrawing() {
350 std::promise<Framebuffer*> resultPromise;
351 std::future<Framebuffer*> resultFuture = resultPromise.get_future();
352 {
353 std::lock_guard lock(mThreadMutex);
354 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
355 ATRACE_NAME("REThreaded::getFramebufferForDrawing");
356 Framebuffer* framebuffer = instance.getFramebufferForDrawing();
357 resultPromise.set_value(framebuffer);
358 });
359 }
360 mCondition.notify_one();
361 return resultFuture.get();
362}
363
364bool RenderEngineThreaded::cleanupPostRender() {
365 std::promise<bool> resultPromise;
366 std::future<bool> resultFuture = resultPromise.get_future();
367 {
368 std::lock_guard lock(mThreadMutex);
369 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
370 ATRACE_NAME("REThreaded::cleanupPostRender");
371 bool returnValue = instance.cleanupPostRender();
372 resultPromise.set_value(returnValue);
373 });
374 }
375 mCondition.notify_one();
376 return resultFuture.get();
377}
378
379status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
380 const std::vector<const LayerSettings*>& layers,
381 const sp<GraphicBuffer>& buffer,
382 const bool useFramebufferCache,
383 base::unique_fd&& bufferFence,
384 base::unique_fd* drawFence) {
385 std::promise<status_t> resultPromise;
386 std::future<status_t> resultFuture = resultPromise.get_future();
387 {
388 std::lock_guard lock(mThreadMutex);
389 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
390 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
391 ATRACE_NAME("REThreaded::drawLayers");
392 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
393 std::move(bufferFence), drawFence);
394 resultPromise.set_value(status);
395 });
396 }
397 mCondition.notify_one();
398 return resultFuture.get();
399}
400
401} // namespace threaded
402} // namespace renderengine
403} // namespace android