Loading libs/renderengine/RenderEngine.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ namespace android { namespace renderengine { std::unique_ptr<impl::RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) { std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) { RenderEngineType renderEngineType = args.renderEngineType; // Keep the ability to override by PROPERTIES: Loading @@ -41,7 +41,9 @@ std::unique_ptr<impl::RenderEngine> RenderEngine::create(const RenderEngineCreat switch (renderEngineType) { case RenderEngineType::THREADED: ALOGD("Threaded RenderEngine with GLES Backend"); return renderengine::threaded::RenderEngineThreaded::create(args); return renderengine::threaded::RenderEngineThreaded::create([&args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); case RenderEngineType::GLES: default: ALOGD("RenderEngine with GLES Backend"); Loading libs/renderengine/include/renderengine/RenderEngine.h +1 −1 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ public: THREADED = 2, }; static std::unique_ptr<impl::RenderEngine> create(const RenderEngineCreationArgs& args); static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args); virtual ~RenderEngine() = 0; Loading libs/renderengine/tests/RenderEngineThreadedTest.cpp +29 −41 Original line number Diff line number Diff line Loading @@ -28,56 +28,44 @@ using testing::Mock; using testing::Return; struct RenderEngineThreadedTest : public ::testing::Test { RenderEngineThreadedTest() { sThreadedRE->setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine)); } ~RenderEngineThreadedTest() {} static void SetUpTestSuite() { sThreadedRE = renderengine::threaded::RenderEngineThreaded::create( renderengine::RenderEngineCreationArgs::Builder() .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::THREADED) .build()); void SetUp() override { mThreadedRE = renderengine::threaded::RenderEngineThreaded::create( [this]() { return std::unique_ptr<renderengine::RenderEngine>(mRenderEngine); }); } static void TearDownTestSuite() { sThreadedRE = nullptr; } // To avoid creating RE on every instantiation of the test, it is kept as a static variable. static std::unique_ptr<renderengine::threaded::RenderEngineThreaded> sThreadedRE; std::unique_ptr<renderengine::threaded::RenderEngineThreaded> mThreadedRE; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); }; std::unique_ptr<renderengine::threaded::RenderEngineThreaded> RenderEngineThreadedTest::sThreadedRE = nullptr; TEST_F(RenderEngineThreadedTest, dump) { std::string testString = "XYZ"; EXPECT_CALL(*mRenderEngine, dump(_)); sThreadedRE->dump(testString); mThreadedRE->dump(testString); } TEST_F(RenderEngineThreadedTest, primeCache) { EXPECT_CALL(*mRenderEngine, primeCache()); sThreadedRE->primeCache(); mThreadedRE->primeCache(); } TEST_F(RenderEngineThreadedTest, genTextures) { uint32_t texName; EXPECT_CALL(*mRenderEngine, genTextures(1, &texName)); sThreadedRE->genTextures(1, &texName); mThreadedRE->genTextures(1, &texName); } TEST_F(RenderEngineThreadedTest, deleteTextures) { uint32_t texName; EXPECT_CALL(*mRenderEngine, deleteTextures(1, &texName)); sThreadedRE->deleteTextures(1, &texName); mThreadedRE->deleteTextures(1, &texName); } TEST_F(RenderEngineThreadedTest, bindExternalBuffer_nullptrBuffer) { EXPECT_CALL(*mRenderEngine, bindExternalTextureBuffer(0, Eq(nullptr), Eq(nullptr))) .WillOnce(Return(BAD_VALUE)); status_t result = sThreadedRE->bindExternalTextureBuffer(0, nullptr, nullptr); status_t result = mThreadedRE->bindExternalTextureBuffer(0, nullptr, nullptr); ASSERT_EQ(BAD_VALUE, result); } Loading @@ -85,119 +73,119 @@ TEST_F(RenderEngineThreadedTest, bindExternalBuffer_withBuffer) { sp<GraphicBuffer> buf = new GraphicBuffer(); EXPECT_CALL(*mRenderEngine, bindExternalTextureBuffer(0, buf, Eq(nullptr))) .WillOnce(Return(NO_ERROR)); status_t result = sThreadedRE->bindExternalTextureBuffer(0, buf, nullptr); status_t result = mThreadedRE->bindExternalTextureBuffer(0, buf, nullptr); ASSERT_EQ(NO_ERROR, result); } TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_nullptr) { EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(Eq(nullptr))); sThreadedRE->cacheExternalTextureBuffer(nullptr); mThreadedRE->cacheExternalTextureBuffer(nullptr); } TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_withBuffer) { sp<GraphicBuffer> buf = new GraphicBuffer(); EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(buf)); sThreadedRE->cacheExternalTextureBuffer(buf); mThreadedRE->cacheExternalTextureBuffer(buf); } TEST_F(RenderEngineThreadedTest, unbindExternalTextureBuffer) { EXPECT_CALL(*mRenderEngine, unbindExternalTextureBuffer(0x0)); sThreadedRE->unbindExternalTextureBuffer(0x0); mThreadedRE->unbindExternalTextureBuffer(0x0); } TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsBadValue) { std::unique_ptr<renderengine::Framebuffer> framebuffer; EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(BAD_VALUE)); status_t result = sThreadedRE->bindFrameBuffer(framebuffer.get()); status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get()); ASSERT_EQ(BAD_VALUE, result); } TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsNoError) { std::unique_ptr<renderengine::Framebuffer> framebuffer; EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(NO_ERROR)); status_t result = sThreadedRE->bindFrameBuffer(framebuffer.get()); status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get()); ASSERT_EQ(NO_ERROR, result); } TEST_F(RenderEngineThreadedTest, unbindFrameBuffer) { std::unique_ptr<renderengine::Framebuffer> framebuffer; EXPECT_CALL(*mRenderEngine, unbindFrameBuffer(framebuffer.get())); sThreadedRE->unbindFrameBuffer(framebuffer.get()); mThreadedRE->unbindFrameBuffer(framebuffer.get()); } TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) { size_t size = 20; EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size)); size_t result = sThreadedRE->getMaxTextureSize(); size_t result = mThreadedRE->getMaxTextureSize(); ASSERT_EQ(size, result); } TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns0) { size_t size = 0; EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size)); size_t result = sThreadedRE->getMaxTextureSize(); size_t result = mThreadedRE->getMaxTextureSize(); ASSERT_EQ(size, result); } TEST_F(RenderEngineThreadedTest, getMaxViewportDims_returns20) { size_t dims = 20; EXPECT_CALL(*mRenderEngine, getMaxViewportDims()).WillOnce(Return(dims)); size_t result = sThreadedRE->getMaxViewportDims(); size_t result = mThreadedRE->getMaxViewportDims(); ASSERT_EQ(dims, result); } TEST_F(RenderEngineThreadedTest, getMaxViewportDims_returns0) { size_t dims = 0; EXPECT_CALL(*mRenderEngine, getMaxViewportDims()).WillOnce(Return(dims)); size_t result = sThreadedRE->getMaxViewportDims(); size_t result = mThreadedRE->getMaxViewportDims(); ASSERT_EQ(dims, result); } TEST_F(RenderEngineThreadedTest, isProtected_returnsFalse) { EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(false)); status_t result = sThreadedRE->isProtected(); status_t result = mThreadedRE->isProtected(); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, isProtected_returnsTrue) { EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(true)); size_t result = sThreadedRE->isProtected(); size_t result = mThreadedRE->isProtected(); ASSERT_EQ(true, result); } TEST_F(RenderEngineThreadedTest, supportsProtectedContent_returnsFalse) { EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(false)); status_t result = sThreadedRE->supportsProtectedContent(); status_t result = mThreadedRE->supportsProtectedContent(); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, supportsProtectedContent_returnsTrue) { EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(true)); status_t result = sThreadedRE->supportsProtectedContent(); status_t result = mThreadedRE->supportsProtectedContent(); ASSERT_EQ(true, result); } TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsFalse) { EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(false)); status_t result = sThreadedRE->useProtectedContext(false); status_t result = mThreadedRE->useProtectedContext(false); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsTrue) { EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(true)); status_t result = sThreadedRE->useProtectedContext(false); status_t result = mThreadedRE->useProtectedContext(false); ASSERT_EQ(true, result); } TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsFalse) { EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return(false)); status_t result = sThreadedRE->cleanupPostRender(); status_t result = mThreadedRE->cleanupPostRender(); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsTrue) { EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return(true)); status_t result = sThreadedRE->cleanupPostRender(); status_t result = mThreadedRE->cleanupPostRender(); ASSERT_EQ(true, result); } Loading @@ -214,7 +202,7 @@ TEST_F(RenderEngineThreadedTest, drawLayers) { const sp<GraphicBuffer>&, const bool, base::unique_fd&&, base::unique_fd*) -> status_t { return NO_ERROR; }); status_t result = sThreadedRE->drawLayers(settings, layers, buffer, false, status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence), &drawFence); ASSERT_EQ(NO_ERROR, result); } Loading libs/renderengine/threaded/RenderEngineThreaded.cpp +37 −28 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <future> #include <android-base/stringprintf.h> #include <private/gui/SyncFeatures.h> #include <utils/Trace.h> #include "gl/GLESRenderEngine.h" Loading @@ -33,36 +34,15 @@ namespace android { namespace renderengine { namespace threaded { std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create( const RenderEngineCreationArgs& args) { return std::make_unique<RenderEngineThreaded>(args); std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory) { return std::make_unique<RenderEngineThreaded>(std::move(factory)); } void RenderEngineThreaded::setRenderEngine( std::unique_ptr<renderengine::RenderEngine> renderEngine) { ATRACE_CALL(); // In order to ensure this is a thread safe call, it also needs to be put on a stack. std::promise<void> resultPromise; std::future<void> resultFuture = resultPromise.get_future(); { std::lock_guard lock(mThreadMutex); mFunctionCalls.push( [this, &resultPromise, &renderEngine](renderengine::RenderEngine& /*instance*/) { ATRACE_NAME("REThreaded::setRenderEngine"); mRenderEngine = std::move(renderEngine); resultPromise.set_value(); }); } mCondition.notify_one(); resultFuture.wait(); } RenderEngineThreaded::RenderEngineThreaded(const RenderEngineCreationArgs& args) : renderengine::impl::RenderEngine(args) { RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory) { ATRACE_CALL(); std::lock_guard lockThread(mThreadMutex); mThread = std::thread(&RenderEngineThreaded::threadMain, this, args); mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory); } RenderEngineThreaded::~RenderEngineThreaded() { Loading @@ -78,8 +58,7 @@ RenderEngineThreaded::~RenderEngineThreaded() { } // NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations. void RenderEngineThreaded::threadMain(const RenderEngineCreationArgs& args) NO_THREAD_SAFETY_ANALYSIS { void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); struct sched_param param = {0}; Loading @@ -88,7 +67,7 @@ void RenderEngineThreaded::threadMain(const RenderEngineCreationArgs& args) ALOGE("Couldn't set SCHED_FIFO"); } mRenderEngine = renderengine::gl::GLESRenderEngine::create(args); mRenderEngine = factory(); std::unique_lock<std::mutex> lock(mThreadMutex); pthread_setname_np(pthread_self(), mThreadName); Loading Loading @@ -137,6 +116,36 @@ void RenderEngineThreaded::dump(std::string& result) { result.assign(resultFuture.get()); } bool RenderEngineThreaded::useNativeFenceSync() 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::useNativeFenceSync"); bool returnValue = SyncFeatures::getInstance().useNativeFenceSync(); resultPromise.set_value(returnValue); }); } mCondition.notify_one(); return resultFuture.get(); } bool RenderEngineThreaded::useWaitSync() 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::useWaitSync"); bool returnValue = SyncFeatures::getInstance().useWaitSync(); resultPromise.set_value(returnValue); }); } mCondition.notify_one(); return resultFuture.get(); } void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) { std::promise<void> resultPromise; std::future<void> resultFuture = resultPromise.get_future(); Loading libs/renderengine/threaded/RenderEngineThreaded.h +8 −5 Original line number Diff line number Diff line Loading @@ -28,21 +28,25 @@ namespace android { namespace renderengine { namespace threaded { using CreateInstanceFactory = std::function<std::unique_ptr<renderengine::RenderEngine>()>; /** * This class extends a basic RenderEngine class. It contains a thread. Each time a function of * this class is called, we create a lambda function that is put on a queue. The main thread then * executes the functions in order. */ class RenderEngineThreaded : public impl::RenderEngine { class RenderEngineThreaded : public RenderEngine { public: static std::unique_ptr<RenderEngineThreaded> create(const RenderEngineCreationArgs& args); static std::unique_ptr<RenderEngineThreaded> create(CreateInstanceFactory factory); RenderEngineThreaded(const RenderEngineCreationArgs& args); RenderEngineThreaded(CreateInstanceFactory factory); ~RenderEngineThreaded() override; void primeCache() const override; void dump(std::string& result) override; bool useNativeFenceSync() const override; bool useWaitSync() const override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; void bindExternalTextureImage(uint32_t texName, const Image& image) override; Loading @@ -64,13 +68,12 @@ public: const std::vector<const LayerSettings*>& layers, const sp<GraphicBuffer>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>); protected: Framebuffer* getFramebufferForDrawing() override; private: void threadMain(const RenderEngineCreationArgs& args); void threadMain(CreateInstanceFactory factory); /* ------------------------------------------------------------------------ * Threading Loading Loading
libs/renderengine/RenderEngine.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -25,7 +25,7 @@ namespace android { namespace renderengine { std::unique_ptr<impl::RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) { std::unique_ptr<RenderEngine> RenderEngine::create(const RenderEngineCreationArgs& args) { RenderEngineType renderEngineType = args.renderEngineType; // Keep the ability to override by PROPERTIES: Loading @@ -41,7 +41,9 @@ std::unique_ptr<impl::RenderEngine> RenderEngine::create(const RenderEngineCreat switch (renderEngineType) { case RenderEngineType::THREADED: ALOGD("Threaded RenderEngine with GLES Backend"); return renderengine::threaded::RenderEngineThreaded::create(args); return renderengine::threaded::RenderEngineThreaded::create([&args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); case RenderEngineType::GLES: default: ALOGD("RenderEngine with GLES Backend"); Loading
libs/renderengine/include/renderengine/RenderEngine.h +1 −1 Original line number Diff line number Diff line Loading @@ -76,7 +76,7 @@ public: THREADED = 2, }; static std::unique_ptr<impl::RenderEngine> create(const RenderEngineCreationArgs& args); static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args); virtual ~RenderEngine() = 0; Loading
libs/renderengine/tests/RenderEngineThreadedTest.cpp +29 −41 Original line number Diff line number Diff line Loading @@ -28,56 +28,44 @@ using testing::Mock; using testing::Return; struct RenderEngineThreadedTest : public ::testing::Test { RenderEngineThreadedTest() { sThreadedRE->setRenderEngine(std::unique_ptr<renderengine::RenderEngine>(mRenderEngine)); } ~RenderEngineThreadedTest() {} static void SetUpTestSuite() { sThreadedRE = renderengine::threaded::RenderEngineThreaded::create( renderengine::RenderEngineCreationArgs::Builder() .setRenderEngineType(renderengine::RenderEngine::RenderEngineType::THREADED) .build()); void SetUp() override { mThreadedRE = renderengine::threaded::RenderEngineThreaded::create( [this]() { return std::unique_ptr<renderengine::RenderEngine>(mRenderEngine); }); } static void TearDownTestSuite() { sThreadedRE = nullptr; } // To avoid creating RE on every instantiation of the test, it is kept as a static variable. static std::unique_ptr<renderengine::threaded::RenderEngineThreaded> sThreadedRE; std::unique_ptr<renderengine::threaded::RenderEngineThreaded> mThreadedRE; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); }; std::unique_ptr<renderengine::threaded::RenderEngineThreaded> RenderEngineThreadedTest::sThreadedRE = nullptr; TEST_F(RenderEngineThreadedTest, dump) { std::string testString = "XYZ"; EXPECT_CALL(*mRenderEngine, dump(_)); sThreadedRE->dump(testString); mThreadedRE->dump(testString); } TEST_F(RenderEngineThreadedTest, primeCache) { EXPECT_CALL(*mRenderEngine, primeCache()); sThreadedRE->primeCache(); mThreadedRE->primeCache(); } TEST_F(RenderEngineThreadedTest, genTextures) { uint32_t texName; EXPECT_CALL(*mRenderEngine, genTextures(1, &texName)); sThreadedRE->genTextures(1, &texName); mThreadedRE->genTextures(1, &texName); } TEST_F(RenderEngineThreadedTest, deleteTextures) { uint32_t texName; EXPECT_CALL(*mRenderEngine, deleteTextures(1, &texName)); sThreadedRE->deleteTextures(1, &texName); mThreadedRE->deleteTextures(1, &texName); } TEST_F(RenderEngineThreadedTest, bindExternalBuffer_nullptrBuffer) { EXPECT_CALL(*mRenderEngine, bindExternalTextureBuffer(0, Eq(nullptr), Eq(nullptr))) .WillOnce(Return(BAD_VALUE)); status_t result = sThreadedRE->bindExternalTextureBuffer(0, nullptr, nullptr); status_t result = mThreadedRE->bindExternalTextureBuffer(0, nullptr, nullptr); ASSERT_EQ(BAD_VALUE, result); } Loading @@ -85,119 +73,119 @@ TEST_F(RenderEngineThreadedTest, bindExternalBuffer_withBuffer) { sp<GraphicBuffer> buf = new GraphicBuffer(); EXPECT_CALL(*mRenderEngine, bindExternalTextureBuffer(0, buf, Eq(nullptr))) .WillOnce(Return(NO_ERROR)); status_t result = sThreadedRE->bindExternalTextureBuffer(0, buf, nullptr); status_t result = mThreadedRE->bindExternalTextureBuffer(0, buf, nullptr); ASSERT_EQ(NO_ERROR, result); } TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_nullptr) { EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(Eq(nullptr))); sThreadedRE->cacheExternalTextureBuffer(nullptr); mThreadedRE->cacheExternalTextureBuffer(nullptr); } TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_withBuffer) { sp<GraphicBuffer> buf = new GraphicBuffer(); EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(buf)); sThreadedRE->cacheExternalTextureBuffer(buf); mThreadedRE->cacheExternalTextureBuffer(buf); } TEST_F(RenderEngineThreadedTest, unbindExternalTextureBuffer) { EXPECT_CALL(*mRenderEngine, unbindExternalTextureBuffer(0x0)); sThreadedRE->unbindExternalTextureBuffer(0x0); mThreadedRE->unbindExternalTextureBuffer(0x0); } TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsBadValue) { std::unique_ptr<renderengine::Framebuffer> framebuffer; EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(BAD_VALUE)); status_t result = sThreadedRE->bindFrameBuffer(framebuffer.get()); status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get()); ASSERT_EQ(BAD_VALUE, result); } TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsNoError) { std::unique_ptr<renderengine::Framebuffer> framebuffer; EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(NO_ERROR)); status_t result = sThreadedRE->bindFrameBuffer(framebuffer.get()); status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get()); ASSERT_EQ(NO_ERROR, result); } TEST_F(RenderEngineThreadedTest, unbindFrameBuffer) { std::unique_ptr<renderengine::Framebuffer> framebuffer; EXPECT_CALL(*mRenderEngine, unbindFrameBuffer(framebuffer.get())); sThreadedRE->unbindFrameBuffer(framebuffer.get()); mThreadedRE->unbindFrameBuffer(framebuffer.get()); } TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) { size_t size = 20; EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size)); size_t result = sThreadedRE->getMaxTextureSize(); size_t result = mThreadedRE->getMaxTextureSize(); ASSERT_EQ(size, result); } TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns0) { size_t size = 0; EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size)); size_t result = sThreadedRE->getMaxTextureSize(); size_t result = mThreadedRE->getMaxTextureSize(); ASSERT_EQ(size, result); } TEST_F(RenderEngineThreadedTest, getMaxViewportDims_returns20) { size_t dims = 20; EXPECT_CALL(*mRenderEngine, getMaxViewportDims()).WillOnce(Return(dims)); size_t result = sThreadedRE->getMaxViewportDims(); size_t result = mThreadedRE->getMaxViewportDims(); ASSERT_EQ(dims, result); } TEST_F(RenderEngineThreadedTest, getMaxViewportDims_returns0) { size_t dims = 0; EXPECT_CALL(*mRenderEngine, getMaxViewportDims()).WillOnce(Return(dims)); size_t result = sThreadedRE->getMaxViewportDims(); size_t result = mThreadedRE->getMaxViewportDims(); ASSERT_EQ(dims, result); } TEST_F(RenderEngineThreadedTest, isProtected_returnsFalse) { EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(false)); status_t result = sThreadedRE->isProtected(); status_t result = mThreadedRE->isProtected(); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, isProtected_returnsTrue) { EXPECT_CALL(*mRenderEngine, isProtected()).WillOnce(Return(true)); size_t result = sThreadedRE->isProtected(); size_t result = mThreadedRE->isProtected(); ASSERT_EQ(true, result); } TEST_F(RenderEngineThreadedTest, supportsProtectedContent_returnsFalse) { EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(false)); status_t result = sThreadedRE->supportsProtectedContent(); status_t result = mThreadedRE->supportsProtectedContent(); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, supportsProtectedContent_returnsTrue) { EXPECT_CALL(*mRenderEngine, supportsProtectedContent()).WillOnce(Return(true)); status_t result = sThreadedRE->supportsProtectedContent(); status_t result = mThreadedRE->supportsProtectedContent(); ASSERT_EQ(true, result); } TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsFalse) { EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(false)); status_t result = sThreadedRE->useProtectedContext(false); status_t result = mThreadedRE->useProtectedContext(false); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, useProtectedContext_returnsTrue) { EXPECT_CALL(*mRenderEngine, useProtectedContext(false)).WillOnce(Return(true)); status_t result = sThreadedRE->useProtectedContext(false); status_t result = mThreadedRE->useProtectedContext(false); ASSERT_EQ(true, result); } TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsFalse) { EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return(false)); status_t result = sThreadedRE->cleanupPostRender(); status_t result = mThreadedRE->cleanupPostRender(); ASSERT_EQ(false, result); } TEST_F(RenderEngineThreadedTest, cleanupPostRender_returnsTrue) { EXPECT_CALL(*mRenderEngine, cleanupPostRender()).WillOnce(Return(true)); status_t result = sThreadedRE->cleanupPostRender(); status_t result = mThreadedRE->cleanupPostRender(); ASSERT_EQ(true, result); } Loading @@ -214,7 +202,7 @@ TEST_F(RenderEngineThreadedTest, drawLayers) { const sp<GraphicBuffer>&, const bool, base::unique_fd&&, base::unique_fd*) -> status_t { return NO_ERROR; }); status_t result = sThreadedRE->drawLayers(settings, layers, buffer, false, status_t result = mThreadedRE->drawLayers(settings, layers, buffer, false, std::move(bufferFence), &drawFence); ASSERT_EQ(NO_ERROR, result); } Loading
libs/renderengine/threaded/RenderEngineThreaded.cpp +37 −28 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <future> #include <android-base/stringprintf.h> #include <private/gui/SyncFeatures.h> #include <utils/Trace.h> #include "gl/GLESRenderEngine.h" Loading @@ -33,36 +34,15 @@ namespace android { namespace renderengine { namespace threaded { std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create( const RenderEngineCreationArgs& args) { return std::make_unique<RenderEngineThreaded>(args); std::unique_ptr<RenderEngineThreaded> RenderEngineThreaded::create(CreateInstanceFactory factory) { return std::make_unique<RenderEngineThreaded>(std::move(factory)); } void RenderEngineThreaded::setRenderEngine( std::unique_ptr<renderengine::RenderEngine> renderEngine) { ATRACE_CALL(); // In order to ensure this is a thread safe call, it also needs to be put on a stack. std::promise<void> resultPromise; std::future<void> resultFuture = resultPromise.get_future(); { std::lock_guard lock(mThreadMutex); mFunctionCalls.push( [this, &resultPromise, &renderEngine](renderengine::RenderEngine& /*instance*/) { ATRACE_NAME("REThreaded::setRenderEngine"); mRenderEngine = std::move(renderEngine); resultPromise.set_value(); }); } mCondition.notify_one(); resultFuture.wait(); } RenderEngineThreaded::RenderEngineThreaded(const RenderEngineCreationArgs& args) : renderengine::impl::RenderEngine(args) { RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory) { ATRACE_CALL(); std::lock_guard lockThread(mThreadMutex); mThread = std::thread(&RenderEngineThreaded::threadMain, this, args); mThread = std::thread(&RenderEngineThreaded::threadMain, this, factory); } RenderEngineThreaded::~RenderEngineThreaded() { Loading @@ -78,8 +58,7 @@ RenderEngineThreaded::~RenderEngineThreaded() { } // NO_THREAD_SAFETY_ANALYSIS is because std::unique_lock presently lacks thread safety annotations. void RenderEngineThreaded::threadMain(const RenderEngineCreationArgs& args) NO_THREAD_SAFETY_ANALYSIS { void RenderEngineThreaded::threadMain(CreateInstanceFactory factory) NO_THREAD_SAFETY_ANALYSIS { ATRACE_CALL(); struct sched_param param = {0}; Loading @@ -88,7 +67,7 @@ void RenderEngineThreaded::threadMain(const RenderEngineCreationArgs& args) ALOGE("Couldn't set SCHED_FIFO"); } mRenderEngine = renderengine::gl::GLESRenderEngine::create(args); mRenderEngine = factory(); std::unique_lock<std::mutex> lock(mThreadMutex); pthread_setname_np(pthread_self(), mThreadName); Loading Loading @@ -137,6 +116,36 @@ void RenderEngineThreaded::dump(std::string& result) { result.assign(resultFuture.get()); } bool RenderEngineThreaded::useNativeFenceSync() 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::useNativeFenceSync"); bool returnValue = SyncFeatures::getInstance().useNativeFenceSync(); resultPromise.set_value(returnValue); }); } mCondition.notify_one(); return resultFuture.get(); } bool RenderEngineThreaded::useWaitSync() 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::useWaitSync"); bool returnValue = SyncFeatures::getInstance().useWaitSync(); resultPromise.set_value(returnValue); }); } mCondition.notify_one(); return resultFuture.get(); } void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) { std::promise<void> resultPromise; std::future<void> resultFuture = resultPromise.get_future(); Loading
libs/renderengine/threaded/RenderEngineThreaded.h +8 −5 Original line number Diff line number Diff line Loading @@ -28,21 +28,25 @@ namespace android { namespace renderengine { namespace threaded { using CreateInstanceFactory = std::function<std::unique_ptr<renderengine::RenderEngine>()>; /** * This class extends a basic RenderEngine class. It contains a thread. Each time a function of * this class is called, we create a lambda function that is put on a queue. The main thread then * executes the functions in order. */ class RenderEngineThreaded : public impl::RenderEngine { class RenderEngineThreaded : public RenderEngine { public: static std::unique_ptr<RenderEngineThreaded> create(const RenderEngineCreationArgs& args); static std::unique_ptr<RenderEngineThreaded> create(CreateInstanceFactory factory); RenderEngineThreaded(const RenderEngineCreationArgs& args); RenderEngineThreaded(CreateInstanceFactory factory); ~RenderEngineThreaded() override; void primeCache() const override; void dump(std::string& result) override; bool useNativeFenceSync() const override; bool useWaitSync() const override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; void bindExternalTextureImage(uint32_t texName, const Image& image) override; Loading @@ -64,13 +68,12 @@ public: const std::vector<const LayerSettings*>& layers, const sp<GraphicBuffer>& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; void setRenderEngine(std::unique_ptr<renderengine::RenderEngine>); protected: Framebuffer* getFramebufferForDrawing() override; private: void threadMain(const RenderEngineCreationArgs& args); void threadMain(CreateInstanceFactory factory); /* ------------------------------------------------------------------------ * Threading Loading