Revert "Revert "Distinguish between "flushed" and "finished" idle state callbacks on GrTexture.""

This reverts commit 88b8d1124b7280d379f7545eda4b9097a4d8a292.

Bug: skia:8800
Change-Id: I27f5da73b651b91af0c5440557f5986e493a1559
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/199080
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/include/gpu/GrTexture.h b/include/gpu/GrTexture.h
index e20ebb0..e8f8035 100644
--- a/include/gpu/GrTexture.h
+++ b/include/gpu/GrTexture.h
@@ -49,17 +49,31 @@
     }
 #endif
 
+    /** See addIdleProc. */
+    enum class IdleState {
+        kFlushed,
+        kFinished
+    };
     /**
-     * Installs a proc on this texture. It will be called when the texture becomes "idle". Idle is
-     * defined to mean that the texture has no refs or pending IOs and that GPU I/O operations on
-     * the texture are completed if the backend API disallows deletion of a texture before such
-     * operations occur (e.g. Vulkan). After the idle proc is called it is removed. The idle proc
-     * will always be called before the texture is destroyed, even in unusual shutdown scenarios
-     * (e.g. GrContext::abandonContext()).
+     * Installs a proc on this texture. It will be called when the texture becomes "idle". There
+     * are two types of idle states as indicated by IdleState. For managed backends (e.g. GL where
+     * a driver typically handles CPU/GPU synchronization of resource access) there is no difference
+     * between the two. They both mean "all work related to the resource has been flushed to the
+     * backend API and the texture is not owned outside the resource cache".
+     *
+     * If the API is unmanaged (e.g. Vulkan) then kFinished has the additional constraint that the
+     * work flushed to the GPU is finished.
      */
-    virtual void addIdleProc(sk_sp<GrRefCntedCallback> callback) {
-        callback->addChild(std::move(fIdleCallback));
-        fIdleCallback = std::move(callback);
+    virtual void addIdleProc(sk_sp<GrRefCntedCallback> idleProc, IdleState) {
+        // This is the default implementation for the managed case where the IdleState can be
+        // ignored. Unmanaged backends, e.g. Vulkan, must override this to consider IdleState.
+        fIdleProcs.push_back(std::move(idleProc));
+    }
+    /** Helper version of addIdleProc that creates the ref-counted wrapper. */
+    void addIdleProc(GrRefCntedCallback::Callback callback,
+                     GrRefCntedCallback::Context context,
+                     IdleState state) {
+        this->addIdleProc(sk_make_sp<GrRefCntedCallback>(callback, context), state);
     }
 
     /** Access methods that are only to be used within Skia code. */
@@ -71,11 +85,11 @@
 
     virtual bool onStealBackendTexture(GrBackendTexture*, SkImage::BackendTextureReleaseProc*) = 0;
 
-    sk_sp<GrRefCntedCallback> fIdleCallback;
+    SkTArray<sk_sp<GrRefCntedCallback>> fIdleProcs;
 
     void willRemoveLastRefOrPendingIO() override {
-        // We're about to be idle in the resource cache. Do our part to trigger the idle callback.
-        fIdleCallback.reset();
+        // We're about to be idle in the resource cache. Do our part to trigger the idle callbacks.
+        fIdleProcs.reset();
     }
 
 private: