diff options
4 files changed, 49 insertions, 77 deletions
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index a69d1f0da0..8dd98c3ba3 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -141,7 +141,7 @@ public: // 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 @@ public: // ----- 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 @@ public: 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 63aa4c891c..b093e88d4f 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -49,6 +49,9 @@ TEST_F(RenderEngineThreadedTest, dump) { 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 783e37fc22..194c7da1c7 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -74,6 +74,12 @@ void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_S 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::threadMain(CreateInstanceFactory factory) NO_THREAD_S } } +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 @@ void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { } 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 @@ status_t RenderEngineThreaded::drawLayers(const DisplaySettings& display, } 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 @@ int RenderEngineThreaded::getContextPriority() { } 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 117257a90e..61ae9b8cf8 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -70,6 +70,7 @@ public: private: void threadMain(CreateInstanceFactory factory); + void waitUntilInitialized() const; /* ------------------------------------------------------------------------ * Threading @@ -83,6 +84,12 @@ private: 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 */ |