Improve time to texture destruction

Eliminate textureCache.mGarbage which is only cleared
in a trimMemory. Instead when we hit ~Bitmap post a
message to RenderThread to release the texture immediately

Bug: 38258699
Test: manual
Change-Id: I962ba275e89afb628ba02f74769287edbab9fed4
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index a0366de..2fdfcd4 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -223,7 +223,6 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 void Caches::clearGarbage() {
-    textureCache.clearGarbage();
     pathCache.clearGarbage();
     patchCache.clearGarbage();
 }
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 63a6a2c..710cdd9 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -191,25 +191,14 @@
     return texture;
 }
 
-void TextureCache::releaseTexture(uint32_t pixelRefStableID) {
-    Mutex::Autolock _l(mLock);
-    mGarbage.push_back(pixelRefStableID);
-}
-
-void TextureCache::clearGarbage() {
-    Mutex::Autolock _l(mLock);
-    size_t count = mGarbage.size();
-    for (size_t i = 0; i < count; i++) {
-        uint32_t pixelRefId = mGarbage[i];
-        auto hardwareIter = mHardwareTextures.find(pixelRefId);
-        if (hardwareIter == mHardwareTextures.end()) {
-            mCache.remove(pixelRefId);
-        } else {
-            hardwareIter->second->deleteTexture();
-            mHardwareTextures.erase(hardwareIter);
-        }
+bool TextureCache::destroyTexture(uint32_t pixelRefStableID) {
+    auto hardwareIter = mHardwareTextures.find(pixelRefStableID);
+    if (hardwareIter != mHardwareTextures.end()) {
+        hardwareIter->second->deleteTexture();
+        mHardwareTextures.erase(hardwareIter);
+        return true;
     }
-    mGarbage.clear();
+    return mCache.remove(pixelRefStableID);
 }
 
 void TextureCache::clear() {
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index db4ff39..776ff8a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -94,14 +94,10 @@
     Texture* get(Bitmap* bitmap);
 
     /**
-     * Removes the texture associated with the specified pixelRef. This is meant
-     * to be called from threads that are not the EGL context thread.
+     * Removes the texture associated with the specified pixelRef. Must be called from RenderThread
+     * Returns true if a texture was destroyed, false if no texture with that id was found
      */
-    ANDROID_API void releaseTexture(uint32_t pixelRefStableID);
-    /**
-     * Process deferred removals.
-     */
-    void clearGarbage();
+    bool destroyTexture(uint32_t pixelRefStableID);
 
     /**
      * Clears the cache. This causes all textures to be deleted.
@@ -139,9 +135,7 @@
 
     bool mDebugEnabled;
 
-    std::vector<uint32_t> mGarbage;
     std::unordered_map<uint32_t, std::unique_ptr<Texture>> mHardwareTextures;
-    mutable Mutex mLock;
 }; // class TextureCache
 
 }; // namespace uirenderer
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index d765584..72be564 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -416,9 +416,7 @@
 
     }
 
-    if (android::uirenderer::Caches::hasInstance()) {
-        android::uirenderer::Caches::getInstance().textureCache.releaseTexture(getStableID());
-    }
+    android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID());
 }
 
 bool Bitmap::hasHardwareMipMap() const {
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index c8833d2..b89272e 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -122,6 +122,13 @@
     mCaches->flush(mode);
 }
 
+void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
+    if (mCaches->textureCache.destroyTexture(pixelRefId)) {
+        glFlush();
+        GL_CHECKPOINT(MODERATE);
+    }
+}
+
 void RenderState::setViewport(GLsizei width, GLsizei height) {
     mViewportWidth = width;
     mViewportHeight = height;
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index f78bf7a..787946f 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -63,6 +63,7 @@
     void onVkContextDestroyed();
 
     void flush(Caches::FlushMode flushMode);
+    void onBitmapDestroyed(uint32_t pixelRefId);
 
     void setViewport(GLsizei width, GLsizei height);
     void getViewport(GLsizei* outWidth, GLsizei* outHeight);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index a1f1717..eed5238 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -24,6 +24,7 @@
 #include "renderthread/EglManager.h"
 #include "renderthread/RenderTask.h"
 #include "renderthread/RenderThread.h"
+#include "renderstate/RenderState.h"
 #include "utils/Macros.h"
 #include "utils/TimeUtils.h"
 
@@ -693,6 +694,20 @@
     }
 }
 
+CREATE_BRIDGE2(onBitmapDestroyed, RenderThread* thread, uint32_t pixelRefId) {
+    args->thread->renderState().onBitmapDestroyed(args->pixelRefId);
+    return nullptr;
+}
+
+void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) {
+    if (!RenderThread::hasInstance()) return;
+    SETUP_TASK(onBitmapDestroyed);
+    RenderThread& thread = RenderThread::getInstance();
+    args->thread = &thread;
+    args->pixelRefId = pixelRefId;
+    thread.queue(task);
+}
+
 void RenderProxy::post(RenderTask* task) {
     mRenderThread.queue(task);
 }
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index a60ed55..b21772c 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -135,6 +135,8 @@
     static sk_sp<Bitmap> allocateHardwareBitmap(SkBitmap& bitmap);
 
     static int copyGraphicBufferInto(GraphicBuffer* buffer, SkBitmap* bitmap);
+
+    static void onBitmapDestroyed(uint32_t pixelRefId);
 private:
     RenderThread& mRenderThread;
     CanvasContext* mContext;