Add postFlush call to GrOnFlushCallbackObject

Adds a new postFlush method and renames the class to
GrOnFlushCallbackObject. Also removes the ref counting in favor of
making the callback object a purely virtual interface. ref/unref on the
callback interface would conflict with existing ref/unref methods on the
subclass. It is now the caller’s responsibility to ensure the lifetime
of the callback is tied to that of the context.

Bug: skia:
Change-Id: I2fc1f98c700032e296a36f3a9a09c0753ab47aea
Reviewed-on: https://skia-review.googlesource.com/15463
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 2b34232..92dc7d6 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -122,8 +122,8 @@
   "$_src/gpu/GrPathUtils.cpp",
   "$_src/gpu/GrPathUtils.h",
   "$_src/gpu/GrPendingProgramElement.h",
-  "$_src/gpu/GrPreFlushResourceProvider.cpp",
-  "$_src/gpu/GrPreFlushResourceProvider.h",
+  "$_src/gpu/GrOnFlushResourceProvider.cpp",
+  "$_src/gpu/GrOnFlushResourceProvider.h",
   "$_src/gpu/GrPipeline.cpp",
   "$_src/gpu/GrPipeline.h",
   "$_src/gpu/GrPipelineBuilder.h",
diff --git a/gn/tests.gni b/gn/tests.gni
index be4389b..a0343f5 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -156,7 +156,7 @@
   "$_tests/PDFMetadataAttributeTest.cpp",
   "$_tests/PDFOpaqueSrcModeToSrcOverTest.cpp",
   "$_tests/PDFPrimitivesTest.cpp",
-  "$_tests/PreFlushCallbackTest.cpp",
+  "$_tests/OnFlushCallbackTest.cpp",
   "$_tests/PictureBBHTest.cpp",
   "$_tests/PictureShaderTest.cpp",
   "$_tests/PictureTest.cpp",
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index aa245b5..2d46b5c 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -750,8 +750,8 @@
                                                            surfaceProps);
 }
 
-void GrContextPriv::addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject> preFlushCBObject) {
-    fContext->fDrawingManager->addPreFlushCallbackObject(std::move(preFlushCBObject));
+void GrContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
+    fContext->fDrawingManager->addOnFlushCallbackObject(onFlushCBObject);
 }
 
 
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 08b26e5..c5f592b 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -14,7 +14,7 @@
 class GrBackendRenderTarget;
 class GrSemaphore;
 class GrSurfaceProxy;
-class GrPreFlushCallbackObject;
+class GrOnFlushCallbackObject;
 
 /** Class that adds methods to GrContext that are only intended for use internal to Skia.
     This class is purely a privileged window into GrContext. It should never have additional
@@ -76,11 +76,15 @@
      */
     void flush(GrSurfaceProxy*);
 
-    /*
-     * A ref will be taken on the preFlushCallbackObject which will be removed when the
-     * context is destroyed.
+    /**
+     * Registers an object for flush-related callbacks. (See GrOnFlushCallbackObject.)
+     *
+     * NOTE: the drawing manager tracks this object as a raw pointer; it is up to the caller to
+     * ensure its lifetime is tied to that of the context.
      */
