Improve performance for certain queries/functions in REThreaded.
Some queries into RE were already thread safe, but now they are
documented as such and avoid jumping to another thread.
Additionally all void method in REThreaded are executed in an async
strategy.
Test: librenderengine_test
Bug: 184243497
Change-Id: Id04bcccf2c90acc3e6cb6f7716f9629639b757b7
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index a69d1f0..8dd98c3 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -141,7 +141,7 @@
// do any work.
virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0;
- // queries
+ // queries that are required to be thread safe
virtual size_t getMaxTextureSize() const = 0;
virtual size_t getMaxViewportDims() const = 0;
@@ -149,8 +149,11 @@
// ----- BEGIN NEW INTERFACE -----
+ // queries that are required to be thread safe
virtual bool isProtected() const = 0;
virtual bool supportsProtectedContent() const = 0;
+
+ // Attempt to switch RenderEngine into and out of protectedContext mode
virtual bool useProtectedContext(bool useProtectedContext) = 0;
// Notify RenderEngine of changes to the dimensions of the primary display
@@ -197,7 +200,8 @@
virtual int getContextPriority() = 0;
// Returns true if blur was requested in the RenderEngineCreationArgs and the implementation
- // also supports background blur. If false, no blur will be applied when drawing layers.
+ // also supports background blur. If false, no blur will be applied when drawing layers. This
+ // query is required to be thread safe.
virtual bool supportsBackgroundBlur() = 0;
// Returns the current type of RenderEngine instance that was created.
diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
index 63aa4c8..b093e88 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -49,6 +49,9 @@
TEST_F(RenderEngineThreadedTest, primeCache) {
EXPECT_CALL(*mRenderEngine, primeCache());
mThreadedRE->primeCache();
+ // need to call ANY synchronous function after primeCache to ensure that primeCache has
+ // completed asynchronously before the test completes execution.
+ mThreadedRE->getContextPriority();
}
TEST_F(RenderEngineThreadedTest, genTextures) {
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp
index 783e37f..194c7da 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -74,6 +74,12 @@
std::unique_lock<std::mutex> lock(mThreadMutex);
pthread_setname_np(pthread_self(), mThreadName);
+ {
+ std::unique_lock<std::mutex> lock(mInitializedMutex);
+ mIsInitialized = true;
+ }
+ mInitializedCondition.notify_all();
+
while (mRunning) {
if (!mFunctionCalls.empty()) {
auto task = mFunctionCalls.front();
@@ -86,19 +92,22 @@
}
}
+void RenderEngineThreaded::waitUntilInitialized() const {
+ std::unique_lock<std::mutex> lock(mInitializedMutex);
+ mInitializedCondition.wait(lock, [=] { return mIsInitialized; });
+}
+
void RenderEngineThreaded::primeCache() {
- std::promise<void> resultPromise;
- std::future<void> resultFuture = resultPromise.get_future();
+ // This function is designed so it can run asynchronously, so we do not need to wait
+ // for the futures.
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
+ mFunctionCalls.push([](renderengine::RenderEngine& instance) {
ATRACE_NAME("REThreaded::primeCache");
instance.primeCache();
- resultPromise.set_value();
});
}
mCondition.notify_one();
- resultFuture.wait();
}
void RenderEngineThreaded::dump(std::string& result) {
@@ -175,63 +184,26 @@
}
size_t RenderEngineThreaded::getMaxTextureSize() const {
- std::promise<size_t> resultPromise;
- std::future<size_t> resultFuture = resultPromise.get_future();
- {
- std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::getMaxTextureSize");
- size_t size = instance.getMaxTextureSize();
- resultPromise.set_value(size);
- });
- }
- mCondition.notify_one();
- return resultFuture.get();
+ waitUntilInitialized();
+ return mRenderEngine->getMaxTextureSize();
}
size_t RenderEngineThreaded::getMaxViewportDims() const {
- std::promise<size_t> resultPromise;
- std::future<size_t> resultFuture = resultPromise.get_future();
- {
- std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::getMaxViewportDims");
- size_t size = instance.getMaxViewportDims();
- resultPromise.set_value(size);
- });
- }
- mCondition.notify_one();
- return resultFuture.get();
+ waitUntilInitialized();
+ return mRenderEngine->getMaxViewportDims();
}
bool RenderEngineThreaded::isProtected() const {
- std::promise<bool> resultPromise;
- std::future<bool> resultFuture = resultPromise.get_future();
- {
- std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::isProtected");
- bool returnValue = instance.isProtected();
- resultPromise.set_value(returnValue);
- });
- }
- mCondition.notify_one();
- return resultFuture.get();
+ waitUntilInitialized();
+ // ensure that useProtectedContext is not currently being changed by some
+ // other thread.
+ std::lock_guard lock(mThreadMutex);
+ return mRenderEngine->isProtected();
}
bool RenderEngineThreaded::supportsProtectedContent() const {
- std::promise<bool> resultPromise;
- std::future<bool> resultFuture = resultPromise.get_future();
- {
- std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::supportsProtectedContent");
- bool returnValue = instance.supportsProtectedContent();
- resultPromise.set_value(returnValue);
- });
- }
- mCondition.notify_one();
- return resultFuture.get();
+ waitUntilInitialized();
+ return mRenderEngine->supportsProtectedContent();
}
bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) {
@@ -288,18 +260,16 @@
}
void RenderEngineThreaded::cleanFramebufferCache() {
- std::promise<void> resultPromise;
- std::future<void> resultFuture = resultPromise.get_future();
+ // This function is designed so it can run asynchronously, so we do not need to wait
+ // for the futures.
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
+ mFunctionCalls.push([](renderengine::RenderEngine& instance) {
ATRACE_NAME("REThreaded::cleanFramebufferCache");
instance.cleanFramebufferCache();
- resultPromise.set_value();
});
}
mCondition.notify_one();
- resultFuture.wait();
}
int RenderEngineThreaded::getContextPriority() {
@@ -318,33 +288,21 @@
}
bool RenderEngineThreaded::supportsBackgroundBlur() {
- std::promise<bool> resultPromise;
- std::future<bool> resultFuture = resultPromise.get_future();
- {
- std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) {
- ATRACE_NAME("REThreaded::supportsBackgroundBlur");
- bool returnValue = instance.supportsBackgroundBlur();
- resultPromise.set_value(returnValue);
- });
- }
- mCondition.notify_one();
- return resultFuture.get();
+ waitUntilInitialized();
+ return mRenderEngine->supportsBackgroundBlur();
}
void RenderEngineThreaded::onPrimaryDisplaySizeChanged(ui::Size size) {
- std::promise<void> resultPromise;
- std::future<void> resultFuture = resultPromise.get_future();
+ // This function is designed so it can run asynchronously, so we do not need to wait
+ // for the futures.
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise, size](renderengine::RenderEngine& instance) {
+ mFunctionCalls.push([size](renderengine::RenderEngine& instance) {
ATRACE_NAME("REThreaded::onPrimaryDisplaySizeChanged");
instance.onPrimaryDisplaySizeChanged(size);
- resultPromise.set_value();
});
}
mCondition.notify_one();
- resultFuture.wait();
}
} // namespace threaded
diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h
index 117257a..61ae9b8 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.h
+++ b/libs/renderengine/threaded/RenderEngineThreaded.h
@@ -70,6 +70,7 @@
private:
void threadMain(CreateInstanceFactory factory);
+ void waitUntilInitialized() const;
/* ------------------------------------------------------------------------
* Threading
@@ -83,6 +84,12 @@
GUARDED_BY(mThreadMutex);
mutable std::condition_variable mCondition;
+ // Used to allow select thread safe methods to be accessed without requiring the
+ // method to be invoked on the RenderEngine thread
+ bool mIsInitialized = false;
+ mutable std::mutex mInitializedMutex;
+ mutable std::condition_variable mInitializedCondition;
+
/* ------------------------------------------------------------------------
* Render Engine
*/