blob: f4cebc05ecd6aa83de0fb2958abb1f7f1561b87e [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
Ana Krulec9bc9dc62020-02-26 12:16:40 -080030using namespace std::chrono_literals;
31
32namespace android {
33namespace renderengine {
34namespace threaded {
35
Leon Scroggins III696bf932024-01-24 15:21:05 -050036std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory) {
37 return std::make_unique<RenderEngineThreaded>(std::move(factory));
Ana Krulec9bc9dc62020-02-26 12:16:40 -080038}
39
Leon Scroggins III696bf932024-01-24 15:21:05 -050040RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory)
41 : RenderEngine(Threaded::YES) {
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() {
Alec Mouri39d9cb72021-06-10 10:26:15 -070049 mRunning = false;
50 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080051
52 if (mThread.joinable()) {
53 mThread.join();
54 }
55}
56
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070057status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
58 static constexpr int kFifoPriority = 2;
59 static constexpr int kOtherPriority = 0;
60
61 struct sched_param param = {0};
62 int sched_policy;
63 if (enabled) {
64 sched_policy = SCHED_FIFO;
65 param.sched_priority = kFifoPriority;
66 } else {
67 sched_policy = SCHED_OTHER;
68 param.sched_priority = kOtherPriority;
69 }
70
71 if (sched_setscheduler(0, sched_policy, &param) != 0) {
72 return -errno;
73 }
74 return NO_ERROR;
75}
76
Ana Krulec9bc9dc62020-02-26 12:16:40 -080077// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070078void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080079 ATRACE_CALL();
80
Wei Wang976a6452021-06-11 15:26:00 -070081 if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) {
82 ALOGW("Failed to set render-engine task profile!");
83 }
84
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070085 if (setSchedFifo(true) != NO_ERROR) {
86 ALOGW("Couldn't set SCHED_FIFO");
Ana Krulec9bc9dc62020-02-26 12:16:40 -080087 }
88
Ana Krulec15f7cf32020-05-12 11:57:42 -070089 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080090
Ana Krulec9bc9dc62020-02-26 12:16:40 -080091 pthread_setname_np(pthread_self(), mThreadName);
92
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040093 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070094 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040095 mIsInitialized = true;
96 }
97 mInitializedCondition.notify_all();
98
Ana Krulec9bc9dc62020-02-26 12:16:40 -080099 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -0700100 const auto getNextTask = [this]() -> std::optional<Work> {
101 std::scoped_lock lock(mThreadMutex);
102 if (!mFunctionCalls.empty()) {
103 Work task = mFunctionCalls.front();
104 mFunctionCalls.pop();
105 return std::make_optional<Work>(task);
106 }
107 return std::nullopt;
108 };
109
110 const auto task = getNextTask();
111
112 if (task) {
113 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800114 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700115
116 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800117 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
118 return !mRunning || !mFunctionCalls.empty();
119 });
120 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400121
122 // we must release the RenderEngine on the thread that created it
123 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800124}
125
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400126void RenderEngineThreaded::waitUntilInitialized() const {
Ady Abraham36135d02023-12-20 13:33:56 -0800127 if (!mIsInitialized) {
128 std::unique_lock<std::mutex> lock(mInitializedMutex);
129 mInitializedCondition.wait(lock, [this] { return mIsInitialized.load(); });
130 }
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400131}
132
Bruno BELANYIb9b5b702023-10-13 13:25:11 +0000133std::future<void> RenderEngineThreaded::primeCache(bool shouldPrimeUltraHDR) {
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700134 const auto resultPromise = std::make_shared<std::promise<void>>();
135 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700136 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400137 // This function is designed so it can run asynchronously, so we do not need to wait
138 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800139 {
140 std::lock_guard lock(mThreadMutex);
Bruno BELANYIb9b5b702023-10-13 13:25:11 +0000141 mFunctionCalls.push(
142 [resultPromise, shouldPrimeUltraHDR](renderengine::RenderEngine& instance) {
143 ATRACE_NAME("REThreaded::primeCache");
144 if (setSchedFifo(false) != NO_ERROR) {
145 ALOGW("Couldn't set SCHED_OTHER for primeCache");
146 }
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700147
Bruno BELANYIb9b5b702023-10-13 13:25:11 +0000148 instance.primeCache(shouldPrimeUltraHDR);
149 resultPromise->set_value();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700150
Bruno BELANYIb9b5b702023-10-13 13:25:11 +0000151 if (setSchedFifo(true) != NO_ERROR) {
152 ALOGW("Couldn't set SCHED_FIFO for primeCache");
153 }
154 });
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800155 }
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
Alec Mouria90a5702021-04-16 16:36:21 +0000178void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
179 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700180 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800181 // This function is designed so it can run asynchronously, so we do not need to wait
182 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800183 {
184 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800185 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000186 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
187 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800188 });
189 }
190 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800191}
192
Alec Mouri92f89fa2023-02-24 00:05:06 +0000193void RenderEngineThreaded::unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700194 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800195 // This function is designed so it can run asynchronously, so we do not need to wait
196 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800197 {
198 std::lock_guard lock(mThreadMutex);
Alec Mouri92f89fa2023-02-24 00:05:06 +0000199 mFunctionCalls.push(
200 [=, buffer = std::move(buffer)](renderengine::RenderEngine& instance) mutable {
201 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
202 instance.unmapExternalTextureBuffer(std::move(buffer));
203 });
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800204 }
205 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800206}
207
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800208size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400209 waitUntilInitialized();
210 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800211}
212
213size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400214 waitUntilInitialized();
215 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800216}
217
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800218bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400219 waitUntilInitialized();
220 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800221}
222
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400223void RenderEngineThreaded::cleanupPostRender() {
224 if (canSkipPostRenderCleanup()) {
225 return;
226 }
227
228 // 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);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400232 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Leon Scroggins III1e34a702021-08-24 15:13:32 -0400233 ATRACE_NAME("REThreaded::cleanupPostRender");
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400234 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800235 });
Alex Careja5b7855f2023-09-27 11:11:22 +0000236 mNeedsPostRenderCleanup = false;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800237 }
238 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400239}
240
241bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
Alex Careja5b7855f2023-09-27 11:11:22 +0000242 return !mNeedsPostRenderCleanup;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800243}
244
Sally Qi4cabdd02021-08-05 16:45:57 -0700245void RenderEngineThreaded::drawLayersInternal(
Patrick Williams2e9748f2022-08-09 22:48:18 +0000246 const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
Sally Qi59a9f502021-10-12 18:53:23 +0000247 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Alec Mourif29700f2023-08-17 21:53:31 +0000248 const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) {
Patrick Williams2e9748f2022-08-09 22:48:18 +0000249 resultPromise->set_value(Fence::NO_FENCE);
Sally Qi4cabdd02021-08-05 16:45:57 -0700250 return;
251}
252
Patrick Williams2e9748f2022-08-09 22:48:18 +0000253ftl::Future<FenceResult> RenderEngineThreaded::drawLayers(
Sally Qi59a9f502021-10-12 18:53:23 +0000254 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Alec Mourif29700f2023-08-17 21:53:31 +0000255 const std::shared_ptr<ExternalTexture>& buffer, base::unique_fd&& bufferFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700256 ATRACE_CALL();
Patrick Williams2e9748f2022-08-09 22:48:18 +0000257 const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
258 std::future<FenceResult> resultFuture = resultPromise->get_future();
Sally Qi59a9f502021-10-12 18:53:23 +0000259 int fd = bufferFence.release();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800260 {
261 std::lock_guard lock(mThreadMutex);
Alex Careja5b7855f2023-09-27 11:11:22 +0000262 mNeedsPostRenderCleanup = true;
Alec Mourif29700f2023-08-17 21:53:31 +0000263 mFunctionCalls.push(
264 [resultPromise, display, layers, buffer, fd](renderengine::RenderEngine& instance) {
265 ATRACE_NAME("REThreaded::drawLayers");
266 instance.updateProtectedContext(layers, buffer);
267 instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
268 base::unique_fd(fd));
269 });
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800270 }
271 mCondition.notify_one();
Sally Qi4cabdd02021-08-05 16:45:57 -0700272 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800273}
274
Alec Mourid6f09462020-12-07 11:18:17 -0800275int RenderEngineThreaded::getContextPriority() {
276 std::promise<int> resultPromise;
277 std::future<int> resultFuture = resultPromise.get_future();
278 {
279 std::lock_guard lock(mThreadMutex);
280 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
281 ATRACE_NAME("REThreaded::getContextPriority");
282 int priority = instance.getContextPriority();
283 resultPromise.set_value(priority);
284 });
285 }
286 mCondition.notify_one();
287 return resultFuture.get();
288}
289
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500290bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400291 waitUntilInitialized();
292 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500293}
294
Ady Abrahamed3290f2021-05-17 15:12:14 -0700295void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400296 // This function is designed so it can run asynchronously, so we do not need to wait
297 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400298 {
299 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400300 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Ady Abrahamed3290f2021-05-17 15:12:14 -0700301 ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
302 instance.onActiveDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400303 });
304 }
305 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400306}
307
Matt Buckleyef51fba2021-10-12 19:30:12 +0000308std::optional<pid_t> RenderEngineThreaded::getRenderEngineTid() const {
309 std::promise<pid_t> tidPromise;
310 std::future<pid_t> tidFuture = tidPromise.get_future();
311 {
312 std::lock_guard lock(mThreadMutex);
313 mFunctionCalls.push([&tidPromise](renderengine::RenderEngine& instance) {
314 tidPromise.set_value(gettid());
315 });
316 }
317
318 mCondition.notify_one();
319 return std::make_optional(tidFuture.get());
320}
321
Leon Scroggins IIIa37ca992022-02-02 18:08:20 -0500322void RenderEngineThreaded::setEnableTracing(bool tracingEnabled) {
323 // This function is designed so it can run asynchronously, so we do not need to wait
324 // for the futures.
325 {
326 std::lock_guard lock(mThreadMutex);
327 mFunctionCalls.push([tracingEnabled](renderengine::RenderEngine& instance) {
328 ATRACE_NAME("REThreaded::setEnableTracing");
329 instance.setEnableTracing(tracingEnabled);
330 });
331 }
332 mCondition.notify_one();
333}
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800334} // namespace threaded
335} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700336} // namespace android