Loading libs/renderengine/include/renderengine/RenderEngine.h +6 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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. Loading libs/renderengine/tests/RenderEngineThreadedTest.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading libs/renderengine/threaded/RenderEngineThreaded.cpp +33 −75 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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) { Loading Loading @@ -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(); { waitUntilInitialized(); // ensure that useProtectedContext is not currently being changed by some // other thread. 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(); 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) { Loading Loading @@ -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() { Loading @@ -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 Loading libs/renderengine/threaded/RenderEngineThreaded.h +7 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ public: private: void threadMain(CreateInstanceFactory factory); void waitUntilInitialized() const; /* ------------------------------------------------------------------------ * Threading Loading @@ -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 */ Loading Loading
libs/renderengine/include/renderengine/RenderEngine.h +6 −2 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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. Loading
libs/renderengine/tests/RenderEngineThreadedTest.cpp +3 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
libs/renderengine/threaded/RenderEngineThreaded.cpp +33 −75 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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) { Loading Loading @@ -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(); { waitUntilInitialized(); // ensure that useProtectedContext is not currently being changed by some // other thread. 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(); 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) { Loading Loading @@ -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() { Loading @@ -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 Loading
libs/renderengine/threaded/RenderEngineThreaded.h +7 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,7 @@ public: private: void threadMain(CreateInstanceFactory factory); void waitUntilInitialized() const; /* ------------------------------------------------------------------------ * Threading Loading @@ -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 */ Loading