blob: 6f96baef420ca1ae847c8f641ddba7fcffafa000 [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>
Ana Krulec9bc9dc62020-02-26 12:16:40 -080027#include <utils/Trace.h>
28
29#include "gl/GLESRenderEngine.h"
30
31using namespace std::chrono_literals;
32
33namespace android {
34namespace renderengine {
35namespace threaded {
36
Alec Mouri0d995102021-02-24 16:53:38 -080037std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory,
38 RenderEngineType type) {
39 return std::make_unique<RenderEngineThreaded>(std::move(factory), type);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080040}
41
Alec Mouri0d995102021-02-24 16:53:38 -080042RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type)
43 : RenderEngine(type) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080044 ATRACE_CALL();
45
46 std::lock_guard lockThread(mThreadMutex);
Ana Krulec15f7cf32020-05-12 11:57:42 -070047 mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080048}
49
50RenderEngineThreaded::~RenderEngineThreaded() {
51 {
52 std::lock_guard lock(mThreadMutex);
53 mRunning = false;
54 mCondition.notify_one();
55 }
56
57 if (mThread.joinable()) {
58 mThread.join();
59 }
60}
61
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070062status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
63 static constexpr int kFifoPriority = 2;
64 static constexpr int kOtherPriority = 0;
65
66 struct sched_param param = {0};
67 int sched_policy;
68 if (enabled) {
69 sched_policy = SCHED_FIFO;
70 param.sched_priority = kFifoPriority;
71 } else {
72 sched_policy = SCHED_OTHER;
73 param.sched_priority = kOtherPriority;
74 }
75
76 if (sched_setscheduler(0, sched_policy, &param) != 0) {
77 return -errno;
78 }
79 return NO_ERROR;
80}
81
Ana Krulec9bc9dc62020-02-26 12:16:40 -080082// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070083void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080084 ATRACE_CALL();
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
92 std::unique_lock<std::mutex> lock(mThreadMutex);
93 pthread_setname_np(pthread_self(), mThreadName);
94
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040095 {
96 std::unique_lock<std::mutex> lock(mInitializedMutex);
97 mIsInitialized = true;
98 }
99 mInitializedCondition.notify_all();
100
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800101 while (mRunning) {
102 if (!mFunctionCalls.empty()) {
103 auto task = mFunctionCalls.front();
104 mFunctionCalls.pop();
105 task(*mRenderEngine);
106 }
107 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
108 return !mRunning || !mFunctionCalls.empty();
109 });
110 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400111
112 // we must release the RenderEngine on the thread that created it
113 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800114}
115
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400116void RenderEngineThreaded::waitUntilInitialized() const {
117 std::unique_lock<std::mutex> lock(mInitializedMutex);
118 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
119}
120
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700121std::future<void> RenderEngineThreaded::primeCache() {
122 const auto resultPromise = std::make_shared<std::promise<void>>();
123 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700124 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400125 // This function is designed so it can run asynchronously, so we do not need to wait
126 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800127 {
128 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700129 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800130 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700131 if (setSchedFifo(false) != NO_ERROR) {
132 ALOGW("Couldn't set SCHED_OTHER for primeCache");
133 }
134
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800135 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700136 resultPromise->set_value();
137
138 if (setSchedFifo(true) != NO_ERROR) {
139 ALOGW("Couldn't set SCHED_FIFO for primeCache");
140 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800141 });
142 }
143 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700144
145 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800146}
147
148void RenderEngineThreaded::dump(std::string& result) {
149 std::promise<std::string> resultPromise;
150 std::future<std::string> resultFuture = resultPromise.get_future();
151 {
152 std::lock_guard lock(mThreadMutex);
153 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
154 ATRACE_NAME("REThreaded::dump");
155 std::string localResult = result;
156 instance.dump(localResult);
157 resultPromise.set_value(std::move(localResult));
158 });
159 }
160 mCondition.notify_one();
161 // Note: This is an rvalue.
162 result.assign(resultFuture.get());
163}
164
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800165void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700166 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800167 std::promise<void> resultPromise;
168 std::future<void> resultFuture = resultPromise.get_future();
169 {
170 std::lock_guard lock(mThreadMutex);
171 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
172 ATRACE_NAME("REThreaded::genTextures");
173 instance.genTextures(count, names);
174 resultPromise.set_value();
175 });
176 }
177 mCondition.notify_one();
178 resultFuture.wait();
179}
180
181void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700182 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800183 std::promise<void> resultPromise;
184 std::future<void> resultFuture = resultPromise.get_future();
185 {
186 std::lock_guard lock(mThreadMutex);
187 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
188 ATRACE_NAME("REThreaded::deleteTextures");
189 instance.deleteTextures(count, names);
190 resultPromise.set_value();
191 });
192 }
193 mCondition.notify_one();
194 resultFuture.wait();
195}
196
Alec Mouria90a5702021-04-16 16:36:21 +0000197void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
198 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700199 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800200 // This function is designed so it can run asynchronously, so we do not need to wait
201 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800202 {
203 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800204 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000205 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
206 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800207 });
208 }
209 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800210}
211
Alec Mouria90a5702021-04-16 16:36:21 +0000212void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
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::unmapExternalTextureBuffer");
220 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800221 });
222 }
223 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800224}
225
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800226size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400227 waitUntilInitialized();
228 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800229}
230
231size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400232 waitUntilInitialized();
233 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800234}
235
236bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400237 waitUntilInitialized();
238 // ensure that useProtectedContext is not currently being changed by some
239 // other thread.
240 std::lock_guard lock(mThreadMutex);
241 return mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800242}
243
244bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400245 waitUntilInitialized();
246 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800247}
248
249bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
250 std::promise<bool> resultPromise;
251 std::future<bool> resultFuture = resultPromise.get_future();
252 {
253 std::lock_guard lock(mThreadMutex);
254 mFunctionCalls.push(
255 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
256 ATRACE_NAME("REThreaded::useProtectedContext");
257 bool returnValue = instance.useProtectedContext(useProtectedContext);
258 resultPromise.set_value(returnValue);
259 });
260 }
261 mCondition.notify_one();
262 return resultFuture.get();
263}
264
Alec Mouri368e1582020-08-13 10:14:29 -0700265bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800266 std::promise<bool> resultPromise;
267 std::future<bool> resultFuture = resultPromise.get_future();
268 {
269 std::lock_guard lock(mThreadMutex);
Alec Mouri368e1582020-08-13 10:14:29 -0700270 mFunctionCalls.push([&resultPromise, mode](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800271 ATRACE_NAME("REThreaded::cleanupPostRender");
Alec Mouri368e1582020-08-13 10:14:29 -0700272 bool returnValue = instance.cleanupPostRender(mode);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800273 resultPromise.set_value(returnValue);
274 });
275 }
276 mCondition.notify_one();
277 return resultFuture.get();
278}
279
280status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
281 const std::vector<const LayerSettings*>& layers,
Alec Mouria90a5702021-04-16 16:36:21 +0000282 const std::shared_ptr<ExternalTexture>& buffer,
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800283 const bool useFramebufferCache,
284 base::unique_fd&& bufferFence,
285 base::unique_fd* drawFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700286 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800287 std::promise<status_t> resultPromise;
288 std::future<status_t> resultFuture = resultPromise.get_future();
289 {
290 std::lock_guard lock(mThreadMutex);
291 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
292 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
293 ATRACE_NAME("REThreaded::drawLayers");
294 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
295 std::move(bufferFence), drawFence);
296 resultPromise.set_value(status);
297 });
298 }
299 mCondition.notify_one();
300 return resultFuture.get();
301}
302
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200303void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700304 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400305 // This function is designed so it can run asynchronously, so we do not need to wait
306 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200307 {
308 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400309 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200310 ATRACE_NAME("REThreaded::cleanFramebufferCache");
311 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200312 });
313 }
314 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200315}
316
Alec Mourid6f09462020-12-07 11:18:17 -0800317int RenderEngineThreaded::getContextPriority() {
318 std::promise<int> resultPromise;
319 std::future<int> resultFuture = resultPromise.get_future();
320 {
321 std::lock_guard lock(mThreadMutex);
322 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
323 ATRACE_NAME("REThreaded::getContextPriority");
324 int priority = instance.getContextPriority();
325 resultPromise.set_value(priority);
326 });
327 }
328 mCondition.notify_one();
329 return resultFuture.get();
330}
331
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500332bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400333 waitUntilInitialized();
334 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500335}
336
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400337void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400338 // This function is designed so it can run asynchronously, so we do not need to wait
339 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400340 {
341 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400342 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400343 ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
344 instance.onPrimaryDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400345 });
346 }
347 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400348}
349
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800350} // namespace threaded
351} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700352} // namespace android