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