blob: ea3871f235c17e73d1be3bd344ba7d8f896a6ddc [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>
Wei Wang976a6452021-06-11 15:26:00 -070027#include <processgroup/processgroup.h>
Ana Krulec9bc9dc62020-02-26 12:16:40 -080028#include <utils/Trace.h>
29
30#include "gl/GLESRenderEngine.h"
31
32using namespace std::chrono_literals;
33
34namespace android {
35namespace renderengine {
36namespace threaded {
37
Alec Mouri0d995102021-02-24 16:53:38 -080038std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory,
39 RenderEngineType type) {
40 return std::make_unique<RenderEngineThreaded>(std::move(factory), type);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080041}
42
Alec Mouri0d995102021-02-24 16:53:38 -080043RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type)
44 : RenderEngine(type) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080045 ATRACE_CALL();
46
47 std::lock_guard lockThread(mThreadMutex);
Ana Krulec15f7cf32020-05-12 11:57:42 -070048 mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080049}
50
51RenderEngineThreaded::~RenderEngineThreaded() {
Alec Mouri39d9cb72021-06-10 10:26:15 -070052 mRunning = false;
53 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080054
55 if (mThread.joinable()) {
56 mThread.join();
57 }
58}
59
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070060status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
61 static constexpr int kFifoPriority = 2;
62 static constexpr int kOtherPriority = 0;
63
64 struct sched_param param = {0};
65 int sched_policy;
66 if (enabled) {
67 sched_policy = SCHED_FIFO;
68 param.sched_priority = kFifoPriority;
69 } else {
70 sched_policy = SCHED_OTHER;
71 param.sched_priority = kOtherPriority;
72 }
73
74 if (sched_setscheduler(0, sched_policy, &param) != 0) {
75 return -errno;
76 }
77 return NO_ERROR;
78}
79
Ana Krulec9bc9dc62020-02-26 12:16:40 -080080// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070081void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080082 ATRACE_CALL();
83
Wei Wang976a6452021-06-11 15:26:00 -070084 if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) {
85 ALOGW("Failed to set render-engine task profile!");
86 }
87
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070088 if (setSchedFifo(true) != NO_ERROR) {
89 ALOGW("Couldn't set SCHED_FIFO");
Ana Krulec9bc9dc62020-02-26 12:16:40 -080090 }
91
Ana Krulec15f7cf32020-05-12 11:57:42 -070092 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080093
Ana Krulec9bc9dc62020-02-26 12:16:40 -080094 pthread_setname_np(pthread_self(), mThreadName);
95
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040096 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070097 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040098 mIsInitialized = true;
99 }
100 mInitializedCondition.notify_all();
101
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800102 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -0700103 const auto getNextTask = [this]() -> std::optional<Work> {
104 std::scoped_lock lock(mThreadMutex);
105 if (!mFunctionCalls.empty()) {
106 Work task = mFunctionCalls.front();
107 mFunctionCalls.pop();
108 return std::make_optional<Work>(task);
109 }
110 return std::nullopt;
111 };
112
113 const auto task = getNextTask();
114
115 if (task) {
116 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800117 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700118
119 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800120 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
121 return !mRunning || !mFunctionCalls.empty();
122 });
123 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400124
125 // we must release the RenderEngine on the thread that created it
126 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800127}
128
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400129void RenderEngineThreaded::waitUntilInitialized() const {
130 std::unique_lock<std::mutex> lock(mInitializedMutex);
131 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
132}
133
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700134std::future<void> RenderEngineThreaded::primeCache() {
135 const auto resultPromise = std::make_shared<std::promise<void>>();
136 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700137 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400138 // This function is designed so it can run asynchronously, so we do not need to wait
139 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800140 {
141 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700142 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800143 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700144 if (setSchedFifo(false) != NO_ERROR) {
145 ALOGW("Couldn't set SCHED_OTHER for primeCache");
146 }
147
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800148 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700149 resultPromise->set_value();
150
151 if (setSchedFifo(true) != NO_ERROR) {
152 ALOGW("Couldn't set SCHED_FIFO for primeCache");
153 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800154 });
155 }
156 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700157
158 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800159}
160
161void RenderEngineThreaded::dump(std::string& result) {
162 std::promise<std::string> resultPromise;
163 std::future<std::string> resultFuture = resultPromise.get_future();
164 {
165 std::lock_guard lock(mThreadMutex);
166 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
167 ATRACE_NAME("REThreaded::dump");
168 std::string localResult = result;
169 instance.dump(localResult);
170 resultPromise.set_value(std::move(localResult));
171 });
172 }
173 mCondition.notify_one();
174 // Note: This is an rvalue.
175 result.assign(resultFuture.get());
176}
177
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800178void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700179 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800180 std::promise<void> resultPromise;
181 std::future<void> resultFuture = resultPromise.get_future();
182 {
183 std::lock_guard lock(mThreadMutex);
184 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
185 ATRACE_NAME("REThreaded::genTextures");
186 instance.genTextures(count, names);
187 resultPromise.set_value();
188 });
189 }
190 mCondition.notify_one();
191 resultFuture.wait();
192}
193
194void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700195 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800196 std::promise<void> resultPromise;
197 std::future<void> resultFuture = resultPromise.get_future();
198 {
199 std::lock_guard lock(mThreadMutex);
200 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
201 ATRACE_NAME("REThreaded::deleteTextures");
202 instance.deleteTextures(count, names);
203 resultPromise.set_value();
204 });
205 }
206 mCondition.notify_one();
207 resultFuture.wait();
208}
209
Alec Mouria90a5702021-04-16 16:36:21 +0000210void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
211 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700212 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800213 // This function is designed so it can run asynchronously, so we do not need to wait
214 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800215 {
216 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800217 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000218 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
219 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800220 });
221 }
222 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800223}
224
Alec Mouria90a5702021-04-16 16:36:21 +0000225void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700226 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800227 // This function is designed so it can run asynchronously, so we do not need to wait
228 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800229 {
230 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800231 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000232 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
233 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800234 });
235 }
236 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800237}
238
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800239size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400240 waitUntilInitialized();
241 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800242}
243
244size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400245 waitUntilInitialized();
246 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800247}
248
249bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400250 waitUntilInitialized();
251 // ensure that useProtectedContext is not currently being changed by some
252 // other thread.
253 std::lock_guard lock(mThreadMutex);
254 return mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800255}
256
257bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400258 waitUntilInitialized();
259 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800260}
261
262bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
263 std::promise<bool> resultPromise;
264 std::future<bool> resultFuture = resultPromise.get_future();
265 {
266 std::lock_guard lock(mThreadMutex);
267 mFunctionCalls.push(
268 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
269 ATRACE_NAME("REThreaded::useProtectedContext");
270 bool returnValue = instance.useProtectedContext(useProtectedContext);
271 resultPromise.set_value(returnValue);
272 });
273 }
274 mCondition.notify_one();
275 return resultFuture.get();
276}
277
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400278void RenderEngineThreaded::cleanupPostRender() {
279 if (canSkipPostRenderCleanup()) {
280 return;
281 }
282
283 // This function is designed so it can run asynchronously, so we do not need to wait
284 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800285 {
286 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400287 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
288 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
289 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800290 });
291 }
292 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400293}
294
295bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
296 waitUntilInitialized();
297 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800298}
299
300status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
301 const std::vector<const LayerSettings*>& layers,
Alec Mouria90a5702021-04-16 16:36:21 +0000302 const std::shared_ptr<ExternalTexture>& buffer,
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800303 const bool useFramebufferCache,
304 base::unique_fd&& bufferFence,
305 base::unique_fd* drawFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700306 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800307 std::promise<status_t> resultPromise;
308 std::future<status_t> resultFuture = resultPromise.get_future();
309 {
310 std::lock_guard lock(mThreadMutex);
311 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
312 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
313 ATRACE_NAME("REThreaded::drawLayers");
314 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
315 std::move(bufferFence), drawFence);
316 resultPromise.set_value(status);
317 });
318 }
319 mCondition.notify_one();
320 return resultFuture.get();
321}
322
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200323void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700324 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400325 // This function is designed so it can run asynchronously, so we do not need to wait
326 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200327 {
328 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400329 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200330 ATRACE_NAME("REThreaded::cleanFramebufferCache");
331 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200332 });
333 }
334 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200335}
336
Alec Mourid6f09462020-12-07 11:18:17 -0800337int RenderEngineThreaded::getContextPriority() {
338 std::promise<int> resultPromise;
339 std::future<int> resultFuture = resultPromise.get_future();
340 {
341 std::lock_guard lock(mThreadMutex);
342 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
343 ATRACE_NAME("REThreaded::getContextPriority");
344 int priority = instance.getContextPriority();
345 resultPromise.set_value(priority);
346 });
347 }
348 mCondition.notify_one();
349 return resultFuture.get();
350}
351
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500352bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400353 waitUntilInitialized();
354 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500355}
356
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400357void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400358 // This function is designed so it can run asynchronously, so we do not need to wait
359 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400360 {
361 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400362 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400363 ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
364 instance.onPrimaryDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400365 });
366 }
367 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400368}
369
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800370} // namespace threaded
371} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700372} // namespace android