-    void addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject>);
+    void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
+
+    void testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject*);
 
     /**
      * After this returns any pending writes to the surface will have been issued to the
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 9cc5845..5b8d37b 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -101,9 +101,9 @@
     SkASSERT(result);
 #endif
 
-    GrPreFlushResourceProvider preFlushProvider(this);
+    GrOnFlushResourceProvider onFlushProvider(this);
 
-    if (fPreFlushCBObjects.count()) {
+    if (!fOnFlushCBObjects.empty()) {
         // MDB TODO: pre-MDB '1' is the correct pre-allocated size. Post-MDB it will need
         // to be larger.
         SkAutoSTArray<1, uint32_t> opListIds(fOpLists.count());
@@ -112,10 +112,10 @@
         }
 
         SkSTArray<1, sk_sp<GrRenderTargetContext>> renderTargetContexts;
-        for (int i = 0; i < fPreFlushCBObjects.count(); ++i) {
-            fPreFlushCBObjects[i]->preFlush(&preFlushProvider,
-                                            opListIds.get(), opListIds.count(),
-                                            &renderTargetContexts);
+        for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
+            onFlushCBObject->preFlush(&onFlushProvider,
+                                      opListIds.get(), opListIds.count(),
+                                      &renderTargetContexts);
             if (!renderTargetContexts.count()) {
                 continue;       // This is fine. No atlases of this type are required for this flush
             }
@@ -178,6 +178,9 @@
     if (flushed || type == GrResourceCache::FlushType::kCacheRequested) {
         fContext->getResourceCache()->notifyFlushOccurred(type);
     }
+    for (GrOnFlushCallbackObject* onFlushCBObject : fOnFlushCBObjects) {
+        onFlushCBObject->postFlush();
+    }
     fFlushing = false;
 }
 
@@ -201,8 +204,8 @@
     }
 }
 
-void GrDrawingManager::addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject> preFlushCBObject) {
-    fPreFlushCBObjects.push_back(preFlushCBObject);
+void GrDrawingManager::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) {
+    fOnFlushCBObjects.push_back(onFlushCBObject);
 }
 
 sk_sp<GrRenderTargetOpList> GrDrawingManager::newRTOpList(sk_sp<GrRenderTargetProxy> rtp) {
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index 1990f9d..85a29df 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -11,7 +11,7 @@
 #include "GrOpFlushState.h"
 #include "GrPathRenderer.h"
 #include "GrPathRendererChain.h"
-#include "GrPreFlushResourceProvider.h"
+#include "GrOnFlushResourceProvider.h"
 #include "GrRenderTargetOpList.h"
 #include "GrResourceCache.h"
 #include "SkTArray.h"
@@ -71,7 +71,8 @@
 
     void prepareSurfaceForExternalIO(GrSurfaceProxy*);
 
-    void addPreFlushCallbackObject(sk_sp<GrPreFlushCallbackObject> preFlushCBObject);
+    void addOnFlushCallbackObject(GrOnFlushCallbackObject*);
+    void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
 
 private:
     GrDrawingManager(GrContext* context,
@@ -99,7 +100,7 @@
 
     friend class GrContext;  // for access to: ctor, abandon, reset & flush
     friend class GrContextPriv; // access to: flush
-    friend class GrPreFlushResourceProvider; // this is just a shallow wrapper around this class
+    friend class GrOnFlushResourceProvider; // this is just a shallow wrapper around this class
 
     static const int kNumPixelGeometries = 5; // The different pixel geometries
     static const int kNumDFTOptions = 2;      // DFT or no DFT
@@ -123,7 +124,7 @@
 
     bool                              fIsImmediateMode;
 
-    SkTArray<sk_sp<GrPreFlushCallbackObject>> fPreFlushCBObjects;
+    SkTArray<GrOnFlushCallbackObject*> fOnFlushCBObjects;
 
     // Lazily allocated
     std::unique_ptr<gr_instanced::OpAllocator> fInstancingAllocator;
diff --git a/src/gpu/GrPreFlushResourceProvider.cpp b/src/gpu/GrOnFlushResourceProvider.cpp
similarity index 94%
rename from src/gpu/GrPreFlushResourceProvider.cpp
rename to src/gpu/GrOnFlushResourceProvider.cpp
index 43037be..377c1f6 100644
--- a/src/gpu/GrPreFlushResourceProvider.cpp
+++ b/src/gpu/GrOnFlushResourceProvider.cpp
@@ -5,12 +5,12 @@
  * found in the LICENSE file.
  */
 
-#include "GrPreFlushResourceProvider.h"
+#include "GrOnFlushResourceProvider.h"
 
 #include "GrDrawingManager.h"
 #include "GrSurfaceProxy.h"
 
