blob: 8aa41b3e50796d233e0d7191c6d493e129bc6fff [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();
Ana Krulec9bc9dc62020-02-26 12:16:40 -080093
Ana Krulec9bc9dc62020-02-26 12:16:40 -080094 pthread_setname_np(pthread_self(), mThreadName);
95
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040096 {
Alec Mouri39d9cb72021-06-10 10:26:15 -070097 std::scoped_lock lock(mInitializedMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -040098 mIsInitialized = true;
99 }
100 mInitializedCondition.notify_all();
101
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800102 while (mRunning) {
Alec Mouri39d9cb72021-06-10 10:26:15 -0700103 const auto getNextTask = [this]() -> std::optional<Work> {
104 std::scoped_lock lock(mThreadMutex);
105 if (!mFunctionCalls.empty()) {
106 Work task = mFunctionCalls.front();
107 mFunctionCalls.pop();
108 return std::make_optional<Work>(task);
109 }
110 return std::nullopt;
111 };
112
113 const auto task = getNextTask();
114
115 if (task) {
116 (*task)(*mRenderEngine);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800117 }
Alec Mouri39d9cb72021-06-10 10:26:15 -0700118
119 std::unique_lock<std::mutex> lock(mThreadMutex);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800120 mCondition.wait(lock, [this]() REQUIRES(mThreadMutex) {
121 return !mRunning || !mFunctionCalls.empty();
122 });
123 }
Derek Sollenberger40dcb022021-04-14 10:28:27 -0400124
125 // we must release the RenderEngine on the thread that created it
126 mRenderEngine.reset();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800127}
128
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400129void RenderEngineThreaded::waitUntilInitialized() const {
130 std::unique_lock<std::mutex> lock(mInitializedMutex);
131 mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
132}
133
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700134std::future<void> RenderEngineThreaded::primeCache() {
135 const auto resultPromise = std::make_shared<std::promise<void>>();
136 std::future<void> resultFuture = resultPromise->get_future();
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700137 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400138 // This function is designed so it can run asynchronously, so we do not need to wait
139 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800140 {
141 std::lock_guard lock(mThreadMutex);
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700142 mFunctionCalls.push([resultPromise](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800143 ATRACE_NAME("REThreaded::primeCache");
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700144 if (setSchedFifo(false) != NO_ERROR) {
145 ALOGW("Couldn't set SCHED_OTHER for primeCache");
146 }
147
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800148 instance.primeCache();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700149 resultPromise->set_value();
150
151 if (setSchedFifo(true) != NO_ERROR) {
152 ALOGW("Couldn't set SCHED_FIFO for primeCache");
153 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800154 });
155 }
156 mCondition.notify_one();
Ady Abrahamfe2a6db2021-06-09 15:41:37 -0700157
158 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800159}
160
161void RenderEngineThreaded::dump(std::string& result) {
162 std::promise<std::string> resultPromise;
163 std::future<std::string> resultFuture = resultPromise.get_future();
164 {
165 std::lock_guard lock(mThreadMutex);
166 mFunctionCalls.push([&resultPromise, &result](renderengine::RenderEngine& instance) {
167 ATRACE_NAME("REThreaded::dump");
168 std::string localResult = result;
169 instance.dump(localResult);
170 resultPromise.set_value(std::move(localResult));
171 });
172 }
173 mCondition.notify_one();
174 // Note: This is an rvalue.
175 result.assign(resultFuture.get());
176}
177
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800178void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700179 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500180 // This is a no-op in SkiaRenderEngine.
181 if (getRenderEngineType() != RenderEngineType::THREADED) {
182 return;
183 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800184 std::promise<void> resultPromise;
185 std::future<void> resultFuture = resultPromise.get_future();
186 {
187 std::lock_guard lock(mThreadMutex);
188 mFunctionCalls.push([&resultPromise, count, names](renderengine::RenderEngine& instance) {
189 ATRACE_NAME("REThreaded::genTextures");
190 instance.genTextures(count, names);
191 resultPromise.set_value();
192 });
193 }
194 mCondition.notify_one();
195 resultFuture.wait();
196}
197
198void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700199 ATRACE_CALL();
Leon Scroggins III48b5f3c2021-12-22 10:05:06 -0500200 // This is a no-op in SkiaRenderEngine.
201 if (getRenderEngineType() != RenderEngineType::THREADED) {
202 return;
203 }
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800204 std::promise<void> resultPromise;
205 std::future<void> resultFuture = resultPromise.get_future();
206 {
207 std::lock_guard lock(mThreadMutex);
208 mFunctionCalls.push([&resultPromise, count, &names](renderengine::RenderEngine& instance) {
209 ATRACE_NAME("REThreaded::deleteTextures");
210 instance.deleteTextures(count, names);
211 resultPromise.set_value();
212 });
213 }
214 mCondition.notify_one();
215 resultFuture.wait();
216}
217
Alec Mouria90a5702021-04-16 16:36:21 +0000218void RenderEngineThreaded::mapExternalTextureBuffer(const sp<GraphicBuffer>& buffer,
219 bool isRenderable) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700220 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800221 // This function is designed so it can run asynchronously, so we do not need to wait
222 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800223 {
224 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800225 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000226 ATRACE_NAME("REThreaded::mapExternalTextureBuffer");
227 instance.mapExternalTextureBuffer(buffer, isRenderable);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800228 });
229 }
230 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800231}
232
Alec Mouria90a5702021-04-16 16:36:21 +0000233void RenderEngineThreaded::unmapExternalTextureBuffer(const sp<GraphicBuffer>& buffer) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700234 ATRACE_CALL();
Ana Krulecdfec8f52021-01-13 12:51:47 -0800235 // This function is designed so it can run asynchronously, so we do not need to wait
236 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800237 {
238 std::lock_guard lock(mThreadMutex);
Ana Krulecdfec8f52021-01-13 12:51:47 -0800239 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Alec Mouria90a5702021-04-16 16:36:21 +0000240 ATRACE_NAME("REThreaded::unmapExternalTextureBuffer");
241 instance.unmapExternalTextureBuffer(buffer);
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800242 });
243 }
244 mCondition.notify_one();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800245}
246
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800247size_t RenderEngineThreaded::getMaxTextureSize() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400248 waitUntilInitialized();
249 return mRenderEngine->getMaxTextureSize();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800250}
251
252size_t RenderEngineThreaded::getMaxViewportDims() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400253 waitUntilInitialized();
254 return mRenderEngine->getMaxViewportDims();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800255}
256
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800257bool RenderEngineThreaded::supportsProtectedContent() const {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400258 waitUntilInitialized();
259 return mRenderEngine->supportsProtectedContent();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800260}
261
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400262void RenderEngineThreaded::cleanupPostRender() {
263 if (canSkipPostRenderCleanup()) {
264 return;
265 }
266
267 // This function is designed so it can run asynchronously, so we do not need to wait
268 // for the futures.
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800269 {
270 std::lock_guard lock(mThreadMutex);
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400271 mFunctionCalls.push([=](renderengine::RenderEngine& instance) {
Leon Scroggins III1e34a702021-08-24 15:13:32 -0400272 ATRACE_NAME("REThreaded::cleanupPostRender");
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400273 instance.cleanupPostRender();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800274 });
275 }
276 mCondition.notify_one();
Derek Sollenbergerd3f60652021-06-11 15:34:36 -0400277}
278
279bool RenderEngineThreaded::canSkipPostRenderCleanup() const {
280 waitUntilInitialized();
281 return mRenderEngine->canSkipPostRenderCleanup();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800282}
283
Sally Qi4cabdd02021-08-05 16:45:57 -0700284void RenderEngineThreaded::drawLayersInternal(
Patrick Williams2e9748f2022-08-09 22:48:18 +0000285 const std::shared_ptr<std::promise<FenceResult>>&& resultPromise,
Sally Qi59a9f502021-10-12 18:53:23 +0000286 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700287 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
288 base::unique_fd&& bufferFence) {
Patrick Williams2e9748f2022-08-09 22:48:18 +0000289 resultPromise->set_value(Fence::NO_FENCE);
Sally Qi4cabdd02021-08-05 16:45:57 -0700290 return;
291}
292
Patrick Williams2e9748f2022-08-09 22:48:18 +0000293ftl::Future<FenceResult> RenderEngineThreaded::drawLayers(
Sally Qi59a9f502021-10-12 18:53:23 +0000294 const DisplaySettings& display, const std::vector<LayerSettings>& layers,
Sally Qi4cabdd02021-08-05 16:45:57 -0700295 const std::shared_ptr<ExternalTexture>& buffer, const bool useFramebufferCache,
296 base::unique_fd&& bufferFence) {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700297 ATRACE_CALL();
Patrick Williams2e9748f2022-08-09 22:48:18 +0000298 const auto resultPromise = std::make_shared<std::promise<FenceResult>>();
299 std::future<FenceResult> resultFuture = resultPromise->get_future();
Sally Qi59a9f502021-10-12 18:53:23 +0000300 int fd = bufferFence.release();
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800301 {
302 std::lock_guard lock(mThreadMutex);
Sally Qi59a9f502021-10-12 18:53:23 +0000303 mFunctionCalls.push([resultPromise, display, layers, buffer, useFramebufferCache,
304 fd](renderengine::RenderEngine& instance) {
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800305 ATRACE_NAME("REThreaded::drawLayers");
Patrick Williams8aed5d22022-10-31 22:18:10 +0000306 instance.updateProtectedContext(layers, buffer);
Sally Qi4cabdd02021-08-05 16:45:57 -0700307 instance.drawLayersInternal(std::move(resultPromise), display, layers, buffer,
Sally Qi59a9f502021-10-12 18:53:23 +0000308 useFramebufferCache, base::unique_fd(fd));
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800309 });
310 }
311 mCondition.notify_one();
Sally Qi4cabdd02021-08-05 16:45:57 -0700312 return resultFuture;
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800313}
314
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200315void RenderEngineThreaded::cleanFramebufferCache() {
Ady Abrahamb57e8c22021-05-07 15:17:29 -0700316 ATRACE_CALL();
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400317 // This function is designed so it can run asynchronously, so we do not need to wait
318 // for the futures.
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200319 {
320 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400321 mFunctionCalls.push([](renderengine::RenderEngine& instance) {
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200322 ATRACE_NAME("REThreaded::cleanFramebufferCache");
323 instance.cleanFramebufferCache();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200324 });
325 }
326 mCondition.notify_one();
Marin Shalamanov23c31af2020-09-09 15:01:47 +0200327}
328
Alec Mourid6f09462020-12-07 11:18:17 -0800329int RenderEngineThreaded::getContextPriority() {
330 std::promise<int> resultPromise;
331 std::future<int> resultFuture = resultPromise.get_future();
332 {
333 std::lock_guard lock(mThreadMutex);
334 mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
335 ATRACE_NAME("REThreaded::getContextPriority");
336 int priority = instance.getContextPriority();
337 resultPromise.set_value(priority);
338 });
339 }
340 mCondition.notify_one();
341 return resultFuture.get();
342}
343
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500344bool RenderEngineThreaded::supportsBackgroundBlur() {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400345 waitUntilInitialized();
346 return mRenderEngine->supportsBackgroundBlur();
Derek Sollenbergerb3998372021-02-16 15:16:56 -0500347}
348
Ady Abrahamed3290f2021-05-17 15:12:14 -0700349void RenderEngineThreaded::onActiveDisplaySizeChanged(ui::Size size) {
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400350 // This function is designed so it can run asynchronously, so we do not need to wait
351 // for the futures.
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400352 {
353 std::lock_guard lock(mThreadMutex);
Derek Sollenberger4bea01e2021-04-09 13:59:37 -0400354 mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
Ady Abrahamed3290f2021-05-17 15:12:14 -0700355 ATRACE_NAME("REThreaded::onActiveDisplaySizeChanged");
356 instance.onActiveDisplaySizeChanged(size);
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400357 });
358 }
359 mCondition.notify_one();
Derek Sollenbergerc4a05e12021-03-24 16:45:20 -0400360}
361
Matt Buckleyef51fba2021-10-12 19:30:12 +0000362std::optional<pid_t> RenderEngineThreaded::getRenderEngineTid() const {
363 std::promise<pid_t> tidPromise;
364 std::future<pid_t> tidFuture = tidPromise.get_future();
365 {
366 std::lock_guard lock(mThreadMutex);
367 mFunctionCalls.push([&tidPromise](renderengine::RenderEngine& instance) {
368 tidPromise.set_value(gettid());
369 });
370 }
371
372 mCondition.notify_one();
373 return std::make_optional(tidFuture.get());
374}
375
Leon Scroggins IIIa37ca992022-02-02 18:08:20 -0500376void RenderEngineThreaded::setEnableTracing(bool tracingEnabled) {
377 // This function is designed so it can run asynchronously, so we do not need to wait
378 // for the futures.
379 {
380 std::lock_guard lock(mThreadMutex);
381 mFunctionCalls.push([tracingEnabled](renderengine::RenderEngine& instance) {
382 ATRACE_NAME("REThreaded::setEnableTracing");
383 instance.setEnableTracing(tracingEnabled);
384 });
385 }
386 mCondition.notify_one();
387}
Ana Krulec9bc9dc62020-02-26 12:16:40 -0800388} // namespace threaded
389} // namespace renderengine
Alec Mouri368e1582020-08-13 10:14:29 -0700390} // namespace android