blob: 5febd8ccd570b420c960e58b245c68b349520fd0 [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
59// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070060void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080061 ATRACE_CALL();
62
63 struct sched_param param = {0};
64 param.sched_priority = 2;
65 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
66 ALOGE("Couldn't set SCHED_FIFO");
67 }
68
Ana Krulec15f7cf32020-05-12 11:57:42 -070069 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080070
Ana Krulec9bc9dc62020-02-26 12:16:40 -080071 pthread_setname_np(pthread_self(), mThreadName);
72
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040073 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070074 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040075 mIsInitialized = true;
76 }
77 mInitializedCondition.notify_all();
78
Ana Krulec9bc9dc62020-02-26 12:16:40 -080079 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -070080 const auto getNextTask = [this]() -> std::optional<Work> {
81 std::scoped_lock lock(mThreadMutex);
82 if (!mFunctionCalls.empty()) {
83 Work task = mFunctionCalls.front();
84 mFunctionCalls.pop();
85 return std::make_optional<Work>(task);
86 }
87 return std::nullopt;
88 };
89
90 const auto task = getNextTask();
91
92 if (task) {
93 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080094 }
Alec Mouri39d9cb72021-06-10 10:26:15 -070095
96 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -080097 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
98 return !mRunning || !mFunctionCalls.empty();
99 });
100 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400101
102 // we must release the RenderEngine on the thread that created it
103 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800104}
105
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400106void RenderEngineThreaded::waitUntilInitialized() const {
107 std::unique_lock<std::mutex> lock(mInitializedMutex);
108 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
109}
110
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500111void RenderEngineThreaded::primeCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700112 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400113 // This function is designed so it can run asynchronously, so we do not need to wait
114 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800115 {
116 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400117 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800118 ATRACE_NAME("REThreaded::primeCache");
119 instance.primeCache();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800120 });
121 }
122 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800123}
124
125void RenderEngineThreaded::dump(std::string& result) {
126 std::promise<std::string> resultPromise;
127 std::future<std::string> resultFuture = resultPromise.get_future();
128 {
129 std::lock_guard lock(mThreadMutex);
130 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
131 ATRACE_NAME("REThreaded::dump");
132 std::string localResult = result;
133 instance.dump(localResult);
134 resultPromise.set_value(std::move(localResult));
135 });
136 }
137 mCondition.notify_one();
138 // Note: This is an rvalue.
139 result.assign(resultFuture.get());
140}
141
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800142void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700143 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800144 std::promise<void> resultPromise;
145 std::future<void> resultFuture = resultPromise.get_future();
146 {
147 std::lock_guard lock(mThreadMutex);
148 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
149 ATRACE_NAME("REThreaded::genTextures");
150 instance.genTextures(count, names);
151 resultPromise.set_value();
152 });
153 }
154 mCondition.notify_one();
155 resultFuture.wait();
156}
157
158void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700159 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800160 std::promise<void> resultPromise;
161 std::future<void> resultFuture = resultPromise.get_future();
162 {
163 std::lock_guard lock(mThreadMutex);
164 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
165 ATRACE_NAME("REThreaded::deleteTextures");
166 instance.deleteTextures(count, names);
167 resultPromise.set_value();
168 });
169 }
170 mCondition.notify_one();
171 resultFuture.wait();
172}
173
Alec Mouria90a5702021-04-16 16:36:21 +0000174void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
175 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700176 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800177 // This function is designed so it can run asynchronously, so we do not need to wait
178 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800179 {
180 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800181 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000182 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
183 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800184 });
185 }
186 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800187}
188
Alec Mouria90a5702021-04-16 16:36:21 +0000189void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
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::unmapExternalTextureBuffer");
197 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800198 });
199 }
200 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800201}
202
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800203size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400204 waitUntilInitialized();
205 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800206}
207
208size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400209 waitUntilInitialized();
210 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800211}
212
213bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400214 waitUntilInitialized();
215 // ensure that useProtectedContext is not currently being changed by some
216 // other thread.
217 std::lock_guard lock(mThreadMutex);
218 return mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800219}
220
221bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400222 waitUntilInitialized();
223 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800224}
225
226bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
227 std::promise<bool> resultPromise;
228 std::future<bool> resultFuture = resultPromise.get_future();
229 {
230 std::lock_guard lock(mThreadMutex);
231 mFunctionCalls.push(
232 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
233 ATRACE_NAME("REThreaded::useProtectedContext");
234 bool returnValue = instance.useProtectedContext(useProtectedContext);
235 resultPromise.set_value(returnValue);
236 });
237 }
238 mCondition.notify_one();
239 return resultFuture.get();
240}
241
Alec Mouri368e1582020-08-13 10:14:29 -0700242bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800243 std::promise<bool> resultPromise;
244 std::future<bool> resultFuture = resultPromise.get_future();
245 {
246 std::lock_guard lock(mThreadMutex);
Alec Mouri368e1582020-08-13 10:14:29 -0700247 mFunctionCalls.push([&resultPromise, mode](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800248 ATRACE_NAME("REThreaded::cleanupPostRender");
Alec Mouri368e1582020-08-13 10:14:29 -0700249 bool returnValue = instance.cleanupPostRender(mode);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800250 resultPromise.set_value(returnValue);
251 });
252 }
253 mCondition.notify_one();
254 return resultFuture.get();
255}
256
257status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
258 const std::vector<const LayerSettings*>& layers,
Alec Mouria90a5702021-04-16 16:36:21 +0000259 const std::shared_ptr<ExternalTexture>& buffer,
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800260 const bool useFramebufferCache,
261 base::unique_fd&& bufferFence,
262 base::unique_fd* drawFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700263 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800264 std::promise<status_t> resultPromise;
265 std::future<status_t> resultFuture = resultPromise.get_future();
266 {
267 std::lock_guard lock(mThreadMutex);
268 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
269 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
270 ATRACE_NAME("REThreaded::drawLayers");
271 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
272 std::move(bufferFence), drawFence);
273 resultPromise.set_value(status);
274 });
275 }
276 mCondition.notify_one();
277 return resultFuture.get();
278}
279
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200280void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700281 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400282 // This function is designed so it can run asynchronously, so we do not need to wait
283 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200284 {
285 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400286 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200287 ATRACE_NAME("REThreaded::cleanFramebufferCache");
288 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200289 });
290 }
291 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200292}
293
Alec Mourid6f09462020-12-07 11:18:17 -0800294int RenderEngineThreaded::getContextPriority() {
295 std::promise<int> resultPromise;
296 std::future<int> resultFuture = resultPromise.get_future();
297 {
298 std::lock_guard lock(mThreadMutex);
299 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
300 ATRACE_NAME("REThreaded::getContextPriority");
301 int priority = instance.getContextPriority();
302 resultPromise.set_value(priority);
303 });
304 }
305 mCondition.notify_one();
306 return resultFuture.get();
307}
308
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500309bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400310 waitUntilInitialized();
311 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500312}
313
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400314void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400315 // This function is designed so it can run asynchronously, so we do not need to wait
316 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400317 {
318 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400319 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400320 ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
321 instance.onPrimaryDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400322 });
323 }
324 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400325}
326
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800327} // namespace threaded
328} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700329} // namespace android