Merge "Caching images and textures for threaded Skia RE"
diff --git a/libs/renderengine/RenderEngine.cpp b/libs/renderengine/RenderEngine.cpp
index 45db31c..b2ad22d 100644
--- a/libs/renderengine/RenderEngine.cpp
+++ b/libs/renderengine/RenderEngine.cpp
@@ -51,11 +51,28 @@
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 c88e298..70ae0b2 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -746,6 +746,7 @@
}
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 30f4b77..bb75878 100644
--- a/libs/renderengine/skia/AutoBackendTexture.h
+++ b/libs/renderengine/skia/AutoBackendTexture.h
@@ -30,7 +30,7 @@
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 dc04f69..03e3339 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.cpp
@@ -267,7 +267,8 @@
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 @@
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 @@
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 ed62a2a..e344f41 100644
--- a/libs/renderengine/skia/SkiaGLRenderEngine.h
+++ b/libs/renderengine/skia/SkiaGLRenderEngine.h
@@ -50,6 +50,7 @@
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 @@
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 ba5175d..02ff06f 100644
--- a/libs/renderengine/tests/RenderEngineThreadedTest.cpp
+++ b/libs/renderengine/tests/RenderEngineThreadedTest.cpp
@@ -62,22 +62,6 @@
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 08f2949..3b97f56 100644
--- a/libs/renderengine/threaded/RenderEngineThreaded.cpp
+++ b/libs/renderengine/threaded/RenderEngineThreaded.cpp
@@ -147,33 +147,29 @@
}
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 {