blob: 9009ce46d3f11a747282885df7c34eeb2e323347 [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
62// NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations.
Ana Krulec15f7cf32020-05-12 11:57:42 -070063void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS {
Ana Krulec9bc9dc62020-02-26 12:16:40 -080064 ATRACE_CALL();
65
66 struct sched_param param = {0};
67 param.sched_priority = 2;
68 if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
69 ALOGE("Couldn't set SCHED_FIFO");
70 }
71
Ana Krulec15f7cf32020-05-12 11:57:42 -070072 mRenderEngine = factory();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080073
74 std::unique_lock<std::mutex> lock(mThreadMutex);
75 pthread_setname_np(pthread_self(), mThreadName);
76
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040077 {
78 std::unique_lock<std::mutex> lock(mInitializedMutex);
79 mIsInitialized = true;
80 }
81 mInitializedCondition.notify_all();
82
Ana Krulec9bc9dc62020-02-26 12:16:40 -080083 while (mRunning) {
84 if (!mFunctionCalls.empty()) {
85 auto task = mFunctionCalls.front();
86 mFunctionCalls.pop();
87 task(*mRenderEngine);
88 }
89 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
90 return !mRunning || !mFunctionCalls.empty();
91 });
92 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -040093
94 // we must release the RenderEngine on the thread that created it
95 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080096}
97
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040098void RenderEngineThreaded::waitUntilInitialized() const {
99 std::unique_lock<std::mutex> lock(mInitializedMutex);
100 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
101}
102
Leon Scroggins IIIb9216dc2021-03-08 17:19:01 -0500103void RenderEngineThreaded::primeCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700104 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400105 // This function is designed so it can run asynchronously, so we do not need to wait
106 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800107 {
108 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400109 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800110 ATRACE_NAME("REThreaded::primeCache");
111 instance.primeCache();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800112 });
113 }
114 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800115}
116
117void RenderEngineThreaded::dump(std::string& result) {
118 std::promise<std::string> resultPromise;
119 std::future<std::string> resultFuture = resultPromise.get_future();
120 {
121 std::lock_guard lock(mThreadMutex);
122 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
123 ATRACE_NAME("REThreaded::dump");
124 std::string localResult = result;
125 instance.dump(localResult);
126 resultPromise.set_value(std::move(localResult));
127 });
128 }
129 mCondition.notify_one();
130 // Note: This is an rvalue.
131 result.assign(resultFuture.get());
132}
133
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800134void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700135 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800136 std::promise<void> resultPromise;
137 std::future<void> resultFuture = resultPromise.get_future();
138 {
139 std::lock_guard lock(mThreadMutex);
140 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
141 ATRACE_NAME("REThreaded::genTextures");
142 instance.genTextures(count, names);
143 resultPromise.set_value();
144 });
145 }
146 mCondition.notify_one();
147 resultFuture.wait();
148}
149
150void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700151 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800152 std::promise<void> resultPromise;
153 std::future<void> resultFuture = resultPromise.get_future();
154 {
155 std::lock_guard lock(mThreadMutex);
156 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
157 ATRACE_NAME("REThreaded::deleteTextures");
158 instance.deleteTextures(count, names);
159 resultPromise.set_value();
160 });
161 }
162 mCondition.notify_one();
163 resultFuture.wait();
164}
165
Alec Mouria90a5702021-04-16 16:36:21 +0000166void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
167 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700168 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800169 // This function is designed so it can run asynchronously, so we do not need to wait
170 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800171 {
172 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800173 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000174 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
175 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800176 });
177 }
178 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800179}
180
Alec Mouria90a5702021-04-16 16:36:21 +0000181void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700182 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800183 // This function is designed so it can run asynchronously, so we do not need to wait
184 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800185 {
186 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800187 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000188 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
189 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800190 });
191 }
192 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800193}
194
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800195size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400196 waitUntilInitialized();
197 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800198}
199
200size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400201 waitUntilInitialized();
202 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800203}
204
205bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400206 waitUntilInitialized();
207 // ensure that useProtectedContext is not currently being changed by some
208 // other thread.
209 std::lock_guard lock(mThreadMutex);
210 return mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800211}
212
213bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400214 waitUntilInitialized();
215 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800216}
217
218bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
219 std::promise<bool> resultPromise;
220 std::future<bool> resultFuture = resultPromise.get_future();
221 {
222 std::lock_guard lock(mThreadMutex);
223 mFunctionCalls.push(
224 [&resultPromise, useProtectedContext](renderengine::RenderEngine& instance) {
225 ATRACE_NAME("REThreaded::useProtectedContext");
226 bool returnValue = instance.useProtectedContext(useProtectedContext);
227 resultPromise.set_value(returnValue);
228 });
229 }
230 mCondition.notify_one();
231 return resultFuture.get();
232}
233
Alec Mouri368e1582020-08-13 10:14:29 -0700234bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800235 std::promise<bool> resultPromise;
236 std::future<bool> resultFuture = resultPromise.get_future();
237 {
238 std::lock_guard lock(mThreadMutex);
Alec Mouri368e1582020-08-13 10:14:29 -0700239 mFunctionCalls.push([&resultPromise, mode](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800240 ATRACE_NAME("REThreaded::cleanupPostRender");
Alec Mouri368e1582020-08-13 10:14:29 -0700241 bool returnValue = instance.cleanupPostRender(mode);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800242 resultPromise.set_value(returnValue);
243 });
244 }
245 mCondition.notify_one();
246 return resultFuture.get();
247}
248
249status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display,
250 const std::vector<const LayerSettings*>& layers,
Alec Mouria90a5702021-04-16 16:36:21 +0000251 const std::shared_ptr<ExternalTexture>& buffer,
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800252 const bool useFramebufferCache,
253 base::unique_fd&& bufferFence,
254 base::unique_fd* drawFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700255 ATRACE_CALL();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800256 std::promise<status_t> resultPromise;
257 std::future<status_t> resultFuture = resultPromise.get_future();
258 {
259 std::lock_guard lock(mThreadMutex);
260 mFunctionCalls.push([&resultPromise, &display, &layers, &buffer, useFramebufferCache,
261 &bufferFence, &drawFence](renderengine::RenderEngine& instance) {
262 ATRACE_NAME("REThreaded::drawLayers");
263 status_t status = instance.drawLayers(display, layers, buffer, useFramebufferCache,
264 std::move(bufferFence), drawFence);
265 resultPromise.set_value(status);
266 });
267 }
268 mCondition.notify_one();
269 return resultFuture.get();
270}
271
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200272void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700273 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400274 // This function is designed so it can run asynchronously, so we do not need to wait
275 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200276 {
277 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400278 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200279 ATRACE_NAME("REThreaded::cleanFramebufferCache");
280 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200281 });
282 }
283 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200284}
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
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400306void RenderEngineThreaded::onPrimaryDisplaySizeChanged(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) {
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400312 ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
313 instance.onPrimaryDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400314 });
315 }
316 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400317}
318
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800319} // namespace threaded
320} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700321} // namespace android