blob: 57055bd9ac8b65a231f2935ef821e32e939c49dd [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
Alec Mouri0d995102021-02-24 16:53:38 -080036std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory,
37 RenderEngineType type) {
38 return std::make_unique<RenderEngineThreaded>(std::move(factory), type);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080039}
40
Alec Mouri0d995102021-02-24 16:53:38 -080041RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type)
42 : RenderEngine(type) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080043 ATRACE_CALL();
44
45 std::lock_guard lockThread(mThreadMutex);
Ana Krulec15f7cf32020-05-12 11:57:42 -070046 mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080047}
48
49RenderEngineThreaded::~RenderEngineThreaded() {
Alec Mouri39d9cb72021-06-10 10:26:15 -070050 mRunning = false;
51 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080052
53 if (mThread.joinable()) {
54 mThread.join();
55 }
56}
57
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070058status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
59 static constexpr int kFifoPriority = 2;
60 static constexpr int kOtherPriority = 0;
61
62 struct sched_param param = {0};
63 int sched_policy;
64 if (enabled) {
65 sched_policy = SCHED_FIFO;
66 param.sched_priority = kFifoPriority;
67 } else {
68 sched_policy = SCHED_OTHER;
69 param.sched_priority = kOtherPriority;
70 }
71
72 if (sched_setscheduler(0, sched_policy, &param) != 0) {
73 return -errno;
74 }
75 return NO_ERROR;
76}
77
Ana Krulec9bc9dc62020-02-26 12:16:40 -080078// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070079void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080080 ATRACE_CALL();
81
Wei Wang976a6452021-06-11 15:26:00 -070082 if (!SetTaskProfiles(0, {"SFRenderEnginePolicy"})) {
83 ALOGW("Failed to set render-engine task profile!");
84 }
85
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070086 if (setSchedFifo(true) != NO_ERROR) {
87 ALOGW("Couldn't set SCHED_FIFO");
Ana Krulec9bc9dc62020-02-26 12:16:40 -080088 }
89
Ana Krulec15f7cf32020-05-12 11:57:42 -070090 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080091
Ana Krulec9bc9dc62020-02-26 12:16:40 -080092 pthread_setname_np(pthread_self(), mThreadName);
93
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040094 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070095 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040096 mIsInitialized = true;
97 }
98 mInitializedCondition.notify_all();
99
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800100 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -0700101 const auto getNextTask = [this]() -> std::optional<Work> {
102 std::scoped_lock lock(mThreadMutex);
103 if (!mFunctionCalls.empty()) {
104 Work task = mFunctionCalls.front();
105 mFunctionCalls.pop();
106 return std::make_optional<Work>(task);
107 }
108 return std::nullopt;
109 };
110
111 const auto task = getNextTask();
112
113 if (task) {
114 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800115 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700116
117 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800118 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
119 return !mRunning || !mFunctionCalls.empty();
120 });
121 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400122
123 // we must release the RenderEngine on the thread that created it
124 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800125}
126
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400127void RenderEngineThreaded::waitUntilInitialized() const {
128 std::unique_lock<std::mutex> lock(mInitializedMutex);
129 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
130}
131
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700132std::future<void> RenderEngineThreaded::primeCache() {
133 const auto resultPromise = std::make_shared<std::promise<void>>();
134 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700135 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400136 // This function is designed so it can run asynchronously, so we do not need to wait
137 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800138 {
139 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700140 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800141 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700142 if (setSchedFifo(false) != NO_ERROR) {
143 ALOGW("Couldn't set SCHED_OTHER for primeCache");
144 }
145
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800146 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700147 resultPromise->set_value();
148
149 if (setSchedFifo(true) != NO_ERROR) {
150 ALOGW("Couldn't set SCHED_FIFO for primeCache");
151 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800152 });
153 }
154 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700155
156 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800157}
158
159void RenderEngineThreaded::dump(std::string& result) {
160 std::promise<std::string> resultPromise;
161 std::future<std::string> resultFuture = resultPromise.get_future();
162 {
163 std::lock_guard lock(mThreadMutex);
164 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
165 ATRACE_NAME("REThreaded::dump");
166 std::string localResult = result;
167 instance.dump(localResult);
168 resultPromise.set_value(std::move(localResult));
169 });
170 }
171 mCondition.notify_one();
172 // Note: This is an rvalue.
173 result.assign(resultFuture.get());
174}
175
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800176void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700177 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500178 // This is a no-op in SkiaRenderEngine.
Alec Mourie2b61c62023-08-15 19:04:54 +0000179 return;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800180}
181
182void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700183 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500184 // This is a no-op in SkiaRenderEngine.
Alec Mourie2b61c62023-08-15 19:04:54 +0000185 return;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800186}
187
Alec Mouria90a5702021-04-16 16:36:21 +0000188void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
189 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700190 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800191 // This function is designed so it can run asynchronously, so we do not need to wait
192 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800193 {
194 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800195 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000196 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
197 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800198 });
199 }
200 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800201}
202
Alec Mouri92f89fa2023-02-24 00:05:06 +0000203void RenderEngineThreaded::unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700204 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800205 // This function is designed so it can run asynchronously, so we do not need to wait
206 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800207 {
208 std::lock_guard lock(mThreadMutex);
Alec Mouri92f89fa2023-02-24 00:05:06 +0000209 mFunctionCalls.push(
210 [=, buffer = std::move(buffer)](renderengine::RenderEngine& instance) mutable {
211 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
212 instance.unmapExternalTextureBuffer(std::move(buffer));
213 });
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800214 }
215 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800216}
217
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800218size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400219 waitUntilInitialized();
220 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800221}
222
223size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400224 waitUntilInitialized();
225 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800226}
227
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800228bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400229 waitUntilInitialized();
230 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800231}
232
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400233void RenderEngineThreaded::cleanupPostRender() {
234 if (canSkipPostRenderCleanup()) {
235 return;
236 }
237
238 // This function is designed so it can run asynchronously, so we do not need to wait
239 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800240 {
241 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400242 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Leon Scroggins III1e34a702021-08-24 15:13:32 -0400243 ATRACE_NAME("REThreaded::cleanupPostRender");
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400244 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800245 });
246 }
247 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400248}
249
250bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
251 waitUntilInitialized();
252 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800253}
254
Sally Qi4cabdd02021-08-05 16:45:57 -0700255void RenderEngineThreaded::drawLayersInternal(
Patrick Williams2e9748f2022-08-09 22:48:18 +0000256 const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
Sally Qi59a9f502021-10-12 18:53:23 +0000257 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700258 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
259 base::unique_fd&& bufferFence) {
Patrick Williams2e9748f2022-08-09 22:48:18 +0000260 resultPromise->set_value(Fence::NO_FENCE);
Sally Qi4cabdd02021-08-05 16:45:57 -0700261 return;
262}
263
Patrick Williams2e9748f2022-08-09 22:48:18 +0000264ftl::Future<FenceResult> RenderEngineThreaded::drawLayers(
Sally Qi59a9f502021-10-12 18:53:23 +0000265 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700266 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
267 base::unique_fd&& bufferFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700268 ATRACE_CALL();
Patrick Williams2e9748f2022-08-09 22:48:18 +0000269 const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
270 std::future<FenceResult> resultFuture = resultPromise->get_future();
Sally Qi59a9f502021-10-12 18:53:23 +0000271 int fd = bufferFence.release();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800272 {
273 std::lock_guard lock(mThreadMutex);
Sally Qi59a9f502021-10-12 18:53:23 +0000274 mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache,
275 fd](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800276 ATRACE_NAME("REThreaded::drawLayers");
Patrick Williams8aed5d22022-10-31 22:18:10 +0000277 instance.updateProtectedContext(layers, buffer);
Sally Qi4cabdd02021-08-05 16:45:57 -0700278 instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
Sally Qi59a9f502021-10-12 18:53:23 +0000279 useFramebufferCache, base::unique_fd(fd));
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800280 });
281 }
282 mCondition.notify_one();
Sally Qi4cabdd02021-08-05 16:45:57 -0700283 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800284}
285
Alec Mourid6f09462020-12-07 11:18:17 -0800286int RenderEngineThreaded::getContextPriority() {
287 std::promise<int> resultPromise;
288 std::future<int> resultFuture = resultPromise.get_future();
289 {
290 std::lock_guard lock(mThreadMutex);
291 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
292 ATRACE_NAME("REThreaded::getContextPriority");
293 int priority = instance.getContextPriority();
294 resultPromise.set_value(priority);
295 });
296 }
297 mCondition.notify_one();
298 return resultFuture.get();
299}
300
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500301bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400302 waitUntilInitialized();
303 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500304}
305
Ady Abrahamed3290f2021-05-17 15:12:14 -0700306void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400307 // This function is designed so it can run asynchronously, so we do not need to wait
308 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400309 {
310 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400311 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Ady Abrahamed3290f2021-05-17 15:12:14 -0700312 ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
313 instance.onActiveDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400314 });
315 }
316 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400317}
318
Matt Buckleyef51fba2021-10-12 19:30:12 +0000319std::optional<pid_t> RenderEngineThreaded::getRenderEngineTid() const {
320 std::promise<pid_t> tidPromise;
321 std::future<pid_t> tidFuture = tidPromise.get_future();
322 {
323 std::lock_guard lock(mThreadMutex);
324 mFunctionCalls.push([&tidPromise](renderengine::RenderEngine& instance) {
325 tidPromise.set_value(gettid());
326 });
327 }
328
329 mCondition.notify_one();
330 return std::make_optional(tidFuture.get());
331}
332
Leon Scroggins IIIa37ca992022-02-02 18:08:20 -0500333void RenderEngineThreaded::setEnableTracing(bool tracingEnabled) {
334 // This function is designed so it can run asynchronously, so we do not need to wait
335 // for the futures.
336 {
337 std::lock_guard lock(mThreadMutex);
338 mFunctionCalls.push([tracingEnabled](renderengine::RenderEngine& instance) {
339 ATRACE_NAME("REThreaded::setEnableTracing");
340 instance.setEnableTracing(tracingEnabled);
341 });
342 }
343 mCondition.notify_one();
344}
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800345} // namespace threaded
346} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700347} // namespace android