blob: 6a1561abcdeafc97c36155790a64c90f747159e5 [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();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500180 // This is a no-op in SkiaRenderEngine.
181 if (getRenderEngineType() != RenderEngineType::THREADED) {
182 return;
183 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800184 std::promise<void> resultPromise;
185 std::future<void> resultFuture = resultPromise.get_future();
186 {
187 std::lock_guard lock(mThreadMutex);
188 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
189 ATRACE_NAME("REThreaded::genTextures");
190 instance.genTextures(count, names);
191 resultPromise.set_value();
192 });
193 }
194 mCondition.notify_one();
195 resultFuture.wait();
196}
197
198void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700199 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500200 // This is a no-op in SkiaRenderEngine.
201 if (getRenderEngineType() != RenderEngineType::THREADED) {
202 return;
203 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800204 std::promise<void> resultPromise;
205 std::future<void> resultFuture = resultPromise.get_future();
206 {
207 std::lock_guard lock(mThreadMutex);
208 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
209 ATRACE_NAME("REThreaded::deleteTextures");
210 instance.deleteTextures(count, names);
211 resultPromise.set_value();
212 });
213 }
214 mCondition.notify_one();
215 resultFuture.wait();
216}
217
Alec Mouria90a5702021-04-16 16:36:21 +0000218void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
219 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700220 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800221 // This function is designed so it can run asynchronously, so we do not need to wait
222 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800223 {
224 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800225 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000226 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
227 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800228 });
229 }
230 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800231}
232
Alec Mouri92f89fa2023-02-24 00:05:06 +0000233void RenderEngineThreaded::unmapExternalTextureBuffer(sp<GraphicBuffer>&& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700234 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800235 // This function is designed so it can run asynchronously, so we do not need to wait
236 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800237 {
238 std::lock_guard lock(mThreadMutex);
Alec Mouri92f89fa2023-02-24 00:05:06 +0000239 mFunctionCalls.push(
240 [=, buffer = std::move(buffer)](renderengine::RenderEngine& instance) mutable {
241 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
242 instance.unmapExternalTextureBuffer(std::move(buffer));
243 });
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800244 }
245 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800246}
247
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800248size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400249 waitUntilInitialized();
250 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800251}
252
253size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400254 waitUntilInitialized();
255 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800256}
257
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800258bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400259 waitUntilInitialized();
260 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800261}
262
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400263void RenderEngineThreaded::cleanupPostRender() {
264 if (canSkipPostRenderCleanup()) {
265 return;
266 }
267
268 // This function is designed so it can run asynchronously, so we do not need to wait
269 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800270 {
271 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400272 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Leon Scroggins III1e34a702021-08-24 15:13:32 -0400273 ATRACE_NAME("REThreaded::cleanupPostRender");
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400274 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800275 });
276 }
277 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400278}
279
280bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
281 waitUntilInitialized();
282 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800283}
284
Sally Qi4cabdd02021-08-05 16:45:57 -0700285void RenderEngineThreaded::drawLayersInternal(
Patrick Williams2e9748f2022-08-09 22:48:18 +0000286 const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
Sally Qi59a9f502021-10-12 18:53:23 +0000287 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700288 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
289 base::unique_fd&& bufferFence) {
Patrick Williams2e9748f2022-08-09 22:48:18 +0000290 resultPromise->set_value(Fence::NO_FENCE);
Sally Qi4cabdd02021-08-05 16:45:57 -0700291 return;
292}
293
Patrick Williams2e9748f2022-08-09 22:48:18 +0000294ftl::Future<FenceResult> RenderEngineThreaded::drawLayers(
Sally Qi59a9f502021-10-12 18:53:23 +0000295 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700296 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
297 base::unique_fd&& bufferFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700298 ATRACE_CALL();
Patrick Williams2e9748f2022-08-09 22:48:18 +0000299 const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
300 std::future<FenceResult> resultFuture = resultPromise->get_future();
Sally Qi59a9f502021-10-12 18:53:23 +0000301 int fd = bufferFence.release();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800302 {
303 std::lock_guard lock(mThreadMutex);
Sally Qi59a9f502021-10-12 18:53:23 +0000304 mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache,
305 fd](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800306 ATRACE_NAME("REThreaded::drawLayers");
Patrick Williams8aed5d22022-10-31 22:18:10 +0000307 instance.updateProtectedContext(layers, buffer);
Sally Qi4cabdd02021-08-05 16:45:57 -0700308 instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
Sally Qi59a9f502021-10-12 18:53:23 +0000309 useFramebufferCache, base::unique_fd(fd));
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800310 });
311 }
312 mCondition.notify_one();
Sally Qi4cabdd02021-08-05 16:45:57 -0700313 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800314}
315
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200316void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700317 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400318 // This function is designed so it can run asynchronously, so we do not need to wait
319 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200320 {
321 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400322 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200323 ATRACE_NAME("REThreaded::cleanFramebufferCache");
324 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200325 });
326 }
327 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200328}
329
Alec Mourid6f09462020-12-07 11:18:17 -0800330int RenderEngineThreaded::getContextPriority() {
331 std::promise<int> resultPromise;
332 std::future<int> resultFuture = resultPromise.get_future();
333 {
334 std::lock_guard lock(mThreadMutex);
335 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
336 ATRACE_NAME("REThreaded::getContextPriority");
337 int priority = instance.getContextPriority();
338 resultPromise.set_value(priority);
339 });
340 }
341 mCondition.notify_one();
342 return resultFuture.get();
343}
344
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500345bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400346 waitUntilInitialized();
347 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500348}
349
Ady Abrahamed3290f2021-05-17 15:12:14 -0700350void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400351 // This function is designed so it can run asynchronously, so we do not need to wait
352 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400353 {
354 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400355 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Ady Abrahamed3290f2021-05-17 15:12:14 -0700356 ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
357 instance.onActiveDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400358 });
359 }
360 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400361}
362
Matt Buckleyef51fba2021-10-12 19:30:12 +0000363std::optional<pid_t> RenderEngineThreaded::getRenderEngineTid() const {
364 std::promise<pid_t> tidPromise;
365 std::future<pid_t> tidFuture = tidPromise.get_future();
366 {
367 std::lock_guard lock(mThreadMutex);
368 mFunctionCalls.push([&tidPromise](renderengine::RenderEngine& instance) {
369 tidPromise.set_value(gettid());
370 });
371 }
372
373 mCondition.notify_one();
374 return std::make_optional(tidFuture.get());
375}
376
Leon Scroggins IIIa37ca992022-02-02 18:08:20 -0500377void RenderEngineThreaded::setEnableTracing(bool tracingEnabled) {
378 // This function is designed so it can run asynchronously, so we do not need to wait
379 // for the futures.
380 {
381 std::lock_guard lock(mThreadMutex);
382 mFunctionCalls.push([tracingEnabled](renderengine::RenderEngine& instance) {
383 ATRACE_NAME("REThreaded::setEnableTracing");
384 instance.setEnableTracing(tracingEnabled);
385 });
386 }
387 mCondition.notify_one();
388}
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800389} // namespace threaded
390} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700391} // namespace android