blob: 072b25c0520590bacdb289f74db44585779a2bcb [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() {
Alec Mouri39d9cb72021-06-10 10:26:15 -070051 mRunning = false;
52 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080053
54 if (mThread.joinable()) {
55 mThread.join();
56 }
57}
58
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070059status_t RenderEngineThreaded::setSchedFifo(bool enabled) {
60 static constexpr int kFifoPriority = 2;
61 static constexpr int kOtherPriority = 0;
62
63 struct sched_param param = {0};
64 int sched_policy;
65 if (enabled) {
66 sched_policy = SCHED_FIFO;
67 param.sched_priority = kFifoPriority;
68 } else {
69 sched_policy = SCHED_OTHER;
70 param.sched_priority = kOtherPriority;
71 }
72
73 if (sched_setscheduler(0, sched_policy, &param) != 0) {
74 return -errno;
75 }
76 return NO_ERROR;
77}
78
Ana Krulec9bc9dc62020-02-26 12:16:40 -080079// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070080void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080081 ATRACE_CALL();
82
Ady Abrahamfe2a6db2021-06-09 15:41:37 -070083 if (setSchedFifo(true) != NO_ERROR) {
84 ALOGW("Couldn't set SCHED_FIFO");
Ana Krulec9bc9dc62020-02-26 12:16:40 -080085 }
86
Ana Krulec15f7cf32020-05-12 11:57:42 -070087 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080088
Ana Krulec9bc9dc62020-02-26 12:16:40 -080089 pthread_setname_np(pthread_self(), mThreadName);
90
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040091 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070092 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040093 mIsInitialized = true;
94 }
95 mInitializedCondition.notify_all();
96
Ana Krulec9bc9dc62020-02-26 12:16:40 -080097 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -070098 const auto getNextTask = [this]() -> std::optional<Work> {
99 std::scoped_lock lock(mThreadMutex);
100 if (!mFunctionCalls.empty()) {
101 Work task = mFunctionCalls.front();
102 mFunctionCalls.pop();
103 return std::make_optional<Work>(task);
104 }
105 return std::nullopt;
106 };
107
108 const auto task = getNextTask();
109
110 if (task) {
111 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800112 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700113
114 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800115 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
116 return !mRunning || !mFunctionCalls.empty();
117 });
118 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400119
120 // we must release the RenderEngine on the thread that created it
121 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800122}
123
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400124void RenderEngineThreaded::waitUntilInitialized() const {
125 std::unique_lock<std::mutex> lock(mInitializedMutex);
126 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
127}
128
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700129std::future<void> RenderEngineThreaded::primeCache() {
130 const auto resultPromise = std::make_shared<std::promise<void>>();
131 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700132 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400133 // This function is designed so it can run asynchronously, so we do not need to wait
134 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800135 {
136 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700137 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800138 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700139 if (setSchedFifo(false) != NO_ERROR) {
140 ALOGW("Couldn't set SCHED_OTHER for primeCache");
141 }
142
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800143 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700144 resultPromise->set_value();
145
146 if (setSchedFifo(true) != NO_ERROR) {
147 ALOGW("Couldn't set SCHED_FIFO for primeCache");
148 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800149 });
150 }
151 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700152
153 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800154}
155
156void RenderEngineThreaded::dump(std::string& result) {
157 std::promise<std::string> resultPromise;
158 std::future<std::string> resultFuture = resultPromise.get_future();
159 {
160 std::lock_guard lock(mThreadMutex);
161 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
162 ATRACE_NAME("REThreaded::dump");
163 std::string localResult = result;
164 instance.dump(localResult);
165 resultPromise.set_value(std::move(localResult));
166 });
167 }
168 mCondition.notify_one();
169 // Note: This is an rvalue.
170 result.assign(resultFuture.get());
171}
172
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800173void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700174 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800175 std::promise<void> resultPromise;
176 std::future<void> resultFuture = resultPromise.get_future();
177 {
178 std::lock_guard lock(mThreadMutex);
179 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
180 ATRACE_NAME("REThreaded::genTextures");
181 instance.genTextures(count, names);
182 resultPromise.set_value();
183 });
184 }
185 mCondition.notify_one();
186 resultFuture.wait();
187}
188
189void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700190 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800191 std::promise<void> resultPromise;
192 std::future<void> resultFuture = resultPromise.get_future();
193 {
194 std::lock_guard lock(mThreadMutex);
195 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
196 ATRACE_NAME("REThreaded::deleteTextures");
197 instance.deleteTextures(count, names);
198 resultPromise.set_value();
199 });
200 }
201 mCondition.notify_one();
202 resultFuture.wait();
203}
204
Alec Mouria90a5702021-04-16 16:36:21 +0000205void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
206 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700207 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800208 // This function is designed so it can run asynchronously, so we do not need to wait
209 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800210 {
211 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800212 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000213 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
214 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800215 });
216 }
217 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800218}
219
Alec Mouria90a5702021-04-16 16:36:21 +0000220void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700221 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800222 // This function is designed so it can run asynchronously, so we do not need to wait
223 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800224 {
225 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800226 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000227 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
228 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800229 });
230 }
231 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800232}
233
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800234size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400235 waitUntilInitialized();
236 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800237}
238
239size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400240 waitUntilInitialized();
241 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800242}
243
244bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400245 waitUntilInitialized();
246 // ensure that useProtectedContext is not currently being changed by some
247 // other thread.
248 std::lock_guard lock(mThreadMutex);
249 return mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800250}
251
252bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400253 waitUntilInitialized();
254 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800255}
256
257bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
258 std::promise<bool> resultPromise;
259 std::future<bool> resultFuture = resultPromise.get_future();
260 {
261 std::lock_guard lock(mThreadMutex);
262 mFunctionCalls.push(
263 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
264 ATRACE_NAME("REThreaded::useProtectedContext");
265 bool returnValue = instance.useProtectedContext(useProtectedContext);
266 resultPromise.set_value(returnValue);
267 });
268 }
269 mCondition.notify_one();
270 return resultFuture.get();
271}
272
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400273void RenderEngineThreaded::cleanupPostRender() {
274 if (canSkipPostRenderCleanup()) {
275 return;
276 }
277
278 // This function is designed so it can run asynchronously, so we do not need to wait
279 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800280 {
281 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400282 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
283 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
284 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800285 });
286 }
287 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400288}
289
290bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
291 waitUntilInitialized();
292 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800293}
294
295status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
296 const std::vector<const LayerSettings*>& layers,
Alec Mouria90a5702021-04-16 16:36:21 +0000297 const std::shared_ptr<ExternalTexture>& buffer,
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800298 const bool useFramebufferCache,
299 base::unique_fd&& bufferFence,
300 base::unique_fd* drawFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700301 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800302 std::promise<status_t> resultPromise;
303 std::future<status_t> resultFuture = resultPromise.get_future();
304 {
305 std::lock_guard lock(mThreadMutex);
306 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
307 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
308 ATRACE_NAME("REThreaded::drawLayers");
309 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
310 std::move(bufferFence), drawFence);
311 resultPromise.set_value(status);
312 });
313 }
314 mCondition.notify_one();
315 return resultFuture.get();
316}
317
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200318void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700319 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400320 // This function is designed so it can run asynchronously, so we do not need to wait
321 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200322 {
323 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400324 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200325 ATRACE_NAME("REThreaded::cleanFramebufferCache");
326 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200327 });
328 }
329 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200330}
331
Alec Mourid6f09462020-12-07 11:18:17 -0800332int RenderEngineThreaded::getContextPriority() {
333 std::promise<int> resultPromise;
334 std::future<int> resultFuture = resultPromise.get_future();
335 {
336 std::lock_guard lock(mThreadMutex);
337 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
338 ATRACE_NAME("REThreaded::getContextPriority");
339 int priority = instance.getContextPriority();
340 resultPromise.set_value(priority);
341 });
342 }
343 mCondition.notify_one();
344 return resultFuture.get();
345}
346
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500347bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400348 waitUntilInitialized();
349 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500350}
351
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400352void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400353 // This function is designed so it can run asynchronously, so we do not need to wait
354 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400355 {
356 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400357 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400358 ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
359 instance.onPrimaryDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400360 });
361 }
362 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400363}
364
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800365} // namespace threaded
366} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700367} // namespace android