blob: 3d446e8e72f02275431e8c4fe6c8b43a73c2fdce [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();
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -040093 mIsProtected = mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080094
Ana Krulec9bc9dc62020-02-26 12:16:40 -080095 pthread_setname_np(pthread_self(), mThreadName);
96
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040097 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070098 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040099 mIsInitialized = true;
100 }
101 mInitializedCondition.notify_all();
102
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800103 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -0700104 const auto getNextTask = [this]() -> std::optional<Work> {
105 std::scoped_lock lock(mThreadMutex);
106 if (!mFunctionCalls.empty()) {
107 Work task = mFunctionCalls.front();
108 mFunctionCalls.pop();
109 return std::make_optional<Work>(task);
110 }
111 return std::nullopt;
112 };
113
114 const auto task = getNextTask();
115
116 if (task) {
117 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800118 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700119
120 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800121 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
122 return !mRunning || !mFunctionCalls.empty();
123 });
124 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400125
126 // we must release the RenderEngine on the thread that created it
127 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800128}
129
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400130void RenderEngineThreaded::waitUntilInitialized() const {
131 std::unique_lock<std::mutex> lock(mInitializedMutex);
132 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
133}
134
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700135std::future<void> RenderEngineThreaded::primeCache() {
136 const auto resultPromise = std::make_shared<std::promise<void>>();
137 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700138 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400139 // This function is designed so it can run asynchronously, so we do not need to wait
140 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800141 {
142 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700143 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800144 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700145 if (setSchedFifo(false) != NO_ERROR) {
146 ALOGW("Couldn't set SCHED_OTHER for primeCache");
147 }
148
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800149 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700150 resultPromise->set_value();
151
152 if (setSchedFifo(true) != NO_ERROR) {
153 ALOGW("Couldn't set SCHED_FIFO for primeCache");
154 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800155 });
156 }
157 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700158
159 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800160}
161
162void RenderEngineThreaded::dump(std::string& result) {
163 std::promise<std::string> resultPromise;
164 std::future<std::string> resultFuture = resultPromise.get_future();
165 {
166 std::lock_guard lock(mThreadMutex);
167 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
168 ATRACE_NAME("REThreaded::dump");
169 std::string localResult = result;
170 instance.dump(localResult);
171 resultPromise.set_value(std::move(localResult));
172 });
173 }
174 mCondition.notify_one();
175 // Note: This is an rvalue.
176 result.assign(resultFuture.get());
177}
178
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800179void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700180 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800181 std::promise<void> resultPromise;
182 std::future<void> resultFuture = resultPromise.get_future();
183 {
184 std::lock_guard lock(mThreadMutex);
185 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
186 ATRACE_NAME("REThreaded::genTextures");
187 instance.genTextures(count, names);
188 resultPromise.set_value();
189 });
190 }
191 mCondition.notify_one();
192 resultFuture.wait();
193}
194
195void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700196 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800197 std::promise<void> resultPromise;
198 std::future<void> resultFuture = resultPromise.get_future();
199 {
200 std::lock_guard lock(mThreadMutex);
201 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
202 ATRACE_NAME("REThreaded::deleteTextures");
203 instance.deleteTextures(count, names);
204 resultPromise.set_value();
205 });
206 }
207 mCondition.notify_one();
208 resultFuture.wait();
209}
210
Alec Mouria90a5702021-04-16 16:36:21 +0000211void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
212 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700213 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800214 // This function is designed so it can run asynchronously, so we do not need to wait
215 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800216 {
217 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800218 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000219 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
220 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800221 });
222 }
223 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800224}
225
Alec Mouria90a5702021-04-16 16:36:21 +0000226void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700227 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800228 // This function is designed so it can run asynchronously, so we do not need to wait
229 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800230 {
231 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800232 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000233 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
234 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800235 });
236 }
237 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800238}
239
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800240size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400241 waitUntilInitialized();
242 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800243}
244
245size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400246 waitUntilInitialized();
247 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800248}
249
250bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400251 waitUntilInitialized();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400252 std::lock_guard lock(mThreadMutex);
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -0400253 return mIsProtected;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800254}
255
256bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400257 waitUntilInitialized();
258 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800259}
260
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -0400261void RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
262 if (isProtected() == useProtectedContext ||
263 (useProtectedContext && !supportsProtectedContent())) {
264 return;
265 }
266
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800267 {
268 std::lock_guard lock(mThreadMutex);
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -0400269 mFunctionCalls.push([useProtectedContext, this](renderengine::RenderEngine& instance) {
270 ATRACE_NAME("REThreaded::useProtectedContext");
271 instance.useProtectedContext(useProtectedContext);
272 if (instance.isProtected() != useProtectedContext) {
273 ALOGE("Failed to switch RenderEngine context.");
274 // reset the cached mIsProtected value to a good state, but this does not
275 // prevent other callers of this method and isProtected from reading the
276 // invalid cached value.
277 mIsProtected = instance.isProtected();
278 }
279 });
280 mIsProtected = useProtectedContext;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800281 }
282 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800283}
284
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400285void RenderEngineThreaded::cleanupPostRender() {
286 if (canSkipPostRenderCleanup()) {
287 return;
288 }
289
290 // This function is designed so it can run asynchronously, so we do not need to wait
291 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800292 {
293 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400294 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Leon Scroggins III1e34a702021-08-24 15:13:32 -0400295 ATRACE_NAME("REThreaded::cleanupPostRender");
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400296 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800297 });
298 }
299 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400300}
301
302bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
303 waitUntilInitialized();
304 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800305}
306
Sally Qi4cabdd02021-08-05 16:45:57 -0700307void RenderEngineThreaded::drawLayersInternal(
308 const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise,
Sally Qi59a9f502021-10-12 18:53:23 +0000309 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700310 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
311 base::unique_fd&& bufferFence) {
312 resultPromise->set_value({NO_ERROR, base::unique_fd()});
313 return;
314}
315
316std::future<RenderEngineResult> RenderEngineThreaded::drawLayers(
Sally Qi59a9f502021-10-12 18:53:23 +0000317 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700318 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
319 base::unique_fd&& bufferFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700320 ATRACE_CALL();
Sally Qi4cabdd02021-08-05 16:45:57 -0700321 const auto resultPromise = std::make_shared<std::promise<RenderEngineResult>>();
322 std::future<RenderEngineResult> resultFuture = resultPromise->get_future();
Sally Qi59a9f502021-10-12 18:53:23 +0000323 int fd = bufferFence.release();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800324 {
325 std::lock_guard lock(mThreadMutex);
Sally Qi59a9f502021-10-12 18:53:23 +0000326 mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache,
327 fd](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800328 ATRACE_NAME("REThreaded::drawLayers");
Sally Qi4cabdd02021-08-05 16:45:57 -0700329 instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
Sally Qi59a9f502021-10-12 18:53:23 +0000330 useFramebufferCache, base::unique_fd(fd));
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800331 });
332 }
333 mCondition.notify_one();
Sally Qi4cabdd02021-08-05 16:45:57 -0700334 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800335}
336
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200337void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700338 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400339 // This function is designed so it can run asynchronously, so we do not need to wait
340 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200341 {
342 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400343 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200344 ATRACE_NAME("REThreaded::cleanFramebufferCache");
345 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200346 });
347 }
348 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200349}
350
Alec Mourid6f09462020-12-07 11:18:17 -0800351int RenderEngineThreaded::getContextPriority() {
352 std::promise<int> resultPromise;
353 std::future<int> resultFuture = resultPromise.get_future();
354 {
355 std::lock_guard lock(mThreadMutex);
356 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
357 ATRACE_NAME("REThreaded::getContextPriority");
358 int priority = instance.getContextPriority();
359 resultPromise.set_value(priority);
360 });
361 }
362 mCondition.notify_one();
363 return resultFuture.get();
364}
365
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500366bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400367 waitUntilInitialized();
368 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500369}
370
Ady Abrahamed3290f2021-05-17 15:12:14 -0700371void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400372 // This function is designed so it can run asynchronously, so we do not need to wait
373 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400374 {
375 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400376 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Ady Abrahamed3290f2021-05-17 15:12:14 -0700377 ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
378 instance.onActiveDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400379 });
380 }
381 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400382}
383
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800384} // namespace threaded
385} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700386} // namespace android