summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ana Krulec <akrulec@google.com> 2021-01-13 12:51:47 -0800
committer Ana Krulec <akrulec@google.com> 2021-01-20 12:39:48 -0800
commitdfec8f5f9665e4088900cd76f656f480a10ed464 (patch)
tree667d5025fa5cf20a63c96ae2b1845986a73cccc6
parente74432c55a7bd6cc904ecb673ac567e343cfe89b (diff)
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
-rw-r--r--libs/renderengine/RenderEngine.cpp23
-rw-r--r--libs/renderengine/gl/GLESRenderEngine.cpp1
-rw-r--r--libs/renderengine/skia/AutoBackendTexture.h2
-rw-r--r--libs/renderengine/skia/SkiaGLRenderEngine.cpp28
-rw-r--r--libs/renderengine/skia/SkiaGLRenderEngine.h5
-rw-r--r--libs/renderengine/tests/RenderEngineThreadedTest.cpp16
-rw-r--r--libs/renderengine/threaded/RenderEngineThreaded.cpp16
7 files changed, 60 insertions, 31 deletions
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> 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<Grap
}
void GLESRenderEngine::cacheExternalTextureBuffer(const sp<GraphicBuffer>& 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<const GrGLInterface> 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<GraphicBuffer>& 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<std::mutex> lock(mRenderingMutex);
+ auto iter = mTextureCache.find(buffer->getId());
+ if (iter != mTextureCache.end()) {
+ ALOGV("Texture already exists in cache.");
+ return;
+ } else {
+ std::shared_ptr<AutoBackendTexture::LocalRef> imageTextureRef =
+ std::make_shared<AutoBackendTexture::LocalRef>();
+ 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<std::mutex> 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<AutoBackendTexture::LocalRef>();
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<GraphicBuffer>& buffer) override;
void unbindExternalTextureBuffer(uint64_t bufferId) override;
status_t drawLayers(const DisplaySettings& display,
const std::vector<const LayerSettings*>& layers,
@@ -128,6 +129,10 @@ private:
bool mInProtectedContext = false;
// Object to capture commands send to Skia.
std::unique_ptr<SkiaCapture> 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<GraphicBuffer> 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<GraphicBuffer>& buffer) {
- std::promise<void> resultPromise;
- std::future<void> resultFuture = resultPromise.get_future();
+ // This function is designed so it can run asynchronously, so we do not need to wait
+ // for the futures.
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise, &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<void> resultPromise;
- std::future<void> resultFuture = resultPromise.get_future();
+ // This function is designed so it can run asynchronously, so we do not need to wait
+ // for the futures.
{
std::lock_guard lock(mThreadMutex);
- mFunctionCalls.push([&resultPromise, &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 {