From 9bc9dc6953628b3a8e48a08e3156c7710f279920 Mon Sep 17 00:00:00 2001 From: Ana Krulec Date: Wed, 26 Feb 2020 12:16:40 -0800 Subject: Creating a threaded version of the Render Engine. This class 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. In V1, all elements are passed by reference, and the main thread blocks on the execution of this thread. In the future iterations, the lambda makes copies of elements that should exist regardless of what happens to the thread that calls into this thread. go/speculative-render-engine for more info. Test: Activate blur. Collect systrace. Test: Open Chrome. Collect systrace. Test: atest RenderEngineThreadedTest Bug: 155929501 Change-Id: I246c6c1abb77a4c96c0867e722757326f8069b16 --- libs/renderengine/RenderEngine.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 0fdf093b2f..f0eb34be03 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -20,19 +20,33 @@ #include #include #include "gl/GLESRenderEngine.h" +#include "threaded/RenderEngineThreaded.h" namespace android { namespace renderengine { std::unique_ptr RenderEngine::create(const RenderEngineCreationArgs& args) { + RenderEngineType renderEngineType = args.renderEngineType; + + // Keep the ability to override by PROPERTIES: char prop[PROPERTY_VALUE_MAX]; - property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles"); + property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, ""); if (strcmp(prop, "gles") == 0) { - ALOGD("RenderEngine GLES Backend"); - return renderengine::gl::GLESRenderEngine::create(args); + renderEngineType = RenderEngineType::GLES; + } + if (strcmp(prop, "threaded") == 0) { + renderEngineType = RenderEngineType::THREADED; + } + + switch (renderEngineType) { + case RenderEngineType::THREADED: + ALOGD("Threaded RenderEngine with GLES Backend"); + return renderengine::threaded::RenderEngineThreaded::create(args); + case RenderEngineType::GLES: + default: + ALOGD("RenderEngine with GLES Backend"); + return renderengine::gl::GLESRenderEngine::create(args); } - ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop); - return renderengine::gl::GLESRenderEngine::create(args); } RenderEngine::~RenderEngine() = default; -- cgit v1.2.3-59-g8ed1b From 15f7cf31bf928543b6505aae6156cf6f008c29a8 Mon Sep 17 00:00:00 2001 From: Ana Krulec Date: Tue, 12 May 2020 11:57:42 -0700 Subject: RenderEngineThreaded takes a function as an argument to create In order to simplify testing and implementation of threaded RE, RenderEngineThreaded::create can takes a std::function argument to call to create the RE instance. RenderEngineThreaded::threadMain then call the function. - RenderEngine::create() uses it to create the production instance. - The test uses it to create the mock instance. Test: Unit tests Change-Id: Ic1af134979d4449c34d9ad86d07673367eb16896 --- libs/renderengine/RenderEngine.cpp | 6 +- .../include/renderengine/RenderEngine.h | 2 +- .../tests/RenderEngineThreadedTest.cpp | 70 +++++++++------------- .../renderengine/threaded/RenderEngineThreaded.cpp | 65 +++++++++++--------- libs/renderengine/threaded/RenderEngineThreaded.h | 13 ++-- 5 files changed, 79 insertions(+), 77 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index f0eb34be03..596f15cff2 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -25,7 +25,7 @@ namespace android { namespace renderengine { -std::unique_ptr RenderEngine::create(const RenderEngineCreationArgs& args) { +std::unique_ptr RenderEngine::create(const RenderEngineCreationArgs& args) { RenderEngineType renderEngineType = args.renderEngineType; // Keep the ability to override by PROPERTIES: @@ -41,7 +41,9 @@ std::unique_ptr 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"); diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 45e19eee62..b137023b84 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -76,7 +76,7 @@ public: THREADED = 2, }; - static std::unique_ptr create(const RenderEngineCreationArgs& args); + static std::unique_ptr create(const RenderEngineCreationArgs& args); virtual ~RenderEngine() = 0; diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 117af0f04a..69a0e1951a 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -28,56 +28,44 @@ using testing::Mock; using testing::Return; struct RenderEngineThreadedTest : public ::testing::Test { - RenderEngineThreadedTest() { - sThreadedRE->setRenderEngine(std::unique_ptr(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(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 sThreadedRE; + std::unique_ptr mThreadedRE; renderengine::mock::RenderEngine* mRenderEngine = new renderengine::mock::RenderEngine(); }; -std::unique_ptr - 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); } @@ -85,119 +73,119 @@ TEST_F(RenderEngineThreadedTest, bindExternalBuffer_withBuffer) { sp 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 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 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 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 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); } @@ -214,7 +202,7 @@ TEST_F(RenderEngineThreadedTest, drawLayers) { const sp&, 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); } diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index a883ad3b13..ad6171874d 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -23,6 +23,7 @@ #include #include +#include #include #include "gl/GLESRenderEngine.h" @@ -33,36 +34,15 @@ namespace android { namespace renderengine { namespace threaded { -std::unique_ptr RenderEngineThreaded::create( - const RenderEngineCreationArgs& args) { - return std::make_unique(args); +std::unique_ptr RenderEngineThreaded::create(CreateInstanceFactory factory) { + return std::make_unique(std::move(factory)); } -void RenderEngineThreaded::setRenderEngine( - std::unique_ptr renderEngine) { - ATRACE_CALL(); - // In order to ensure this is a thread safe call, it also needs to be put on a stack. - std::promise resultPromise; - std::future 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() { @@ -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}; @@ -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 lock(mThreadMutex); pthread_setname_np(pthread_self(), mThreadName); @@ -137,6 +116,36 @@ void RenderEngineThreaded::dump(std::string& result) { result.assign(resultFuture.get()); } +bool RenderEngineThreaded::useNativeFenceSync() const { + std::promise resultPromise; + std::future 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 resultPromise; + std::future 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 resultPromise; std::future resultFuture = resultPromise.get_future(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 8e4431e9b5..ec18e1f7b5 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -28,21 +28,25 @@ namespace android { namespace renderengine { namespace threaded { +using CreateInstanceFactory = std::function()>; + /** * 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 create(const RenderEngineCreationArgs& args); + static std::unique_ptr 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; @@ -64,13 +68,12 @@ public: const std::vector& layers, const sp& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; - void setRenderEngine(std::unique_ptr); protected: Framebuffer* getFramebufferForDrawing() override; private: - void threadMain(const RenderEngineCreationArgs& args); + void threadMain(CreateInstanceFactory factory); /* ------------------------------------------------------------------------ * Threading -- cgit v1.2.3-59-g8ed1b From d0156d931db2810ee76524916dd2c7ae16932b13 Mon Sep 17 00:00:00 2001 From: Ana Krulec Date: Mon, 1 Jun 2020 14:07:57 -0700 Subject: Copy arguments into RenderEngineThreaded RenderEngineThreaded currently crashes when trying to create framebuffer in function: createFramebufferImageIfNeeded. Looks like passing the copy of arguments fixes the problem. Bug: 157932582 Test: Print mFramebufferImageCacheSize, when threaded is off: 2 Test: Print mFramebufferImageCacheSize, when threaded is on: 2 Test: Open Chrome to trigger RE composition. Test: Pull down status bar to trigger RE composition. Change-Id: I3b21e0d159d63ea4454e46d10ffe698c4c1c3c4e --- libs/renderengine/RenderEngine.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 596f15cff2..c3fbb60af2 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -41,9 +41,8 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg switch (renderEngineType) { case RenderEngineType::THREADED: ALOGD("Threaded RenderEngine with GLES Backend"); - return renderengine::threaded::RenderEngineThreaded::create([&args]() { - return android::renderengine::gl::GLESRenderEngine::create(args); - }); + return renderengine::threaded::RenderEngineThreaded::create( + [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); case RenderEngineType::GLES: default: ALOGD("RenderEngine with GLES Backend"); -- cgit v1.2.3-59-g8ed1b From 992a2ca73f913f69939703cee5aa03013292578a Mon Sep 17 00:00:00 2001 From: John Reck Date: Thu, 3 Sep 2020 17:20:56 -0700 Subject: Remove some private methods from RenderEngine Moved some methods that are only used as an implementation detail of GLESRenderEngine out of RE's main header Test: builds Change-Id: Ib157082df23615b8c95a8aede9cd0ded093c8948 --- libs/renderengine/RenderEngine.cpp | 4 -- libs/renderengine/gl/GLESRenderEngine.cpp | 22 +++++++ libs/renderengine/gl/GLESRenderEngine.h | 10 +-- .../include/renderengine/RenderEngine.h | 37 ----------- .../include/renderengine/mock/RenderEngine.h | 1 - .../tests/RenderEngineThreadedTest.cpp | 20 ------ .../renderengine/threaded/RenderEngineThreaded.cpp | 76 ---------------------- libs/renderengine/threaded/RenderEngineThreaded.h | 7 -- 8 files changed, 28 insertions(+), 149 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index c3fbb60af2..eb0074bc40 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -62,10 +62,6 @@ bool RenderEngine::useNativeFenceSync() const { return SyncFeatures::getInstance().useNativeFenceSync(); } -bool RenderEngine::useWaitSync() const { - return SyncFeatures::getInstance().useWaitSync(); -} - } // namespace impl } // namespace renderengine } // namespace android diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 3dcfebe483..3090d193d1 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -114,6 +114,28 @@ namespace android { namespace renderengine { namespace gl { +class BindNativeBufferAsFramebuffer { +public: + BindNativeBufferAsFramebuffer(GLESRenderEngine& engine, ANativeWindowBuffer* buffer, + const bool useFramebufferCache) + : mEngine(engine), mFramebuffer(mEngine.getFramebufferForDrawing()), mStatus(NO_ERROR) { + mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected(), + useFramebufferCache) + ? mEngine.bindFrameBuffer(mFramebuffer) + : NO_MEMORY; + } + ~BindNativeBufferAsFramebuffer() { + mFramebuffer->setNativeWindowBuffer(nullptr, false, /*arbitrary*/ true); + mEngine.unbindFrameBuffer(mFramebuffer); + } + status_t getStatus() const { return mStatus; } + +private: + GLESRenderEngine& mEngine; + Framebuffer* mFramebuffer; + status_t mStatus; +}; + using base::StringAppendF; using ui::Dataspace; diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index 2c6eae2fff..2a98bd88a6 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -60,13 +60,10 @@ public: void primeCache() 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; status_t bindExternalTextureBuffer(uint32_t texName, const sp& buffer, const sp& fence) EXCLUDES(mRenderingMutex); void cacheExternalTextureBuffer(const sp& buffer) EXCLUDES(mRenderingMutex); void unbindExternalTextureBuffer(uint64_t bufferId) EXCLUDES(mRenderingMutex); - status_t bindFrameBuffer(Framebuffer* framebuffer) override; - void unbindFrameBuffer(Framebuffer* framebuffer) override; bool isProtected() const override { return mInProtectedContext; } bool supportsProtectedContent() const override; @@ -102,13 +99,15 @@ public: std::shared_ptr unbindExternalTextureBufferForTesting(uint64_t bufferId); protected: - Framebuffer* getFramebufferForDrawing() override; + Framebuffer* getFramebufferForDrawing(); void dump(std::string& result) override EXCLUDES(mRenderingMutex) EXCLUDES(mFramebufferImageCacheMutex); size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; private: + friend class BindNativeBufferAsFramebuffer; + enum GlesVersion { GLES_VERSION_1_0 = 0x10000, GLES_VERSION_1_1 = 0x10001, @@ -133,6 +132,9 @@ private: status_t cacheExternalTextureBufferInternal(const sp& buffer) EXCLUDES(mRenderingMutex); void unbindExternalTextureBufferInternal(uint64_t bufferId) EXCLUDES(mRenderingMutex); + status_t bindFrameBuffer(Framebuffer* framebuffer); + void unbindFrameBuffer(Framebuffer* framebuffer); + void bindExternalTextureImage(uint32_t texName, const Image& image); // A data space is considered HDR data space if it has BT2020 color space // with PQ or HLG transfer function. diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 09a0f65b43..6db2af8612 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -44,7 +44,6 @@ class Region; namespace renderengine { -class BindNativeBufferAsFramebuffer; class Image; class Mesh; class Texture; @@ -90,10 +89,8 @@ public: virtual void dump(std::string& result) = 0; virtual bool useNativeFenceSync() const = 0; - virtual bool useWaitSync() const = 0; virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; - virtual void bindExternalTextureImage(uint32_t texName, const Image& image) = 0; // Legacy public method used by devices that don't support native fence // synchronization in their GPU driver, as this method provides implicit // synchronization for latching buffers. @@ -116,10 +113,6 @@ public: // a buffer should never occur before binding the buffer if the caller // called {bind, cache}ExternalTextureBuffer before calling unbind. virtual void unbindExternalTextureBuffer(uint64_t bufferId) = 0; - // When binding a native buffer, it must be done before setViewportAndProjection - // Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation. - virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0; - virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0; enum class CleanupMode { CLEAN_OUTPUT_RESOURCES, @@ -187,13 +180,6 @@ public: base::unique_fd&& bufferFence, base::unique_fd* drawFence) = 0; protected: - // Gets a framebuffer to render to. This framebuffer may or may not be - // cached depending on the implementation. - // - // Note that this method does not transfer ownership, so the caller most not - // live longer than RenderEngine. - virtual Framebuffer* getFramebufferForDrawing() = 0; - friend class BindNativeBufferAsFramebuffer; friend class threaded::RenderEngineThreaded; }; @@ -280,28 +266,6 @@ private: RenderEngine::RenderEngineType renderEngineType = RenderEngine::RenderEngineType::GLES; }; -class BindNativeBufferAsFramebuffer { -public: - BindNativeBufferAsFramebuffer(RenderEngine& engine, ANativeWindowBuffer* buffer, - const bool useFramebufferCache) - : mEngine(engine), mFramebuffer(mEngine.getFramebufferForDrawing()), mStatus(NO_ERROR) { - mStatus = mFramebuffer->setNativeWindowBuffer(buffer, mEngine.isProtected(), - useFramebufferCache) - ? mEngine.bindFrameBuffer(mFramebuffer) - : NO_MEMORY; - } - ~BindNativeBufferAsFramebuffer() { - mFramebuffer->setNativeWindowBuffer(nullptr, false, /*arbitrary*/ true); - mEngine.unbindFrameBuffer(mFramebuffer); - } - status_t getStatus() const { return mStatus; } - -private: - RenderEngine& mEngine; - Framebuffer* mFramebuffer; - status_t mStatus; -}; - namespace impl { // impl::RenderEngine contains common implementation that is graphics back-end agnostic. @@ -310,7 +274,6 @@ public: virtual ~RenderEngine() = 0; bool useNativeFenceSync() const override; - bool useWaitSync() const override; protected: RenderEngine(const RenderEngineCreationArgs& args); diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index e03dd58c3a..3fd125ec74 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -43,7 +43,6 @@ public: MOCK_CONST_METHOD0(isCurrent, bool()); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); - MOCK_METHOD2(bindExternalTextureImage, void(uint32_t, const renderengine::Image&)); MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp&)); MOCK_METHOD3(bindExternalTextureBuffer, status_t(uint32_t, const sp&, const sp&)); diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 97c74421e6..78fec29036 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -93,26 +93,6 @@ TEST_F(RenderEngineThreadedTest, unbindExternalTextureBuffer) { mThreadedRE->unbindExternalTextureBuffer(0x0); } -TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsBadValue) { - std::unique_ptr framebuffer; - EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(BAD_VALUE)); - status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get()); - ASSERT_EQ(BAD_VALUE, result); -} - -TEST_F(RenderEngineThreadedTest, bindFrameBuffer_returnsNoError) { - std::unique_ptr framebuffer; - EXPECT_CALL(*mRenderEngine, bindFrameBuffer(framebuffer.get())).WillOnce(Return(NO_ERROR)); - status_t result = mThreadedRE->bindFrameBuffer(framebuffer.get()); - ASSERT_EQ(NO_ERROR, result); -} - -TEST_F(RenderEngineThreadedTest, unbindFrameBuffer) { - std::unique_ptr framebuffer; - EXPECT_CALL(*mRenderEngine, unbindFrameBuffer(framebuffer.get())); - mThreadedRE->unbindFrameBuffer(framebuffer.get()); -} - TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) { size_t size = 20; EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size)); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index d4184fdf72..dc47070460 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -131,21 +131,6 @@ bool RenderEngineThreaded::useNativeFenceSync() const { return resultFuture.get(); } -bool RenderEngineThreaded::useWaitSync() const { - std::promise resultPromise; - std::future 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 resultPromise; std::future resultFuture = resultPromise.get_future(); @@ -176,22 +161,6 @@ void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { resultFuture.wait(); } -void RenderEngineThreaded::bindExternalTextureImage(uint32_t texName, const Image& image) { - std::promise resultPromise; - std::future resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push( - [&resultPromise, texName, &image](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::bindExternalTextureImage"); - instance.bindExternalTextureImage(texName, image); - resultPromise.set_value(); - }); - } - mCondition.notify_one(); - resultFuture.wait(); -} - status_t RenderEngineThreaded::bindExternalTextureBuffer(uint32_t texName, const sp& buffer, const sp& fence) { @@ -240,36 +209,6 @@ void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { resultFuture.wait(); } -status_t RenderEngineThreaded::bindFrameBuffer(Framebuffer* framebuffer) { - std::promise resultPromise; - std::future resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise, &framebuffer](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::bindFrameBuffer"); - status_t status = instance.bindFrameBuffer(framebuffer); - resultPromise.set_value(status); - }); - } - mCondition.notify_one(); - return resultFuture.get(); -} - -void RenderEngineThreaded::unbindFrameBuffer(Framebuffer* framebuffer) { - std::promise resultPromise; - std::future resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise, &framebuffer](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::unbindFrameBuffer"); - instance.unbindFrameBuffer(framebuffer); - resultPromise.set_value(); - }); - } - mCondition.notify_one(); - resultFuture.wait(); -} - size_t RenderEngineThreaded::getMaxTextureSize() const { std::promise resultPromise; std::future resultFuture = resultPromise.get_future(); @@ -346,21 +285,6 @@ bool RenderEngineThreaded::useProtectedContext(bool useProtectedContext) { return resultFuture.get(); } -Framebuffer* RenderEngineThreaded::getFramebufferForDrawing() { - std::promise resultPromise; - std::future resultFuture = resultPromise.get_future(); - { - std::lock_guard lock(mThreadMutex); - mFunctionCalls.push([&resultPromise](renderengine::RenderEngine& instance) { - ATRACE_NAME("REThreaded::getFramebufferForDrawing"); - Framebuffer* framebuffer = instance.getFramebufferForDrawing(); - resultPromise.set_value(framebuffer); - }); - } - mCondition.notify_one(); - return resultFuture.get(); -} - bool RenderEngineThreaded::cleanupPostRender(CleanupMode mode) { std::promise resultPromise; std::future resultFuture = resultPromise.get_future(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 86a49e949d..96a49b3a0b 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -46,16 +46,12 @@ public: 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; status_t bindExternalTextureBuffer(uint32_t texName, const sp& buffer, const sp& fence) override; void cacheExternalTextureBuffer(const sp& buffer) override; void unbindExternalTextureBuffer(uint64_t bufferId) override; - status_t bindFrameBuffer(Framebuffer* framebuffer) override; - void unbindFrameBuffer(Framebuffer* framebuffer) override; size_t getMaxTextureSize() const override; size_t getMaxViewportDims() const override; @@ -69,9 +65,6 @@ public: const sp& buffer, const bool useFramebufferCache, base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; -protected: - Framebuffer* getFramebufferForDrawing() override; - private: void threadMain(CreateInstanceFactory factory); -- cgit v1.2.3-59-g8ed1b From 67b1e2b6ba789f1d16e76f5d1d64cc6da00fa738 Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 26 Aug 2020 13:17:24 -0700 Subject: RE-on-SK The First Steps Lots of stuff is broken, but it puts things on screen Test: enable via setprop, force gpu comp Bug: 164223050 Change-Id: I443f751f5db95fbe9f4ee9294e3bace6e213545e --- libs/renderengine/Android.bp | 10 + libs/renderengine/RenderEngine.cpp | 7 + .../include/renderengine/RenderEngine.h | 1 + libs/renderengine/skia/SkiaGLRenderEngine.cpp | 539 +++++++++++++++++++++ libs/renderengine/skia/SkiaGLRenderEngine.h | 93 ++++ libs/renderengine/skia/SkiaRenderEngine.cpp | 26 + libs/renderengine/skia/SkiaRenderEngine.h | 71 +++ services/surfaceflinger/Android.bp | 5 +- .../CompositionEngine/src/RenderSurface.cpp | 10 + services/surfaceflinger/RegionSamplingThread.cpp | 3 +- 10 files changed, 763 insertions(+), 2 deletions(-) create mode 100644 libs/renderengine/skia/SkiaGLRenderEngine.cpp create mode 100644 libs/renderengine/skia/SkiaGLRenderEngine.h create mode 100644 libs/renderengine/skia/SkiaRenderEngine.cpp create mode 100644 libs/renderengine/skia/SkiaRenderEngine.h (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 9264bb6b0e..1ccbff16f7 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -31,6 +31,7 @@ cc_defaults { "libui", "libutils", ], + whole_static_libs: ["libskia"], local_include_dirs: ["include"], export_include_dirs: ["include"], } @@ -71,6 +72,14 @@ filegroup { ], } +filegroup { + name: "librenderengine_skia_sources", + srcs: [ + "skia/SkiaRenderEngine.cpp", + "skia/SkiaGLRenderEngine.cpp", + ], +} + cc_library_static { name: "librenderengine", defaults: ["librenderengine_defaults"], @@ -84,6 +93,7 @@ cc_library_static { ":librenderengine_sources", ":librenderengine_gl_sources", ":librenderengine_threaded_sources", + ":librenderengine_skia_sources", ], lto: { thin: true, diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index eb0074bc40..c6436cdbec 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -22,6 +22,8 @@ #include "gl/GLESRenderEngine.h" #include "threaded/RenderEngineThreaded.h" +#include "skia/SkiaGLRenderEngine.h" + namespace android { namespace renderengine { @@ -37,12 +39,17 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg if (strcmp(prop, "threaded") == 0) { renderEngineType = RenderEngineType::THREADED; } + if (strcmp(prop, "skiagl") == 0) { + renderEngineType = RenderEngineType::SKIA_GL; + } switch (renderEngineType) { case RenderEngineType::THREADED: ALOGD("Threaded RenderEngine with GLES Backend"); return renderengine::threaded::RenderEngineThreaded::create( [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); + case RenderEngineType::SKIA_GL: + return renderengine::skia::SkiaGLRenderEngine::create(args); case RenderEngineType::GLES: default: ALOGD("RenderEngine with GLES Backend"); diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index a0e7ab7a43..3c90a3aeaf 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -73,6 +73,7 @@ public: enum class RenderEngineType { GLES = 1, THREADED = 2, + SKIA_GL = 3, }; static std::unique_ptr create(const RenderEngineCreationArgs& args); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp new file mode 100644 index 0000000000..94ba15392f --- /dev/null +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -0,0 +1,539 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "RenderEngine" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include + +#include +#include +#include +#include +#include +#include +#include "../gl/GLExtensions.h" +#include "SkiaGLRenderEngine.h" + +#include +#include + +#include +#include +#include + +extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name); + +bool checkGlError(const char* op, int lineNumber); + +namespace android { +namespace renderengine { +namespace skia { + +static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute, + EGLint wanted, EGLConfig* outConfig) { + EGLint numConfigs = -1, n = 0; + eglGetConfigs(dpy, nullptr, 0, &numConfigs); + std::vector configs(numConfigs, EGL_NO_CONFIG_KHR); + eglChooseConfig(dpy, attrs, configs.data(), configs.size(), &n); + configs.resize(n); + + if (!configs.empty()) { + if (attribute != EGL_NONE) { + for (EGLConfig config : configs) { + EGLint value = 0; + eglGetConfigAttrib(dpy, config, attribute, &value); + if (wanted == value) { + *outConfig = config; + return NO_ERROR; + } + } + } else { + // just pick the first one + *outConfig = configs[0]; + return NO_ERROR; + } + } + + return NAME_NOT_FOUND; +} + +static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint renderableType, + EGLConfig* config) { + // select our EGLConfig. It must support EGL_RECORDABLE_ANDROID if + // it is to be used with WIFI displays + status_t err; + EGLint wantedAttribute; + EGLint wantedAttributeValue; + + std::vector attribs; + if (renderableType) { + const ui::PixelFormat pixelFormat = static_cast(format); + const bool is1010102 = pixelFormat == ui::PixelFormat::RGBA_1010102; + + // Default to 8 bits per channel. + const EGLint tmpAttribs[] = { + EGL_RENDERABLE_TYPE, + renderableType, + EGL_RECORDABLE_ANDROID, + EGL_TRUE, + EGL_SURFACE_TYPE, + EGL_WINDOW_BIT | EGL_PBUFFER_BIT, + EGL_FRAMEBUFFER_TARGET_ANDROID, + EGL_TRUE, + EGL_RED_SIZE, + is1010102 ? 10 : 8, + EGL_GREEN_SIZE, + is1010102 ? 10 : 8, + EGL_BLUE_SIZE, + is1010102 ? 10 : 8, + EGL_ALPHA_SIZE, + is1010102 ? 2 : 8, + EGL_NONE, + }; + std::copy(tmpAttribs, tmpAttribs + (sizeof(tmpAttribs) / sizeof(EGLint)), + std::back_inserter(attribs)); + wantedAttribute = EGL_NONE; + wantedAttributeValue = EGL_NONE; + } else { + // if no renderable type specified, fallback to a simplified query + wantedAttribute = EGL_NATIVE_VISUAL_ID; + wantedAttributeValue = format; + } + + err = selectConfigForAttribute(display, attribs.data(), wantedAttribute, wantedAttributeValue, + config); + if (err == NO_ERROR) { + EGLint caveat; + if (eglGetConfigAttrib(display, *config, EGL_CONFIG_CAVEAT, &caveat)) + ALOGW_IF(caveat == EGL_SLOW_CONFIG, "EGL_SLOW_CONFIG selected!"); + } + + return err; +} + +std::unique_ptr SkiaGLRenderEngine::create( + const RenderEngineCreationArgs& args) { + // initialize EGL for the default display + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(display, nullptr, nullptr)) { + LOG_ALWAYS_FATAL("failed to initialize EGL"); + } + + const auto eglVersion = eglQueryStringImplementationANDROID(display, EGL_VERSION); + if (!eglVersion) { + checkGlError(__FUNCTION__, __LINE__); + LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_VERSION) failed"); + } + + const auto eglExtensions = eglQueryStringImplementationANDROID(display, EGL_EXTENSIONS); + if (!eglExtensions) { + checkGlError(__FUNCTION__, __LINE__); + LOG_ALWAYS_FATAL("eglQueryStringImplementationANDROID(EGL_EXTENSIONS) failed"); + } + + auto& extensions = gl::GLExtensions::getInstance(); + extensions.initWithEGLStrings(eglVersion, eglExtensions); + + // The code assumes that ES2 or later is available if this extension is + // supported. + EGLConfig config = EGL_NO_CONFIG_KHR; + if (!extensions.hasNoConfigContext()) { + config = chooseEglConfig(display, args.pixelFormat, /*logConfig*/ true); + } + + bool useContextPriority = + extensions.hasContextPriority() && args.contextPriority == ContextPriority::HIGH; + EGLContext protectedContext = EGL_NO_CONTEXT; + if (args.enableProtectedContext && extensions.hasProtectedContent()) { + protectedContext = createEglContext(display, config, nullptr, useContextPriority, + Protection::PROTECTED); + ALOGE_IF(protectedContext == EGL_NO_CONTEXT, "Can't create protected context"); + } + + EGLContext ctxt = createEglContext(display, config, protectedContext, useContextPriority, + Protection::UNPROTECTED); + + // if can't create a GL context, we can only abort. + LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed"); + + EGLSurface placeholder = EGL_NO_SURFACE; + if (!extensions.hasSurfacelessContext()) { + placeholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat, + Protection::UNPROTECTED); + LOG_ALWAYS_FATAL_IF(placeholder == EGL_NO_SURFACE, "can't create placeholder pbuffer"); + } + EGLBoolean success = eglMakeCurrent(display, placeholder, placeholder, ctxt); + LOG_ALWAYS_FATAL_IF(!success, "can't make placeholder pbuffer current"); + extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER), + glGetString(GL_VERSION), glGetString(GL_EXTENSIONS)); + + EGLSurface protectedPlaceholder = EGL_NO_SURFACE; + if (protectedContext != EGL_NO_CONTEXT && !extensions.hasSurfacelessContext()) { + protectedPlaceholder = createPlaceholderEglPbufferSurface(display, config, args.pixelFormat, + Protection::PROTECTED); + ALOGE_IF(protectedPlaceholder == EGL_NO_SURFACE, + "can't create protected placeholder pbuffer"); + } + + // initialize the renderer while GL is current + std::unique_ptr engine = + std::make_unique(args, display, config, ctxt, placeholder, + protectedContext, protectedPlaceholder); + + ALOGI("OpenGL ES informations:"); + ALOGI("vendor : %s", extensions.getVendor()); + ALOGI("renderer : %s", extensions.getRenderer()); + ALOGI("version : %s", extensions.getVersion()); + ALOGI("extensions: %s", extensions.getExtensions()); + ALOGI("GL_MAX_TEXTURE_SIZE = %zu", engine->getMaxTextureSize()); + ALOGI("GL_MAX_VIEWPORT_DIMS = %zu", engine->getMaxViewportDims()); + + return engine; +} + +EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool logConfig) { + status_t err; + EGLConfig config; + + // First try to get an ES3 config + err = selectEGLConfig(display, format, EGL_OPENGL_ES3_BIT, &config); + if (err != NO_ERROR) { + // If ES3 fails, try to get an ES2 config + err = selectEGLConfig(display, format, EGL_OPENGL_ES2_BIT, &config); + if (err != NO_ERROR) { + // If ES2 still doesn't work, probably because we're on the emulator. + // try a simplified query + ALOGW("no suitable EGLConfig found, trying a simpler query"); + err = selectEGLConfig(display, format, 0, &config); + if (err != NO_ERROR) { + // this EGL is too lame for android + LOG_ALWAYS_FATAL("no suitable EGLConfig found, giving up"); + } + } + } + + if (logConfig) { + // print some debugging info + EGLint r, g, b, a; + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &r); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &g); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &b); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &a); + ALOGI("EGL information:"); + ALOGI("vendor : %s", eglQueryString(display, EGL_VENDOR)); + ALOGI("version : %s", eglQueryString(display, EGL_VERSION)); + ALOGI("extensions: %s", eglQueryString(display, EGL_EXTENSIONS)); + ALOGI("Client API: %s", eglQueryString(display, EGL_CLIENT_APIS) ?: "Not Supported"); + ALOGI("EGLSurface: %d-%d-%d-%d, config=%p", r, g, b, a, config); + } + + return config; +} + +SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, + EGLConfig config, EGLContext ctxt, EGLSurface placeholder, + EGLContext protectedContext, EGLSurface protectedPlaceholder) + : renderengine::skia::SkiaRenderEngine(args), + mEGLDisplay(display), + mEGLConfig(config), + mEGLContext(ctxt), + mPlaceholderSurface(placeholder), + mProtectedEGLContext(protectedContext), + mProtectedPlaceholderSurface(protectedPlaceholder) { + // Suppress unused field warnings for things we definitely will need/use + // These EGL fields will all be needed for toggling between protected & unprotected contexts + // Or we need different RE instances for that + (void)mEGLDisplay; + (void)mEGLConfig; + (void)mEGLContext; + (void)mPlaceholderSurface; + (void)mProtectedEGLContext; + (void)mProtectedPlaceholderSurface; + + sk_sp glInterface(GrGLCreateNativeInterface()); + LOG_ALWAYS_FATAL_IF(!glInterface.get()); + + GrContextOptions options; + options.fPreferExternalImagesOverES3 = true; + options.fDisableDistanceFieldPaths = true; + mGrContext = GrDirectContext::MakeGL(std::move(glInterface), options); +} + +base::unique_fd SkiaGLRenderEngine::flush() { + ATRACE_CALL(); + if (!gl::GLExtensions::getInstance().hasNativeFenceSync()) { + return base::unique_fd(); + } + + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, nullptr); + if (sync == EGL_NO_SYNC_KHR) { + ALOGW("failed to create EGL native fence sync: %#x", eglGetError()); + return base::unique_fd(); + } + + // native fence fd will not be populated until flush() is done. + glFlush(); + + // get the fence fd + base::unique_fd fenceFd(eglDupNativeFenceFDANDROID(mEGLDisplay, sync)); + eglDestroySyncKHR(mEGLDisplay, sync); + if (fenceFd == EGL_NO_NATIVE_FENCE_FD_ANDROID) { + ALOGW("failed to dup EGL native fence sync: %#x", eglGetError()); + } + + return fenceFd; +} + +bool SkiaGLRenderEngine::waitFence(base::unique_fd fenceFd) { + if (!gl::GLExtensions::getInstance().hasNativeFenceSync() || + !gl::GLExtensions::getInstance().hasWaitSync()) { + return false; + } + + // release the fd and transfer the ownership to EGLSync + EGLint attribs[] = {EGL_SYNC_NATIVE_FENCE_FD_ANDROID, fenceFd.release(), EGL_NONE}; + EGLSyncKHR sync = eglCreateSyncKHR(mEGLDisplay, EGL_SYNC_NATIVE_FENCE_ANDROID, attribs); + if (sync == EGL_NO_SYNC_KHR) { + ALOGE("failed to create EGL native fence sync: %#x", eglGetError()); + return false; + } + + // XXX: The spec draft is inconsistent as to whether this should return an + // EGLint or void. Ignore the return value for now, as it's not strictly + // needed. + eglWaitSyncKHR(mEGLDisplay, sync, 0); + EGLint error = eglGetError(); + eglDestroySyncKHR(mEGLDisplay, sync); + if (error != EGL_SUCCESS) { + ALOGE("failed to wait for EGL native fence sync: %#x", error); + return false; + } + + return true; +} + +static bool hasUsage(const AHardwareBuffer_Desc& desc, uint64_t usage) { + return !!(desc.usage & usage); +} + +void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { + std::lock_guard lock(mRenderingMutex); + mImageCache.erase(bufferId); +} + +status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, + const std::vector& layers, + const sp& buffer, + const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) { + ATRACE_NAME("SkiaGL::drawLayers"); + std::lock_guard lock(mRenderingMutex); + if (layers.empty()) { + ALOGV("Drawing empty layer stack"); + return NO_ERROR; + } + + if (bufferFence.get() >= 0) { + // Duplicate the fence for passing to waitFence. + base::unique_fd bufferFenceDup(dup(bufferFence.get())); + if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) { + ATRACE_NAME("Waiting before draw"); + sync_wait(bufferFence.get(), -1); + } + } + if (buffer == nullptr) { + ALOGE("No output buffer provided. Aborting GPU composition."); + return BAD_VALUE; + } + + AHardwareBuffer_Desc bufferDesc; + AHardwareBuffer_describe(buffer->toAHardwareBuffer(), &bufferDesc); + + LOG_ALWAYS_FATAL_IF(!hasUsage(bufferDesc, AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE), + "missing usage"); + + sk_sp surface; + if (useFramebufferCache) { + auto iter = mSurfaceCache.find(buffer->getId()); + if (iter != mSurfaceCache.end()) { + ALOGV("Cache hit!"); + surface = iter->second; + } + } + if (!surface) { + surface = SkSurface::MakeFromAHardwareBuffer(mGrContext.get(), buffer->toAHardwareBuffer(), + GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin, + SkColorSpace::MakeSRGB(), nullptr); + if (useFramebufferCache && surface) { + ALOGD("Adding to cache"); + mSurfaceCache.insert({buffer->getId(), surface}); + } + } + if (!surface) { + ALOGE("Failed to make surface"); + return BAD_VALUE; + } + auto canvas = surface->getCanvas(); + + canvas->clipRect(SkRect::MakeLTRB(display.clip.left, display.clip.top, display.clip.right, + display.clip.bottom)); + canvas->drawColor(0, SkBlendMode::kSrc); + for (const auto& layer : layers) { + if (layer->source.buffer.buffer) { + ATRACE_NAME("DrawImage"); + const auto& item = layer->source.buffer; + sk_sp image; + auto iter = mImageCache.find(item.buffer->getId()); + if (iter != mImageCache.end()) { + image = iter->second; + } else { + image = SkImage::MakeFromAHardwareBuffer(item.buffer->toAHardwareBuffer(), + item.usePremultipliedAlpha + ? kPremul_SkAlphaType + : kUnpremul_SkAlphaType); + mImageCache.insert({item.buffer->getId(), image}); + } + const auto& bounds = layer->geometry.boundaries; + SkRect dest = SkRect::MakeLTRB(bounds.left, bounds.top, bounds.right, bounds.bottom); + canvas->drawImageRect(image, dest, nullptr); + } else { + ATRACE_NAME("DrawColor"); + SkPaint paint; + const auto color = layer->source.solidColor; + paint.setColor(SkColor4f{.fR = color.r, .fG = color.g, .fB = color.b, layer->alpha}); + } + } + { + ATRACE_NAME("flush surface"); + surface->flush(); + } + + if (drawFence != nullptr) { + *drawFence = flush(); + } + + // If flush failed or we don't support native fences, we need to force the + // gl command stream to be executed. + bool requireSync = drawFence == nullptr || drawFence->get() < 0; + if (requireSync) { + ATRACE_BEGIN("Submit(sync=true)"); + } else { + ATRACE_BEGIN("Submit(sync=false)"); + } + bool success = mGrContext->submit(requireSync); + ATRACE_END(); + if (!success) { + ALOGE("Failed to flush RenderEngine commands"); + // Chances are, something illegal happened (either the caller passed + // us bad parameters, or we messed up our shader generation). + return INVALID_OPERATION; + } + + // checkErrors(); + return NO_ERROR; +} + +size_t SkiaGLRenderEngine::getMaxTextureSize() const { + return mGrContext->maxTextureSize(); +} + +size_t SkiaGLRenderEngine::getMaxViewportDims() const { + return mGrContext->maxRenderTargetSize(); +} + +EGLContext SkiaGLRenderEngine::createEglContext(EGLDisplay display, EGLConfig config, + EGLContext shareContext, bool useContextPriority, + Protection protection) { + EGLint renderableType = 0; + if (config == EGL_NO_CONFIG_KHR) { + renderableType = EGL_OPENGL_ES3_BIT; + } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) { + LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE"); + } + EGLint contextClientVersion = 0; + if (renderableType & EGL_OPENGL_ES3_BIT) { + contextClientVersion = 3; + } else if (renderableType & EGL_OPENGL_ES2_BIT) { + contextClientVersion = 2; + } else if (renderableType & EGL_OPENGL_ES_BIT) { + contextClientVersion = 1; + } else { + LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs"); + } + + std::vector contextAttributes; + contextAttributes.reserve(7); + contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION); + contextAttributes.push_back(contextClientVersion); + if (useContextPriority) { + contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG); + contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG); + } + if (protection == Protection::PROTECTED) { + contextAttributes.push_back(EGL_PROTECTED_CONTENT_EXT); + contextAttributes.push_back(EGL_TRUE); + } + contextAttributes.push_back(EGL_NONE); + + EGLContext context = eglCreateContext(display, config, shareContext, contextAttributes.data()); + + if (contextClientVersion == 3 && context == EGL_NO_CONTEXT) { + // eglGetConfigAttrib indicated we can create GLES 3 context, but we failed, thus + // EGL_NO_CONTEXT so that we can abort. + if (config != EGL_NO_CONFIG_KHR) { + return context; + } + // If |config| is EGL_NO_CONFIG_KHR, we speculatively try to create GLES 3 context, so we + // should try to fall back to GLES 2. + contextAttributes[1] = 2; + context = eglCreateContext(display, config, shareContext, contextAttributes.data()); + } + + return context; +} + +EGLSurface SkiaGLRenderEngine::createPlaceholderEglPbufferSurface(EGLDisplay display, + EGLConfig config, int hwcFormat, + Protection protection) { + EGLConfig placeholderConfig = config; + if (placeholderConfig == EGL_NO_CONFIG_KHR) { + placeholderConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true); + } + std::vector attributes; + attributes.reserve(7); + attributes.push_back(EGL_WIDTH); + attributes.push_back(1); + attributes.push_back(EGL_HEIGHT); + attributes.push_back(1); + if (protection == Protection::PROTECTED) { + attributes.push_back(EGL_PROTECTED_CONTENT_EXT); + attributes.push_back(EGL_TRUE); + } + attributes.push_back(EGL_NONE); + + return eglCreatePbufferSurface(display, placeholderConfig, attributes.data()); +} + +void SkiaGLRenderEngine::cleanFramebufferCache() { + mSurfaceCache.clear(); +} + +} // namespace skia +} // namespace renderengine +} // namespace android \ No newline at end of file diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h new file mode 100644 index 0000000000..eb098cb0ac --- /dev/null +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -0,0 +1,93 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SF_SKIAGLRENDERENGINE_H_ +#define SF_SKIAGLRENDERENGINE_H_ + +#include +#include +#include + +#include +#include + +#include +#include + +#include "SkiaRenderEngine.h" + +namespace android { +namespace renderengine { +namespace skia { + +class SkiaGLRenderEngine : public skia::SkiaRenderEngine { +public: + static std::unique_ptr create(const RenderEngineCreationArgs& args); + SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config, + EGLContext ctxt, EGLSurface placeholder, EGLContext protectedContext, + EGLSurface protectedPlaceholder); + ~SkiaGLRenderEngine() override{}; + + void unbindExternalTextureBuffer(uint64_t bufferId) override; + status_t drawLayers(const DisplaySettings& display, + const std::vector& layers, + const sp& buffer, const bool useFramebufferCache, + base::unique_fd&& bufferFence, base::unique_fd* drawFence) override; + void cleanFramebufferCache() override; + +protected: + void dump(std::string& /*result*/) override{}; + size_t getMaxTextureSize() const override; + size_t getMaxViewportDims() const override; + +private: + static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig); + static EGLContext createEglContext(EGLDisplay display, EGLConfig config, + EGLContext shareContext, bool useContextPriority, + Protection protection); + static EGLSurface createPlaceholderEglPbufferSurface(EGLDisplay display, EGLConfig config, + int hwcFormat, Protection protection); + + base::unique_fd flush(); + bool waitFence(base::unique_fd fenceFd); + + EGLDisplay mEGLDisplay; + EGLConfig mEGLConfig; + EGLContext mEGLContext; + EGLSurface mPlaceholderSurface; + EGLContext mProtectedEGLContext; + EGLSurface mProtectedPlaceholderSurface; + + // Cache of GL images that we'll store per GraphicBuffer ID + std::unordered_map> mImageCache GUARDED_BY(mRenderingMutex); + // Mutex guarding rendering operations, so that: + // 1. GL operations aren't interleaved, and + // 2. Internal state related to rendering that is potentially modified by + // multiple threads is guaranteed thread-safe. + std::mutex mRenderingMutex; + + sp mLastDrawFence; + + sk_sp mGrContext; + + std::unordered_map> mSurfaceCache; +}; + +} // namespace skia +} // namespace renderengine +} // namespace android + +#endif /* SF_GLESRENDERENGINE_H_ */ \ No newline at end of file diff --git a/libs/renderengine/skia/SkiaRenderEngine.cpp b/libs/renderengine/skia/SkiaRenderEngine.cpp new file mode 100644 index 0000000000..81f0b6f970 --- /dev/null +++ b/libs/renderengine/skia/SkiaRenderEngine.cpp @@ -0,0 +1,26 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +//#define LOG_NDEBUG 0 +#undef LOG_TAG +#define LOG_TAG "RenderEngine" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +namespace android { +namespace renderengine { +namespace skia {} // namespace skia +} // namespace renderengine +} // namespace android \ No newline at end of file diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h new file mode 100644 index 0000000000..3c5d0cf24d --- /dev/null +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -0,0 +1,71 @@ +/* + * Copyright 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SF_SKIARENDERENGINE_H_ +#define SF_SKIARENDERENGINE_H_ + +#include +#include + +namespace android { + +namespace renderengine { + +class Mesh; +class Texture; + +namespace skia { + +class BlurFilter; + +// TODO: Put common skia stuff here that can be shared between the GL & Vulkan backends +// Currently mostly just handles all the no-op / missing APIs +class SkiaRenderEngine : public impl::RenderEngine { +public: + static std::unique_ptr create(const RenderEngineCreationArgs& args); + SkiaRenderEngine(const RenderEngineCreationArgs& args) : RenderEngine(args){}; + ~SkiaRenderEngine() override {} + + virtual void primeCache() const override{}; + virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{}; + virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{}; + virtual status_t bindExternalTextureBuffer(uint32_t /*texName*/, + const sp& /*buffer*/, + const sp& /*fence*/) { + return 0; + }; // EXCLUDES(mRenderingMutex); + virtual void cacheExternalTextureBuffer(const sp& /*buffer*/){}; + virtual void unbindExternalTextureBuffer(uint64_t /*bufferId*/){}; + + virtual bool isProtected() const override { return false; } // mInProtectedContext; } + virtual bool supportsProtectedContent() const override { return false; }; + virtual bool useProtectedContext(bool /*useProtectedContext*/) override { return false; }; + virtual status_t drawLayers(const DisplaySettings& /*display*/, + const std::vector& /*layers*/, + const sp& /*buffer*/, + const bool /*useFramebufferCache*/, + base::unique_fd&& /*bufferFence*/, + base::unique_fd* /*drawFence*/) override { + return 0; + }; + virtual bool cleanupPostRender(CleanupMode) override { return true; }; +}; + +} // namespace skia +} // namespace renderengine +} // namespace android + +#endif /* SF_GLESRENDERENGINE_H_ */ \ No newline at end of file diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index b017ad7e78..db808e0663 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -13,7 +13,10 @@ cc_defaults { cc_defaults { name: "libsurfaceflinger_defaults", - defaults: ["surfaceflinger_defaults"], + defaults: [ + "surfaceflinger_defaults", + "skia_deps", + ], cflags: [ "-DLOG_TAG=\"SurfaceFlinger\"", "-DGL_GLEXT_PROTOTYPES", diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 2773fd3a16..8d1ffe326d 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -42,6 +42,9 @@ // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic pop // ignored "-Wconversion" +// Uncomment to enable RE-SK workarounds; b/b/168499446 +//#define USE_SKIA_WORKAROUNDS + namespace android::compositionengine { RenderSurface::~RenderSurface() = default; @@ -81,7 +84,11 @@ void RenderSurface::initialize() { ALOGE_IF(status != NO_ERROR, "Unable to connect BQ producer: %d", status); status = native_window_set_buffers_format(window, HAL_PIXEL_FORMAT_RGBA_8888); ALOGE_IF(status != NO_ERROR, "Unable to set BQ format to RGBA888: %d", status); +#ifdef USE_SKIA_WORKAROUNDS + status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE); +#else status = native_window_set_usage(window, GRALLOC_USAGE_HW_RENDER); +#endif ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for GPU rendering: %d", status); } @@ -113,6 +120,9 @@ void RenderSurface::setProtected(bool useProtected) { if (useProtected) { usageFlags |= GRALLOC_USAGE_PROTECTED; } +#ifdef USE_SKIA_WORKAROUNDS + usageFlags |= GRALLOC_USAGE_HW_TEXTURE; +#endif const int status = native_window_set_usage(mNativeWindow.get(), usageFlags); ALOGE_IF(status != NO_ERROR, "Unable to set BQ usage bits for protected content: %d", status); if (status == NO_ERROR) { diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index a2fc6925b8..890945f6f3 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -441,7 +441,8 @@ void RegionSamplingThread::captureSample() { mCachedBuffer->getHeight() == sampledBounds.getHeight()) { buffer = mCachedBuffer; } else { - const uint32_t usage = GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER; + const uint32_t usage = + GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE; buffer = new GraphicBuffer(sampledBounds.getWidth(), sampledBounds.getHeight(), PIXEL_FORMAT_RGBA_8888, 1, usage, "RegionSamplingThread"); } -- cgit v1.2.3-59-g8ed1b From 081be4c36dcf51a660f25f3c05fab5ac0ebaa59a Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Wed, 16 Sep 2020 10:24:47 -0700 Subject: Delete RenderEngine unused code * V0 skia implementation beat the prior change deleting unused code, so delete bindExternalTextureBuffer there. * Remove useNativeFenceSync, now that there's no more usages * Remove impl::RenderEngine, since there's no need for a private impl-superclass spanning every RenderEngine implementation * Clean up mock/RenderEngine Bug: 168553972 Test: builds Change-Id: I6f760510656b90b30d86b04fc70c19067a4491cd --- libs/renderengine/RenderEngine.cpp | 12 ------------ libs/renderengine/gl/GLESRenderEngine.cpp | 9 ++++----- libs/renderengine/gl/GLESRenderEngine.h | 6 +++++- libs/renderengine/include/renderengine/RenderEngine.h | 16 ---------------- .../include/renderengine/mock/RenderEngine.h | 8 -------- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 11 +++++------ libs/renderengine/skia/SkiaGLRenderEngine.h | 4 ++-- libs/renderengine/skia/SkiaRenderEngine.h | 8 +------- libs/renderengine/threaded/RenderEngineThreaded.cpp | 15 --------------- libs/renderengine/threaded/RenderEngineThreaded.h | 1 - .../surfaceflinger/tests/unittests/CompositionTest.cpp | 7 ------- 11 files changed, 17 insertions(+), 80 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index c6436cdbec..3e65d9afce 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -18,7 +18,6 @@ #include #include -#include #include "gl/GLESRenderEngine.h" #include "threaded/RenderEngineThreaded.h" @@ -59,16 +58,5 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg RenderEngine::~RenderEngine() = default; -namespace impl { - -RenderEngine::RenderEngine(const RenderEngineCreationArgs& args) : mArgs(args) {} - -RenderEngine::~RenderEngine() = default; - -bool RenderEngine::useNativeFenceSync() const { - return SyncFeatures::getInstance().useNativeFenceSync(); -} - -} // namespace impl } // namespace renderengine } // namespace android diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 3367664d81..6adcbeaf76 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -356,8 +356,7 @@ EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface stub, EGLContext protectedContext, EGLSurface protectedStub) - : renderengine::impl::RenderEngine(args), - mEGLDisplay(display), + : mEGLDisplay(display), mEGLConfig(config), mEGLContext(ctxt), mStubSurface(stub), @@ -366,7 +365,8 @@ GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisp mVpWidth(0), mVpHeight(0), mFramebufferImageCacheSize(args.imageCacheSize), - mUseColorManagement(args.useColorManagement) { + mUseColorManagement(args.useColorManagement), + mPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly) { glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims); @@ -475,8 +475,7 @@ Framebuffer* GLESRenderEngine::getFramebufferForDrawing() { void GLESRenderEngine::primeCache() const { ProgramCache::getInstance().primeCache(mInProtectedContext ? mProtectedEGLContext : mEGLContext, - mArgs.useColorManagement, - mArgs.precacheToneMapperShaderOnly); + mUseColorManagement, mPrecacheToneMapperShaderOnly); } base::unique_fd GLESRenderEngine::flush() { diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h index c72b7f9d01..1779994d4a 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -48,7 +48,7 @@ namespace gl { class GLImage; class BlurFilter; -class GLESRenderEngine : public impl::RenderEngine { +class GLESRenderEngine : public RenderEngine { public: static std::unique_ptr create(const RenderEngineCreationArgs& args); @@ -231,6 +231,10 @@ private: // supports sRGB, DisplayP3 color spaces. const bool mUseColorManagement = false; + // Whether only shaders performing tone mapping from HDR to SDR will be generated on + // primeCache(). + const bool mPrecacheToneMapperShaderOnly = false; + // Cache of GL images that we'll store per GraphicBuffer ID std::unordered_map> mImageCache GUARDED_BY(mRenderingMutex); std::unordered_map> mTextureView; diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 9b87229d66..11b8e44e4f 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -89,7 +89,6 @@ public: // dump the extension strings. always call the base class. virtual void dump(std::string& result) = 0; - virtual bool useNativeFenceSync() const = 0; virtual void genTextures(size_t count, uint32_t* names) = 0; virtual void deleteTextures(size_t count, uint32_t const* names) = 0; // Caches Image resources for this buffer, but does not bind the buffer to @@ -263,21 +262,6 @@ private: RenderEngine::RenderEngineType renderEngineType = RenderEngine::RenderEngineType::GLES; }; -namespace impl { - -// impl::RenderEngine contains common implementation that is graphics back-end agnostic. -class RenderEngine : public renderengine::RenderEngine { -public: - virtual ~RenderEngine() = 0; - - bool useNativeFenceSync() const override; - -protected: - RenderEngine(const RenderEngineCreationArgs& args); - const RenderEngineCreationArgs mArgs; -}; - -} // namespace impl } // namespace renderengine } // namespace android diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h index 0b80d885b8..95ee9258a1 100644 --- a/libs/renderengine/include/renderengine/mock/RenderEngine.h +++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h @@ -35,20 +35,12 @@ public: RenderEngine(); ~RenderEngine() override; - MOCK_METHOD0(getFramebufferForDrawing, Framebuffer*()); MOCK_CONST_METHOD0(primeCache, void()); MOCK_METHOD1(dump, void(std::string&)); - MOCK_CONST_METHOD0(useNativeFenceSync, bool()); - MOCK_CONST_METHOD0(useWaitSync, bool()); - MOCK_CONST_METHOD0(isCurrent, bool()); MOCK_METHOD2(genTextures, void(size_t, uint32_t*)); MOCK_METHOD2(deleteTextures, void(size_t, uint32_t const*)); MOCK_METHOD1(cacheExternalTextureBuffer, void(const sp&)); - MOCK_METHOD3(bindExternalTextureBuffer, - status_t(uint32_t, const sp&, const sp&)); MOCK_METHOD1(unbindExternalTextureBuffer, void(uint64_t)); - MOCK_METHOD1(bindFrameBuffer, status_t(renderengine::Framebuffer*)); - MOCK_METHOD1(unbindFrameBuffer, void(renderengine::Framebuffer*)); MOCK_METHOD1(drawMesh, void(const renderengine::Mesh&)); MOCK_CONST_METHOD0(getMaxTextureSize, size_t()); MOCK_CONST_METHOD0(getMaxViewportDims, size_t()); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 94ba15392f..7cfe207c1e 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -193,7 +193,7 @@ std::unique_ptr SkiaGLRenderEngine::create( // initialize the renderer while GL is current std::unique_ptr engine = - std::make_unique(args, display, config, ctxt, placeholder, + std::make_unique(display, config, ctxt, placeholder, protectedContext, protectedPlaceholder); ALOGI("OpenGL ES informations:"); @@ -246,11 +246,10 @@ EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bo return config; } -SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, - EGLConfig config, EGLContext ctxt, EGLSurface placeholder, - EGLContext protectedContext, EGLSurface protectedPlaceholder) - : renderengine::skia::SkiaRenderEngine(args), - mEGLDisplay(display), +SkiaGLRenderEngine::SkiaGLRenderEngine(EGLDisplay display, EGLConfig config, EGLContext ctxt, + EGLSurface placeholder, EGLContext protectedContext, + EGLSurface protectedPlaceholder) + : mEGLDisplay(display), mEGLConfig(config), mEGLContext(ctxt), mPlaceholderSurface(placeholder), diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index eb098cb0ac..b8387b2dc9 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -36,8 +36,8 @@ namespace skia { class SkiaGLRenderEngine : public skia::SkiaRenderEngine { public: static std::unique_ptr create(const RenderEngineCreationArgs& args); - SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config, - EGLContext ctxt, EGLSurface placeholder, EGLContext protectedContext, + SkiaGLRenderEngine(EGLDisplay display, EGLConfig config, EGLContext ctxt, + EGLSurface placeholder, EGLContext protectedContext, EGLSurface protectedPlaceholder); ~SkiaGLRenderEngine() override{}; diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 3c5d0cf24d..2352c7e59e 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -33,20 +33,14 @@ class BlurFilter; // TODO: Put common skia stuff here that can be shared between the GL & Vulkan backends // Currently mostly just handles all the no-op / missing APIs -class SkiaRenderEngine : public impl::RenderEngine { +class SkiaRenderEngine : public RenderEngine { public: static std::unique_ptr create(const RenderEngineCreationArgs& args); - SkiaRenderEngine(const RenderEngineCreationArgs& args) : RenderEngine(args){}; ~SkiaRenderEngine() override {} virtual void primeCache() const override{}; virtual void genTextures(size_t /*count*/, uint32_t* /*names*/) override{}; virtual void deleteTextures(size_t /*count*/, uint32_t const* /*names*/) override{}; - virtual status_t bindExternalTextureBuffer(uint32_t /*texName*/, - const sp& /*buffer*/, - const sp& /*fence*/) { - return 0; - }; // EXCLUDES(mRenderingMutex); virtual void cacheExternalTextureBuffer(const sp& /*buffer*/){}; virtual void unbindExternalTextureBuffer(uint64_t /*bufferId*/){}; diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 953cbc6f3d..5453302428 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -116,21 +116,6 @@ void RenderEngineThreaded::dump(std::string& result) { result.assign(resultFuture.get()); } -bool RenderEngineThreaded::useNativeFenceSync() const { - std::promise resultPromise; - std::future 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(); -} - void RenderEngineThreaded::genTextures(size_t count, uint32_t* names) { std::promise resultPromise; std::future resultFuture = resultPromise.get_future(); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index ac9f606a83..cdfbd04872 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -45,7 +45,6 @@ public: void dump(std::string& result) override; - bool useNativeFenceSync() const override; void genTextures(size_t count, uint32_t* names) override; void deleteTextures(size_t count, uint32_t const* names) override; void cacheExternalTextureBuffer(const sp& buffer) override; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 159a215667..e25ffb5234 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -339,8 +339,6 @@ struct BaseDisplayVariant { EXPECT_CALL(*test->mComposer, presentDisplay(HWC_DISPLAY, _)).Times(1); EXPECT_CALL(*test->mComposer, getReleaseFences(HWC_DISPLAY, _, _)).Times(1); - EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); - EXPECT_CALL(*test->mDisplaySurface, onFrameCommitted()).Times(1); EXPECT_CALL(*test->mDisplaySurface, advanceFrame()).Times(1); @@ -449,8 +447,6 @@ struct PoweredOffDisplaySetupVariant : public BaseDisplayVariant static void setupCommonCompositionCallExpectations(CompositionTest* test) { - EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); - // TODO: This seems like an unnecessary call if display is powered off. EXPECT_CALL(*test->mComposer, setColorTransform(HWC_DISPLAY, _, Hwc2::ColorTransform::IDENTITY)) @@ -465,8 +461,6 @@ struct PoweredOffDisplaySetupVariant : public BaseDisplayVariantmRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); - // TODO: This seems like an unnecessary call if display is powered off. EXPECT_CALL(*test->mDisplaySurface, getClientTargetAcquireFence()) .WillRepeatedly(ReturnRef(test->mClientTargetAcquireFence)); @@ -549,7 +543,6 @@ struct BaseLayerProperties { enqueueBuffer(test, layer); Mock::VerifyAndClearExpectations(test->mMessageQueue); - EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); bool ignoredRecomputeVisibleRegions; layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0); Mock::VerifyAndClear(test->mRenderEngine); -- cgit v1.2.3-59-g8ed1b From 243dbc2c8dc53717255f318f50a000d56cbabf04 Mon Sep 17 00:00:00 2001 From: Ana Krulec Date: Wed, 6 Jan 2021 13:17:08 -0800 Subject: Creating Threaded Skia GL RE The RE creates a thread and intializes SkiaGLRenderEngine on it. This first pass is synchronous communication. Test: adb shell setprop debug.renderengine.backend "skiaglthreaded" Change-Id: I9811c51f8cc2a999fb2587067bd5dd3a5a972cd1 --- libs/renderengine/RenderEngine.cpp | 7 +++++++ libs/renderengine/include/renderengine/RenderEngine.h | 1 + 2 files changed, 8 insertions(+) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 3e65d9afce..45db31c026 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -41,6 +41,9 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg if (strcmp(prop, "skiagl") == 0) { renderEngineType = RenderEngineType::SKIA_GL; } + if (strcmp(prop, "skiaglthreaded") == 0) { + renderEngineType = RenderEngineType::SKIA_GL_THREADED; + } switch (renderEngineType) { case RenderEngineType::THREADED: @@ -49,6 +52,10 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); case RenderEngineType::SKIA_GL: return renderengine::skia::SkiaGLRenderEngine::create(args); + case RenderEngineType::SKIA_GL_THREADED: + return renderengine::threaded::RenderEngineThreaded::create([args]() { + return android::renderengine::skia::SkiaGLRenderEngine::create(args); + }); case RenderEngineType::GLES: default: ALOGD("RenderEngine with GLES Backend"); diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 915706675a..506f81ecc2 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -82,6 +82,7 @@ public: GLES = 1, THREADED = 2, SKIA_GL = 3, + SKIA_GL_THREADED = 4, }; static std::unique_ptr create(const RenderEngineCreationArgs& args); -- cgit v1.2.3-59-g8ed1b From dfec8f5f9665e4088900cd76f656f480a10ed464 Mon Sep 17 00:00:00 2001 From: Ana Krulec Date: Wed, 13 Jan 2021 12:51:47 -0800 Subject: Caching images and textures for threaded Skia RE Skia also performs texture generation and deletion when we create an image. This needs to happen on the same thread. Running Skia on it's own thread, will allow async caching of images, and hopefully increasing the start up/transition of application. Screenshot of the parallel caching: https://screenshot.googleplex.com/BUnne3urcoavykk Test results for DisplayOrientationMicrobench test for SFSTATS_GLOBAL_RENDER_ENGINE_DURATION_AVG metric: skiathreaded 1st run: 5.750296 ms skia threaded 2nd run: 5.530306 ms gles: 4.974821 ms skia: 6.374791 ms Test: Set renderengine backend to 'skiathreaded'. - run libsurfaceflinger_test, SurfaceFlinger_test - open apps - switch between apps Bug: 175312877 Change-Id: I6521f9ddfadff8c839bdd7071c2bd6cfadebb663 --- libs/renderengine/RenderEngine.cpp | 23 +++++++++++++++--- libs/renderengine/gl/GLESRenderEngine.cpp | 1 + libs/renderengine/skia/AutoBackendTexture.h | 2 +- libs/renderengine/skia/SkiaGLRenderEngine.cpp | 28 +++++++++++++++++++++- libs/renderengine/skia/SkiaGLRenderEngine.h | 5 ++++ .../tests/RenderEngineThreadedTest.cpp | 16 ------------- .../renderengine/threaded/RenderEngineThreaded.cpp | 16 +++++-------- 7 files changed, 60 insertions(+), 31 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 45db31c026..b2ad22d687 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -51,11 +51,28 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg return renderengine::threaded::RenderEngineThreaded::create( [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); case RenderEngineType::SKIA_GL: + ALOGD("RenderEngine with SkiaGL Backend"); return renderengine::skia::SkiaGLRenderEngine::create(args); - case RenderEngineType::SKIA_GL_THREADED: - return renderengine::threaded::RenderEngineThreaded::create([args]() { - return android::renderengine::skia::SkiaGLRenderEngine::create(args); + case RenderEngineType::SKIA_GL_THREADED: { + // These need to be recreated, since they are a constant reference, and we need to + // let SkiaRE know that it's running as threaded, and all GL operation will happen on + // the same thread. + RenderEngineCreationArgs skiaArgs = + RenderEngineCreationArgs::Builder() + .setPixelFormat(args.pixelFormat) + .setImageCacheSize(args.imageCacheSize) + .setUseColorManagerment(args.useColorManagement) + .setEnableProtectedContext(args.enableProtectedContext) + .setPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly) + .setSupportsBackgroundBlur(args.supportsBackgroundBlur) + .setContextPriority(args.contextPriority) + .setRenderEngineType(RenderEngineType::SKIA_GL_THREADED) + .build(); + ALOGD("Threaded RenderEngine with SkiaGL Backend"); + return renderengine::threaded::RenderEngineThreaded::create([skiaArgs]() { + return android::renderengine::skia::SkiaGLRenderEngine::create(skiaArgs); }); + } case RenderEngineType::GLES: default: ALOGD("RenderEngine with GLES Backend"); diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index c88e29879b..70ae0b288a 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -746,6 +746,7 @@ void GLESRenderEngine::bindExternalTextureBuffer(uint32_t texName, const sp& buffer) { + ATRACE_CALL(); mImageManager->cacheAsync(buffer, nullptr); } diff --git a/libs/renderengine/skia/AutoBackendTexture.h b/libs/renderengine/skia/AutoBackendTexture.h index 30f4b77573..bb758780e1 100644 --- a/libs/renderengine/skia/AutoBackendTexture.h +++ b/libs/renderengine/skia/AutoBackendTexture.h @@ -30,7 +30,7 @@ namespace renderengine { namespace skia { /** - * AutoBackendTexture manages GPU image lifetime. It is a ref-counted object + * AutoBackendTexture manages GPU image lifetime. It is a ref-counted object * that keeps GPU resources alive until the last SkImage or SkSurface object using them is * destroyed. */ diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index dc04f69dc6..03e3339114 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -267,7 +267,8 @@ SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGL mPlaceholderSurface(placeholder), mProtectedEGLContext(protectedContext), mProtectedPlaceholderSurface(protectedPlaceholder), - mUseColorManagement(args.useColorManagement) { + mUseColorManagement(args.useColorManagement), + mRenderEngineType(args.renderEngineType) { sk_sp glInterface(GrGLCreateNativeInterface()); LOG_ALWAYS_FATAL_IF(!glInterface.get()); @@ -453,7 +454,30 @@ static bool needsLinearEffect(const mat4& colorTransform, ui::Dataspace sourceDa return colorTransform != mat4() || needsToneMapping(sourceDataspace, destinationDataspace); } +void SkiaGLRenderEngine::cacheExternalTextureBuffer(const sp& buffer) { + // Only run this if RE is running on its own thread. This way the access to GL + // operations is guaranteed to be happening on the same thread. + if (mRenderEngineType != RenderEngineType::SKIA_GL_THREADED) { + return; + } + ATRACE_CALL(); + + std::lock_guard lock(mRenderingMutex); + auto iter = mTextureCache.find(buffer->getId()); + if (iter != mTextureCache.end()) { + ALOGV("Texture already exists in cache."); + return; + } else { + std::shared_ptr imageTextureRef = + std::make_shared(); + imageTextureRef->setTexture( + new AutoBackendTexture(mGrContext.get(), buffer->toAHardwareBuffer(), false)); + mTextureCache.insert({buffer->getId(), imageTextureRef}); + } +} + void SkiaGLRenderEngine::unbindExternalTextureBuffer(uint64_t bufferId) { + ATRACE_CALL(); std::lock_guard lock(mRenderingMutex); mTextureCache.erase(bufferId); mProtectedTextureCache.erase(bufferId); @@ -523,11 +547,13 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, auto iter = cache.find(buffer->getId()); if (iter != cache.end()) { ALOGV("Cache hit!"); + ATRACE_NAME("Cache hit"); surfaceTextureRef = iter->second; } } if (surfaceTextureRef == nullptr || surfaceTextureRef->getTexture() == nullptr) { + ATRACE_NAME("Cache miss"); surfaceTextureRef = std::make_shared(); surfaceTextureRef->setTexture( new AutoBackendTexture(grContext.get(), buffer->toAHardwareBuffer(), true)); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index ed62a2a84f..e344f41c8f 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -50,6 +50,7 @@ public: EGLSurface protectedPlaceholder); ~SkiaGLRenderEngine() override EXCLUDES(mRenderingMutex); + void cacheExternalTextureBuffer(const sp& buffer) override; void unbindExternalTextureBuffer(uint64_t bufferId) override; status_t drawLayers(const DisplaySettings& display, const std::vector& layers, @@ -128,6 +129,10 @@ private: bool mInProtectedContext = false; // Object to capture commands send to Skia. std::unique_ptr mCapture; + + // Keep this information as a local variable to determine whether the access of the GL + // operations is working on the same threads. + const RenderEngineType mRenderEngineType = RenderEngineType::SKIA_GL; }; } // namespace skia diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index ba5175d985..02ff06f393 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -62,22 +62,6 @@ TEST_F(RenderEngineThreadedTest, deleteTextures) { mThreadedRE->deleteTextures(1, &texName); } -TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_nullptr) { - EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(Eq(nullptr))); - mThreadedRE->cacheExternalTextureBuffer(nullptr); -} - -TEST_F(RenderEngineThreadedTest, cacheExternalTextureBuffer_withBuffer) { - sp buf = new GraphicBuffer(); - EXPECT_CALL(*mRenderEngine, cacheExternalTextureBuffer(buf)); - mThreadedRE->cacheExternalTextureBuffer(buf); -} - -TEST_F(RenderEngineThreadedTest, unbindExternalTextureBuffer) { - EXPECT_CALL(*mRenderEngine, unbindExternalTextureBuffer(0x0)); - mThreadedRE->unbindExternalTextureBuffer(0x0); -} - TEST_F(RenderEngineThreadedTest, getMaxTextureSize_returns20) { size_t size = 20; EXPECT_CALL(*mRenderEngine, getMaxTextureSize()).WillOnce(Return(size)); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index 08f2949f0a..3b97f5659e 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -147,33 +147,29 @@ void RenderEngineThreaded::deleteTextures(size_t count, uint32_t const* names) { } void RenderEngineThreaded::cacheExternalTextureBuffer(const sp& buffer) { - std::promise resultPromise; - std::future 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, &buffer](renderengine::RenderEngine& instance) { + mFunctionCalls.push([=](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::cacheExternalTextureBuffer"); instance.cacheExternalTextureBuffer(buffer); - resultPromise.set_value(); }); } mCondition.notify_one(); - resultFuture.wait(); } void RenderEngineThreaded::unbindExternalTextureBuffer(uint64_t bufferId) { - std::promise resultPromise; - std::future 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, &bufferId](renderengine::RenderEngine& instance) { + mFunctionCalls.push([=](renderengine::RenderEngine& instance) { ATRACE_NAME("REThreaded::unbindExternalTextureBuffer"); instance.unbindExternalTextureBuffer(bufferId); - resultPromise.set_value(); }); } mCondition.notify_one(); - resultFuture.wait(); } size_t RenderEngineThreaded::getMaxTextureSize() const { -- cgit v1.2.3-59-g8ed1b From 0d995106c0fb4480ac1de5f58667d918fa9aea62 Mon Sep 17 00:00:00 2001 From: Alec Mouri Date: Wed, 24 Feb 2021 16:53:38 -0800 Subject: Dispatch texture destruction off of render thread for screenshots This is only enabled when the skia threaded variant renderengine is enabled. This essentially defers texture deletion until after drawLayers() is invoked, which shaves off time from the main SF thread. Bug: 179959621 Bug: 180767535 Test: perfetto trace Change-Id: I333091d8792fdd0dc01076c73af2956da9ee73df --- libs/renderengine/RenderEngine.cpp | 13 ++++++++----- libs/renderengine/gl/GLESRenderEngine.cpp | 3 ++- libs/renderengine/include/renderengine/RenderEngine.h | 10 ++++++++++ libs/renderengine/skia/SkiaGLRenderEngine.cpp | 6 +++--- libs/renderengine/skia/SkiaGLRenderEngine.h | 4 ---- libs/renderengine/skia/SkiaRenderEngine.h | 1 + libs/renderengine/tests/RenderEngineThreadedTest.cpp | 3 ++- libs/renderengine/threaded/RenderEngineThreaded.cpp | 8 +++++--- libs/renderengine/threaded/RenderEngineThreaded.h | 5 +++-- services/surfaceflinger/RegionSamplingThread.cpp | 6 ++++++ services/surfaceflinger/SurfaceFlinger.cpp | 15 ++++++++++++++- 11 files changed, 54 insertions(+), 20 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index b2ad22d687..79839c1f91 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -49,7 +49,8 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg case RenderEngineType::THREADED: ALOGD("Threaded RenderEngine with GLES Backend"); return renderengine::threaded::RenderEngineThreaded::create( - [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }); + [args]() { return android::renderengine::gl::GLESRenderEngine::create(args); }, + renderEngineType); case RenderEngineType::SKIA_GL: ALOGD("RenderEngine with SkiaGL Backend"); return renderengine::skia::SkiaGLRenderEngine::create(args); @@ -66,12 +67,14 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg .setPrecacheToneMapperShaderOnly(args.precacheToneMapperShaderOnly) .setSupportsBackgroundBlur(args.supportsBackgroundBlur) .setContextPriority(args.contextPriority) - .setRenderEngineType(RenderEngineType::SKIA_GL_THREADED) + .setRenderEngineType(renderEngineType) .build(); ALOGD("Threaded RenderEngine with SkiaGL Backend"); - return renderengine::threaded::RenderEngineThreaded::create([skiaArgs]() { - return android::renderengine::skia::SkiaGLRenderEngine::create(skiaArgs); - }); + return renderengine::threaded::RenderEngineThreaded::create( + [skiaArgs]() { + return android::renderengine::skia::SkiaGLRenderEngine::create(skiaArgs); + }, + renderEngineType); } case RenderEngineType::GLES: default: diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 70ae0b288a..397f0384f2 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -379,7 +379,8 @@ EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface stub, EGLContext protectedContext, EGLSurface protectedStub) - : mEGLDisplay(display), + : RenderEngine(args.renderEngineType), + mEGLDisplay(display), mEGLConfig(config), mEGLContext(ctxt), mStubSurface(stub), diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 163a163fb2..572d348240 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -87,6 +87,10 @@ public: static std::unique_ptr create(const RenderEngineCreationArgs& args); + RenderEngine() : RenderEngine(RenderEngineType::GLES) {} + + RenderEngine(RenderEngineType type) : mRenderEngineType(type) {} + virtual ~RenderEngine() = 0; // ----- BEGIN DEPRECATED INTERFACE ----- @@ -192,8 +196,14 @@ public: // also supports background blur. If false, no blur will be applied when drawing layers. virtual bool supportsBackgroundBlur() = 0; + // Returns the current type of RenderEngine instance that was created. + // TODO(b/180767535): This is only implemented to allow for backend-specific behavior, which + // we should not allow in general, so remove this. + RenderEngineType getRenderEngineType() const { return mRenderEngineType; } + protected: friend class threaded::RenderEngineThreaded; + const RenderEngineType mRenderEngineType; }; struct RenderEngineCreationArgs { diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index 327b04c699..7cf672a090 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -266,13 +266,13 @@ EGLConfig SkiaGLRenderEngine::chooseEglConfig(EGLDisplay display, int format, bo SkiaGLRenderEngine::SkiaGLRenderEngine(const RenderEngineCreationArgs& args, EGLDisplay display, EGLContext ctxt, EGLSurface placeholder, EGLContext protectedContext, EGLSurface protectedPlaceholder) - : mEGLDisplay(display), + : SkiaRenderEngine(args.renderEngineType), + mEGLDisplay(display), mEGLContext(ctxt), mPlaceholderSurface(placeholder), mProtectedEGLContext(protectedContext), mProtectedPlaceholderSurface(protectedPlaceholder), - mUseColorManagement(args.useColorManagement), - mRenderEngineType(args.renderEngineType) { + mUseColorManagement(args.useColorManagement) { sk_sp glInterface(GrGLCreateNativeInterface()); LOG_ALWAYS_FATAL_IF(!glInterface.get()); diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.h b/libs/renderengine/skia/SkiaGLRenderEngine.h index 5779ae679b..a8853e0245 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.h +++ b/libs/renderengine/skia/SkiaGLRenderEngine.h @@ -129,10 +129,6 @@ private: bool mInProtectedContext = false; // Object to capture commands send to Skia. std::unique_ptr mCapture; - - // Keep this information as a local variable to determine whether the access of the GL - // operations is working on the same threads. - const RenderEngineType mRenderEngineType = RenderEngineType::SKIA_GL; }; } // namespace skia diff --git a/libs/renderengine/skia/SkiaRenderEngine.h b/libs/renderengine/skia/SkiaRenderEngine.h index 12b8586ad7..79a1040b78 100644 --- a/libs/renderengine/skia/SkiaRenderEngine.h +++ b/libs/renderengine/skia/SkiaRenderEngine.h @@ -36,6 +36,7 @@ class BlurFilter; class SkiaRenderEngine : public RenderEngine { public: static std::unique_ptr create(const RenderEngineCreationArgs& args); + SkiaRenderEngine(RenderEngineType type) : RenderEngine(type) {} ~SkiaRenderEngine() override {} virtual void primeCache() const override{}; diff --git a/libs/renderengine/tests/RenderEngineThreadedTest.cpp b/libs/renderengine/tests/RenderEngineThreadedTest.cpp index 08b672a99f..63aa4c891c 100644 --- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp +++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp @@ -32,7 +32,8 @@ struct RenderEngineThreadedTest : public ::testing::Test { void SetUp() override { mThreadedRE = renderengine::threaded::RenderEngineThreaded::create( - [this]() { return std::unique_ptr(mRenderEngine); }); + [this]() { return std::unique_ptr(mRenderEngine); }, + renderengine::RenderEngine::RenderEngineType::THREADED); } std::unique_ptr mThreadedRE; diff --git a/libs/renderengine/threaded/RenderEngineThreaded.cpp b/libs/renderengine/threaded/RenderEngineThreaded.cpp index f4481358cf..7c7d165c04 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.cpp +++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp @@ -34,11 +34,13 @@ namespace android { namespace renderengine { namespace threaded { -std::unique_ptr RenderEngineThreaded::create(CreateInstanceFactory factory) { - return std::make_unique(std::move(factory)); +std::unique_ptr RenderEngineThreaded::create(CreateInstanceFactory factory, + RenderEngineType type) { + return std::make_unique(std::move(factory), type); } -RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory) { +RenderEngineThreaded::RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type) + : RenderEngine(type) { ATRACE_CALL(); std::lock_guard lockThread(mThreadMutex); diff --git a/libs/renderengine/threaded/RenderEngineThreaded.h b/libs/renderengine/threaded/RenderEngineThreaded.h index 8279cbcd09..d362e176d3 100644 --- a/libs/renderengine/threaded/RenderEngineThreaded.h +++ b/libs/renderengine/threaded/RenderEngineThreaded.h @@ -37,9 +37,10 @@ using CreateInstanceFactory = std::function create(CreateInstanceFactory factory); + static std::unique_ptr create(CreateInstanceFactory factory, + RenderEngineType type); - RenderEngineThreaded(CreateInstanceFactory factory); + RenderEngineThreaded(CreateInstanceFactory factory, RenderEngineType type); ~RenderEngineThreaded() override; void primeCache() const override; diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 09615f920d..e06bc88f7c 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -481,6 +481,12 @@ void RegionSamplingThread::captureSample() { // 1) The region sampling thread is the last owner of the buffer, and the freeing of the buffer // happens in this thread, as opposed to the main thread. // 2) The listener(s) receive their notifications prior to freeing the buffer. + if (mCachedBuffer != nullptr && mCachedBuffer != buffer) { + if (mFlinger.getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { + mFlinger.getRenderEngine().unbindExternalTextureBuffer(mCachedBuffer->getId()); + } + } mCachedBuffer = buffer; ATRACE_INT(lumaSamplingStepTag, static_cast(samplingStep::noWorkNeeded)); } diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index da8360edaf..4215d20ceb 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5858,6 +5858,15 @@ status_t SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, regionSampling, grayscale, captureResults); }); + // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine + // Only do this when we're not doing region sampling, to allow the region sampling thread to + // manage buffer lifecycle itself. + if (!regionSampling && + getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED) { + getRenderEngine().unbindExternalTextureBuffer(buffer->getId()); + } + captureResults.result = result; captureListener->onScreenCaptureCompleted(captureResults); })); @@ -5977,8 +5986,12 @@ status_t SurfaceFlinger::renderScreenImplLocked(const RenderArea& renderArea, base::unique_fd bufferFence; base::unique_fd drawFence; getRenderEngine().useProtectedContext(useProtected); + + // TODO(b/180767535): Remove this once we optimize buffer lifecycle for RenderEngine + const bool useFramebufferCache = getRenderEngine().getRenderEngineType() == + renderengine::RenderEngine::RenderEngineType::SKIA_GL_THREADED; getRenderEngine().drawLayers(clientCompositionDisplay, clientCompositionLayerPointers, buffer, - /*useFramebufferCache=*/false, std::move(bufferFence), &drawFence); + useFramebufferCache, std::move(bufferFence), &drawFence); if (drawFence >= 0) { sp releaseFence = new Fence(dup(drawFence)); -- cgit v1.2.3-59-g8ed1b From 193426d6c539d4638d6416e9e0caaa62f18fa7ac Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Thu, 18 Feb 2021 14:01:53 -0800 Subject: SF: add buffer checks to Render Engine Make sure that both input and output buffers are GPU accessible before Render Engine tries to do something with the buffers. Test: Boot, launch an app, take a screenshot Bug: 158790260 Change-Id: I905a670f6cc2d419b49fe79694df6e71d60a2a92 --- libs/renderengine/RenderEngine.cpp | 10 ++++ libs/renderengine/gl/GLESRenderEngine.cpp | 3 ++ .../include/renderengine/RenderEngine.h | 3 ++ libs/renderengine/skia/SkiaGLRenderEngine.cpp | 3 ++ services/surfaceflinger/tests/BufferGenerator.cpp | 2 +- .../tests/LayerRenderTypeTransaction_test.cpp | 63 ++++++---------------- .../surfaceflinger/tests/LayerTransactionTest.h | 4 +- .../LayerTypeAndRenderTypeTransaction_test.cpp | 13 ++--- 8 files changed, 42 insertions(+), 59 deletions(-) (limited to 'libs/renderengine/RenderEngine.cpp') diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp index 79839c1f91..0c5a851c41 100644 --- a/libs/renderengine/RenderEngine.cpp +++ b/libs/renderengine/RenderEngine.cpp @@ -85,5 +85,15 @@ std::unique_ptr RenderEngine::create(const RenderEngineCreationArg RenderEngine::~RenderEngine() = default; +void RenderEngine::validateInputBufferUsage(const sp& buffer) { + LOG_ALWAYS_FATAL_IF(!(buffer->getUsage() & GraphicBuffer::USAGE_HW_TEXTURE), + "input buffer not gpu readable"); +} + +void RenderEngine::validateOutputBufferUsage(const sp& buffer) { + LOG_ALWAYS_FATAL_IF(!(buffer->getUsage() & GraphicBuffer::USAGE_HW_RENDER), + "output buffer not gpu writeable"); +} + } // namespace renderengine } // namespace android diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp index 397f0384f2..2b09c15f95 100644 --- a/libs/renderengine/gl/GLESRenderEngine.cpp +++ b/libs/renderengine/gl/GLESRenderEngine.cpp @@ -1125,6 +1125,8 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } + validateOutputBufferUsage(buffer); + std::unique_ptr fbo; // Gathering layers that requested blur, we'll need them to decide when to render to an // offscreen buffer, and when to render to the native buffer. @@ -1249,6 +1251,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display, isOpaque = layer->source.buffer.isOpaque; sp gBuf = layer->source.buffer.buffer; + validateInputBufferUsage(gBuf); bindExternalTextureBuffer(layer->source.buffer.textureName, gBuf, layer->source.buffer.fence); diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h index 572d348240..ddae34a26e 100644 --- a/libs/renderengine/include/renderengine/RenderEngine.h +++ b/libs/renderengine/include/renderengine/RenderEngine.h @@ -201,6 +201,9 @@ public: // we should not allow in general, so remove this. RenderEngineType getRenderEngineType() const { return mRenderEngineType; } + static void validateInputBufferUsage(const sp&); + static void validateOutputBufferUsage(const sp&); + protected: friend class threaded::RenderEngineThreaded; const RenderEngineType mRenderEngineType; diff --git a/libs/renderengine/skia/SkiaGLRenderEngine.cpp b/libs/renderengine/skia/SkiaGLRenderEngine.cpp index cbb02a37d2..91b163eda8 100644 --- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp +++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp @@ -598,6 +598,8 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, return BAD_VALUE; } + validateOutputBufferUsage(buffer); + auto grContext = mInProtectedContext ? mProtectedGrContext : mGrContext; auto& cache = mInProtectedContext ? mProtectedTextureCache : mTextureCache; AHardwareBuffer_Desc bufferDesc; @@ -815,6 +817,7 @@ status_t SkiaGLRenderEngine::drawLayers(const DisplaySettings& display, SkPaint paint; if (layer->source.buffer.buffer) { ATRACE_NAME("DrawImage"); + validateInputBufferUsage(layer->source.buffer.buffer); const auto& item = layer->source.buffer; std::shared_ptr imageTextureRef = nullptr; auto iter = mTextureCache.find(item.buffer->getId()); diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 4868c1224a..03f8e1afba 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -70,7 +70,7 @@ public: consumer->setDefaultBufferSize(width, height); consumer->setDefaultBufferFormat(format); - mBufferItemConsumer = new BufferItemConsumer(consumer, 0); + mBufferItemConsumer = new BufferItemConsumer(consumer, GraphicBuffer::USAGE_HW_TEXTURE); mListener = new BufferListener(consumer, callback); mBufferItemConsumer->setFrameAvailableListener(mListener); diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 52e1a4d967..b35eaa980c 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -43,6 +43,9 @@ public: protected: LayerRenderPathTestHarness mHarness; + + static constexpr int64_t kUsageFlags = BufferUsage::CPU_READ_OFTEN | + BufferUsage::CPU_WRITE_OFTEN | BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE; }; INSTANTIATE_TEST_CASE_P(LayerRenderTypeTransactionTests, LayerRenderTypeTransactionTest, @@ -377,10 +380,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); ASSERT_NO_FATAL_FAILURE( TransactionUtils::fillGraphicBufferColor(buffer, top, Color::TRANSPARENT)); @@ -405,10 +405,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetTransparentRegionHintBasic_BufferState shot->expectColor(bottom, Color::BLACK); } - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); ASSERT_NO_FATAL_FAILURE(TransactionUtils::fillGraphicBufferColor(buffer, top, Color::RED)); ASSERT_NO_FATAL_FAILURE( @@ -1015,10 +1012,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropOutOfBounds_BufferState) { ASSERT_NO_FATAL_FAILURE( layer = createLayer("test", 32, 64, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 64, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 64, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 16), Color::BLUE); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 16, 32, 64), Color::RED); @@ -1341,10 +1335,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_BufferState) { size_t idx = 0; for (auto& buffer : buffers) { - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); Color color = colors[idx % colors.size()]; TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); idx++; @@ -1377,10 +1368,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_LeastRecentlyUsed_Buffer size_t idx = 0; for (auto& buffer : buffers) { - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); Color color = colors[idx % colors.size()]; TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); idx++; @@ -1413,10 +1401,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetBufferCaching_DestroyedBuffer_BufferSt size_t idx = 0; for (auto& buffer : buffers) { - buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + buffer = new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); Color color = colors[idx % colors.size()]; TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), color); idx++; @@ -1499,10 +1484,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceBasic_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); sp fence; @@ -1528,10 +1510,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetFenceNull_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); sp fence = Fence::NO_FENCE; @@ -1549,10 +1528,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetDataspaceBasic_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); Transaction().setBuffer(layer, buffer).setDataspace(layer, ui::Dataspace::UNKNOWN).apply(); @@ -1568,10 +1544,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetHdrMetadataBasic_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); HdrMetadata hdrMetadata; @@ -1589,10 +1562,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetSurfaceDamageRegionBasic_BufferState) layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); Region region; @@ -1610,10 +1580,7 @@ TEST_P(LayerRenderTypeTransactionTest, SetApiBasic_BufferState) { layer = createLayer("test", 32, 32, ISurfaceComposerClient::eFXSurfaceBufferState)); sp buffer = - new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(32, 32, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, 32, 32), Color::RED); Transaction().setBuffer(layer, buffer).setApi(layer, NATIVE_WINDOW_API_CPU).apply(); diff --git a/services/surfaceflinger/tests/LayerTransactionTest.h b/services/surfaceflinger/tests/LayerTransactionTest.h index 05729be34b..be6665b5ff 100644 --- a/services/surfaceflinger/tests/LayerTransactionTest.h +++ b/services/surfaceflinger/tests/LayerTransactionTest.h @@ -139,7 +139,7 @@ protected: sp buffer = new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, + BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE, "test"); TransactionUtils::fillGraphicBufferColor(buffer, Rect(0, 0, bufferWidth, bufferHeight), color); @@ -208,7 +208,7 @@ protected: sp buffer = new GraphicBuffer(bufferWidth, bufferHeight, PIXEL_FORMAT_RGBA_8888, 1, BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, + BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE, "test"); ASSERT_TRUE(bufferWidth % 2 == 0 && bufferHeight % 2 == 0); diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index 44e718921a..67db717296 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -39,6 +39,9 @@ public: protected: LayerRenderPathTestHarness mRenderPathHarness; + + static constexpr int64_t kUsageFlags = BufferUsage::CPU_READ_OFTEN | + BufferUsage::CPU_WRITE_OFTEN | BufferUsage::COMPOSER_OVERLAY | BufferUsage::GPU_TEXTURE; }; ::testing::Environment* const binderEnv = @@ -521,10 +524,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBufferFormat) { sp surface = layer->getSurface(); sp buffer = - new GraphicBuffer(width, height, PIXEL_FORMAT_RGBX_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + new GraphicBuffer(width, height, PIXEL_FORMAT_RGBX_8888, 1, kUsageFlags, "test"); ASSERT_NO_FATAL_FAILURE( TransactionUtils::fillGraphicBufferColor(buffer, crop, Color::TRANSPARENT)); @@ -540,10 +540,7 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetBufferFormat) { shot->expectColor(crop, Color::BLACK); } - buffer = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, 1, - BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN | - BufferUsage::COMPOSER_OVERLAY, - "test"); + buffer = new GraphicBuffer(width, height, PIXEL_FORMAT_RGBA_8888, 1, kUsageFlags, "test"); ASSERT_NO_FATAL_FAILURE( TransactionUtils::fillGraphicBufferColor(buffer, crop, Color::TRANSPARENT)); -- cgit v1.2.3-59-g8ed1b