blob: a7176d32797f9223c06ec6b8976ed1107dba31a5 [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();
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -040093 mIsProtected = mRenderEngine->isProtected();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080094
Ana Krulec9bc9dc62020-02-26 12:16:40 -080095 pthread_setname_np(pthread_self(), mThreadName);
96
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040097 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070098 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040099 mIsInitialized = true;
100 }
101 mInitializedCondition.notify_all();
102
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800103 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -0700104 const auto getNextTask = [this]() -> std::optional<Work> {
105 std::scoped_lock lock(mThreadMutex);
106 if (!mFunctionCalls.empty()) {
107 Work task = mFunctionCalls.front();
108 mFunctionCalls.pop();
109 return std::make_optional<Work>(task);
110 }
111 return std::nullopt;
112 };
113
114 const auto task = getNextTask();
115
116 if (task) {
117 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800118 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700119
120 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800121 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
122 return !mRunning || !mFunctionCalls.empty();
123 });
124 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400125
126 // we must release the RenderEngine on the thread that created it
127 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800128}
129
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400130void RenderEngineThreaded::waitUntilInitialized() const {
131 std::unique_lock<std::mutex> lock(mInitializedMutex);
132 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
133}
134
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700135std::future<void> RenderEngineThreaded::primeCache() {
136 const auto resultPromise = std::make_shared<std::promise<void>>();
137 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700138 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400139 // This function is designed so it can run asynchronously, so we do not need to wait
140 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800141 {
142 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700143 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800144 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700145 if (setSchedFifo(false) != NO_ERROR) {
146 ALOGW("Couldn't set SCHED_OTHER for primeCache");
147 }
148
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800149 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700150 resultPromise->set_value();
151
152 if (setSchedFifo(true) != NO_ERROR) {
153 ALOGW("Couldn't set SCHED_FIFO for primeCache");
154 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800155 });
156 }
157 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700158
159 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800160}
161
162void RenderEngineThreaded::dump(std::string& result) {
163 std::promise<std::string> resultPromise;
164 std::future<std::string> resultFuture = resultPromise.get_future();
165 {
166 std::lock_guard lock(mThreadMutex);
167 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
168 ATRACE_NAME("REThreaded::dump");
169 std::string localResult = result;
170 instance.dump(localResult);
171 resultPromise.set_value(std::move(localResult));
172 });
173 }
174 mCondition.notify_one();
175 // Note: This is an rvalue.
176 result.assign(resultFuture.get());
177}
178
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800179void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700180 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500181 // This is a no-op in SkiaRenderEngine.
182 if (getRenderEngineType() != RenderEngineType::THREADED) {
183 return;
184 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800185 std::promise<void> resultPromise;
186 std::future<void> resultFuture = resultPromise.get_future();
187 {
188 std::lock_guard lock(mThreadMutex);
189 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
190 ATRACE_NAME("REThreaded::genTextures");
191 instance.genTextures(count, names);
192 resultPromise.set_value();
193 });
194 }
195 mCondition.notify_one();
196 resultFuture.wait();
197}
198
199void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700200 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500201 // This is a no-op in SkiaRenderEngine.
202 if (getRenderEngineType() != RenderEngineType::THREADED) {
203 return;
204 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800205 std::promise<void> resultPromise;
206 std::future<void> resultFuture = resultPromise.get_future();
207 {
208 std::lock_guard lock(mThreadMutex);
209 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
210 ATRACE_NAME("REThreaded::deleteTextures");
211 instance.deleteTextures(count, names);
212 resultPromise.set_value();
213 });
214 }
215 mCondition.notify_one();
216 resultFuture.wait();
217}
218
Alec Mouria90a5702021-04-16 16:36:21 +0000219void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
220 bool isRenderable) {
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::mapExternalTextureBuffer");
228 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800229 });
230 }
231 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800232}
233
Alec Mouria90a5702021-04-16 16:36:21 +0000234void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700235 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800236 // This function is designed so it can run asynchronously, so we do not need to wait
237 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800238 {
239 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800240 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000241 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
242 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800243 });
244 }
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
258bool RenderEngineThreaded::isProtected() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400259 waitUntilInitialized();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400260 std::lock_guard lock(mThreadMutex);
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -0400261 return mIsProtected;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800262}
263
264bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400265 waitUntilInitialized();
266 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800267}
268
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -0400269void RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
270 if (isProtected() == useProtectedContext ||
271 (useProtectedContext && !supportsProtectedContent())) {
272 return;
273 }
274
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800275 {
276 std::lock_guard lock(mThreadMutex);
Derek Sollenberger1ec2fb52021-06-16 15:11:27 -0400277 mFunctionCalls.push([useProtectedContext, this](renderengine::RenderEngine& instance) {
278 ATRACE_NAME("REThreaded::useProtectedContext");
279 instance.useProtectedContext(useProtectedContext);
280 if (instance.isProtected() != useProtectedContext) {
281 ALOGE("Failed to switch RenderEngine context.");
282 // reset the cached mIsProtected value to a good state, but this does not
283 // prevent other callers of this method and isProtected from reading the
284 // invalid cached value.
285 mIsProtected = instance.isProtected();
286 }
287 });
288 mIsProtected = useProtectedContext;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800289 }
290 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800291}
292
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400293void RenderEngineThreaded::cleanupPostRender() {
294 if (canSkipPostRenderCleanup()) {
295 return;
296 }
297
298 // This function is designed so it can run asynchronously, so we do not need to wait
299 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800300 {
301 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400302 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Leon Scroggins III1e34a702021-08-24 15:13:32 -0400303 ATRACE_NAME("REThreaded::cleanupPostRender");
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400304 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800305 });
306 }
307 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400308}
309
310bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
311 waitUntilInitialized();
312 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800313}
314
Sally Qi4cabdd02021-08-05 16:45:57 -0700315void RenderEngineThreaded::drawLayersInternal(
316 const std::shared_ptr<std::promise<RenderEngineResult>>&& resultPromise,
Sally Qi59a9f502021-10-12 18:53:23 +0000317 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700318 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
319 base::unique_fd&& bufferFence) {
320 resultPromise->set_value({NO_ERROR, base::unique_fd()});
321 return;
322}
323
324std::future<RenderEngineResult> RenderEngineThreaded::drawLayers(
Sally Qi59a9f502021-10-12 18:53:23 +0000325 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700326 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
327 base::unique_fd&& bufferFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700328 ATRACE_CALL();
Sally Qi4cabdd02021-08-05 16:45:57 -0700329 const auto resultPromise = std::make_shared<std::promise<RenderEngineResult>>();
330 std::future<RenderEngineResult> resultFuture = resultPromise->get_future();
Sally Qi59a9f502021-10-12 18:53:23 +0000331 int fd = bufferFence.release();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800332 {
333 std::lock_guard lock(mThreadMutex);
Sally Qi59a9f502021-10-12 18:53:23 +0000334 mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache,
335 fd](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800336 ATRACE_NAME("REThreaded::drawLayers");
Sally Qi4cabdd02021-08-05 16:45:57 -0700337 instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
Sally Qi59a9f502021-10-12 18:53:23 +0000338 useFramebufferCache, base::unique_fd(fd));
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800339 });
340 }
341 mCondition.notify_one();
Sally Qi4cabdd02021-08-05 16:45:57 -0700342 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800343}
344
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200345void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700346 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400347 // This function is designed so it can run asynchronously, so we do not need to wait
348 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200349 {
350 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400351 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200352 ATRACE_NAME("REThreaded::cleanFramebufferCache");
353 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200354 });
355 }
356 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200357}
358
Alec Mourid6f09462020-12-07 11:18:17 -0800359int RenderEngineThreaded::getContextPriority() {
360 std::promise<int> resultPromise;
361 std::future<int> resultFuture = resultPromise.get_future();
362 {
363 std::lock_guard lock(mThreadMutex);
364 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
365 ATRACE_NAME("REThreaded::getContextPriority");
366 int priority = instance.getContextPriority();
367 resultPromise.set_value(priority);
368 });
369 }
370 mCondition.notify_one();
371 return resultFuture.get();
372}
373
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500374bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400375 waitUntilInitialized();
376 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500377}
378
Ady Abrahamed3290f2021-05-17 15:12:14 -0700379void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400380 // This function is designed so it can run asynchronously, so we do not need to wait
381 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400382 {
383 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400384 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Ady Abrahamed3290f2021-05-17 15:12:14 -0700385 ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
386 instance.onActiveDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400387 });
388 }
389 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400390}
391
Matt Buckleyef51fba2021-10-12 19:30:12 +0000392std::optional<pid_t> RenderEngineThreaded::getRenderEngineTid() const {
393 std::promise<pid_t> tidPromise;
394 std::future<pid_t> tidFuture = tidPromise.get_future();
395 {
396 std::lock_guard lock(mThreadMutex);
397 mFunctionCalls.push([&tidPromise](renderengine::RenderEngine& instance) {
398 tidPromise.set_value(gettid());
399 });
400 }
401
402 mCondition.notify_one();
403 return std::make_optional(tidFuture.get());
404}
405
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800406} // namespace threaded
407} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700408} // namespace android