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 {