-sk_sp<GrRenderTargetContext> GrPreFlushResourceProvider::makeRenderTargetContext(
+sk_sp<GrRenderTargetContext> GrOnFlushResourceProvider::makeRenderTargetContext(
                                                         const GrSurfaceDesc& desc,
                                                         sk_sp<SkColorSpace> colorSpace,
                                                         const SkSurfaceProps* props) {
@@ -54,7 +54,7 @@
 
 // TODO: we only need this entry point as long as we have to pre-allocate the atlas.
 // Remove it ASAP.
-sk_sp<GrRenderTargetContext> GrPreFlushResourceProvider::makeRenderTargetContext(
+sk_sp<GrRenderTargetContext> GrOnFlushResourceProvider::makeRenderTargetContext(
                                                         sk_sp<GrSurfaceProxy> proxy,
                                                         sk_sp<SkColorSpace> colorSpace,
                                                         const SkSurfaceProps* props) {
diff --git a/src/gpu/GrPreFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h
similarity index 65%
rename from src/gpu/GrPreFlushResourceProvider.h
rename to src/gpu/GrOnFlushResourceProvider.h
index 5f4b96b..b29dc9c 100644
--- a/src/gpu/GrPreFlushResourceProvider.h
+++ b/src/gpu/GrOnFlushResourceProvider.h
@@ -5,19 +5,16 @@
  * found in the LICENSE file.
  */
 
-#ifndef GrPreFlushResourceProvider_DEFINED
-#define GrPreFlushResourceProvider_DEFINED
+#ifndef GrOnFlushResourceProvider_DEFINED
+#define GrOnFlushResourceProvider_DEFINED
 
 #include "GrTypes.h"
-#include "GrNonAtomicRef.h"
-
-// These two are just for GrPreFlushCallbackObject
 #include "SkRefCnt.h"
-#include "SkTDArray.h"
+#include "SkTArray.h"
 
 class GrDrawingManager;
 class GrOpList;
-class GrPreFlushResourceProvider;
+class GrOnFlushResourceProvider;
 class GrRenderTargetOpList;
 class GrRenderTargetContext;
 class GrSurfaceProxy;
@@ -27,32 +24,38 @@
 
 /*
  * This is the base class from which all pre-flush callback objects must be derived. It
- * provides the "preFlush" interface.
+ * provides the "preFlush" / "postFlush" interface.
  */
-class GrPreFlushCallbackObject : public GrNonAtomicRef<GrPreFlushCallbackObject> {
+class GrOnFlushCallbackObject {
 public:
-    virtual ~GrPreFlushCallbackObject() { }
+    virtual ~GrOnFlushCallbackObject() { }
 
     /*
-     * The preFlush callback allows subsystems (e.g., text, path renderers) to create atlases
+     * The onFlush callback allows subsystems (e.g., text, path renderers) to create atlases
      * for a specific flush. All the GrOpList IDs required for the flush are passed into the
      * callback. The callback should return the render target contexts used to render the atlases
      * in 'results'.
      */
-    virtual void preFlush(GrPreFlushResourceProvider*,
+    virtual void preFlush(GrOnFlushResourceProvider*,
                           const uint32_t* opListIDs, int numOpListIDs,
                           SkTArray<sk_sp<GrRenderTargetContext>>* results) = 0;
 
+    /**
+     * Called once flushing is complete and all ops indicated by preFlush have been executed and
+     * released.
+     */
+    virtual void postFlush() {}
+
 private:
     typedef SkRefCnt INHERITED;
 };
 
 /*
  * This class is a shallow wrapper around the drawing manager. It is passed into the
- * preFlush callbacks and is intended to limit the functionality available to them.
+ * onFlush callbacks and is intended to limit the functionality available to them.
  * It should never have additional data members or virtual methods.
  */
-class GrPreFlushResourceProvider {
+class GrOnFlushResourceProvider {
 public:
     sk_sp<GrRenderTargetContext> makeRenderTargetContext(const GrSurfaceDesc& desc,
                                                          sk_sp<SkColorSpace> colorSpace,
@@ -65,9 +68,9 @@
                                                          const SkSurfaceProps* props);
 
 private:
-    explicit GrPreFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
-    GrPreFlushResourceProvider(const GrPreFlushResourceProvider&); // unimpl
-    GrPreFlushResourceProvider& operator=(const GrPreFlushResourceProvider&); // unimpl
+    explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
+    GrOnFlushResourceProvider(const GrOnFlushResourceProvider&) = delete;
+    GrOnFlushResourceProvider& operator=(const GrOnFlushResourceProvider&) = delete;
 
     GrDrawingManager* fDrawingMgr;
 
diff --git a/tests/PreFlushCallbackTest.cpp b/tests/OnFlushCallbackTest.cpp
similarity index 97%
rename from tests/PreFlushCallbackTest.cpp
rename to tests/OnFlushCallbackTest.cpp
index fc736a4..4adcad9 100644
--- a/tests/PreFlushCallbackTest.cpp
+++ b/tests/OnFlushCallbackTest.cpp
@@ -12,7 +12,7 @@
 #include "GrClip.h"
 #include "GrContextPriv.h"
 #include "GrDefaultGeoProcFactory.h"
-#include "GrPreFlushResourceProvider.h"
+#include "GrOnFlushResourceProvider.h"
 #include "GrRenderTargetContextPriv.h"
 #include "GrResourceProvider.h"
 #include "GrQuad.h"
@@ -244,7 +244,7 @@
 /*
  * This class aggregates the op information required for atlasing
  */
-class AtlasObject final : public GrPreFlushCallbackObject {
+class AtlasObject final : public GrOnFlushCallbackObject {
 public:
     AtlasObject() : fDone(false) { }
 
@@ -299,7 +299,7 @@
     /*
      * This callback back creates the atlas and updates the AtlasedRectOps to read from it
      */
-    void preFlush(GrPreFlushResourceProvider* resourceProvider,
+    void preFlush(GrOnFlushResourceProvider* resourceProvider,
                   const uint32_t* opListIDs, int numOpListIDs,
                   SkTArray<sk_sp<GrRenderTargetContext>>* results) override {
         SkASSERT(!results->count());
@@ -530,7 +530,7 @@
  * Note: until MDB lands, the atlas will actually have width= 9*kAtlasTileSize and look like:
  *           R G B C M Y K Grey White
  */
-DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(PreFlushCallbackTest, reporter, ctxInfo) {
+DEF_GPUTEST_FOR_GL_RENDERING_CONTEXTS(OnFlushCallbackTest, reporter, ctxInfo) {
     static const int kNumProxies = 3;
 
     GrContext* context = ctxInfo.grContext();
@@ -540,19 +540,19 @@
         return;
     }
 
-    sk_sp<AtlasObject> object = sk_make_sp<AtlasObject>();
+    AtlasObject object;
 
     // For now (until we add a GrSuperDeferredSimpleTextureEffect), we create the final atlas
     // proxy ahead of time.
     sk_sp<GrTextureProxy> atlasDest = pre_create_atlas(context);
 
-    object->setAtlasDest(atlasDest);
+    object.setAtlasDest(atlasDest);
 
-    context->contextPriv().addPreFlushCallbackObject(object);
+    context->contextPriv().addOnFlushCallbackObject(&object);
 
     sk_sp<GrTextureProxy> proxies[kNumProxies];
     for (int i = 0; i < kNumProxies; ++i) {
-        proxies[i] = make_upstream_image(context, object.get(), i*3, atlasDest);
+        proxies[i] = make_upstream_image(context, &object, i*3, atlasDest);
     }
 
     static const int kFinalWidth = 6*kDrawnTileSize;
@@ -592,7 +592,9 @@
                                                readBack.rowBytes(), 0, 0);
     SkASSERT(result);
 
-    object->markAsDone();
+    context->contextPriv().testingOnly_flushAndRemoveOnFlushCallbackObject(&object);
+
+    object.markAsDone();
 
 #if 0
     save_bm(readBack, "atlas-final-image.png");
diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp
index f5459b1..6dc21bb 100644
--- a/tools/gpu/GrTest.cpp
+++ b/tools/gpu/GrTest.cpp
@@ -9,6 +9,7 @@
 
 #include "GrBackendSurface.h"
 #include "GrContextOptions.h"
+#include "GrContextPriv.h"
 #include "GrDrawOpAtlas.h"
 #include "GrDrawingManager.h"
 #include "GrGpuResourceCacheAccess.h"
@@ -26,6 +27,8 @@
 #include "text/GrAtlasGlyphCache.h"
 #include "text/GrTextBlobCache.h"
 
+#include <algorithm>
+
 namespace GrTest {
 void SetupAlwaysEvictAtlas(GrContext* context) {
     // These sizes were selected because they allow each atlas to hold a single plot and will thus
@@ -436,3 +439,15 @@
     // resources in the buffer pools.
     fDrawingManager->abandon();
 }
+
+void GrContextPriv::testingOnly_flushAndRemoveOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
+    fContext->flush();
+    fContext->fDrawingManager->testingOnly_removeOnFlushCallbackObject(cb);
+}
+
+void GrDrawingManager::testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject* cb) {
+    int n = std::find(fOnFlushCBObjects.begin(), fOnFlushCBObjects.end(), cb) -
+            fOnFlushCBObjects.begin();
+    SkASSERT(n < fOnFlushCBObjects.count());
+    fOnFlushCBObjects.removeShuffle(n);
+}