Revert "Change promise image contract to for when Release and Done are called."

This reverts commit c5e8e150c86d817834b4e9ac13c3c60eedbc6f4e.

Reason for revert: Reverting to revert 9ac040700659cefff3c9a7ec6d4ada98948c307c https://skia-review.googlesource.com/c/skia/+/197163


Original change's description:
> Change promise image contract to for when Release and Done are called.
> 
> Now Release is called when all work related to the SkImage is flushed
> and Done is called when it is finished on the GPU in Vulkan. In GL they
> are still both called back-to-back after flushing.
> 
> Bug: skia:8800
> Change-Id: I990be7b9ebef8411590afd860ef40511fb5fee32
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/198165
> Commit-Queue: Brian Salomon <bsalomon@google.com>
> Reviewed-by: Robert Phillips <robertphillips@google.com>

TBR=egdaniel@google.com,bsalomon@google.com,robertphillips@google.com

Change-Id: I13e8211d89ed1b7694c2d7734eeaaf4ba9ad410a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:8800
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/198602
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/include/core/SkDeferredDisplayListRecorder.h b/include/core/SkDeferredDisplayListRecorder.h
index c044647..7516001 100644
--- a/include/core/SkDeferredDisplayListRecorder.h
+++ b/include/core/SkDeferredDisplayListRecorder.h
@@ -58,45 +58,31 @@
     using PromiseImageTextureReleaseProc = void (*)(PromiseImageTextureContext);
     using PromiseImageTextureDoneProc = void (*)(PromiseImageTextureContext);
 
-    enum class PromiseImageApiVersion { kLegacy, kNew };
-
     /**
-        Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The
-        difference is that the caller need not have created the texture nor populated it with the
-        image pixel data. Moreover, the SkImage may be created on a thread as the creation of the
-        image does not require access to the backend API or GrContext. Instead of passing a
-        GrBackendTexture the client supplies a description of the texture consisting of
-        GrBackendFormat, width, height, and GrMipMapped state. The resulting SkImage can be drawn
-        to a SkDeferredDisplayListRecorder or directly to a GPU-backed SkSurface.
+        Create a new SkImage that is very similar to an SkImage created by MakeFromTexture. The main
+        difference is that the client doesn't have the backend texture on the gpu yet but they know
+        all the properties of the texture. So instead of passing in a GrBackendTexture the client
+        supplies a GrBackendFormat, width, height, and GrMipMapped state.
 
-        When the actual texture is required to perform a backend API draw, textureFulfillProc will
-        be called to receive a GrBackendTexture. The properties of the GrBackendTexture must match
-        those set during the SkImage creation, and it must refer to a valid existing texture in the
-        backend API context/device, and be populated with the image pixel data. The texture contents
-        cannot be modified until textureReleaseProc is called. The texture cannot be deleted until
-        textureDoneProc is called.
+        When we actually send the draw calls to the GPU, we will call the textureFulfillProc and
+        the client will return a GrBackendTexture to us. The properties of the GrBackendTexture must
+        match those set during the SkImage creation, and it must have a valid backend gpu texture.
+        The gpu texture supplied by the client must stay valid until we call the textureReleaseProc.
 
         When all the following are true:
-            * the promise SkImage is deleted,
+            * the promise image is deleted,
             * any SkDeferredDisplayLists that recorded draws referencing the image are deleted,
-            * and all draws referencing the texture have been flushed (via GrContext::flush or
-              SkSurface::flush)
-        the textureReleaseProc is called. When the following additional constraint is met
-           * the texture is safe to delete in the underlying API
-        the textureDoneProc is called. For some APIs (e.g. GL) the two states are equivalent.
-        However, for others (e.g. Vulkan) they are not as it is not legal to delete a texture until
-        the GPU work referencing it has completed.
+            * and the texture is safe to delete in the underlying API with respect to drawn
+              SkDeferredDisplayLists that reference the image
+        the textureReleaseProc and then textureDoneProc are called. The texture can be deleted
+        by the client as soon as textureReleaseProc is called. There is at most one call to each of
+        textureFulfillProc, textureReleaseProc, and textureDoneProc. textureDoneProc is always
+        called even if image creation fails or if the image is never fulfilled (e.g. it is never
+        drawn). If textureFulfillProc is called then textureReleaseProc will always be called even
+        if textureFulfillProc fails.
 
-        There is at most one call to each of textureFulfillProc, textureReleaseProc, and
-        textureDoneProc. textureDoneProc is always called even if image creation fails or if the
-        image is never fulfilled (e.g. it is never drawn or all draws are clipped out). If
-        textureFulfillProc is called then textureReleaseProc will always be called even if
-        textureFulfillProc failed.
 
-        If 'version' is set to kLegacy then the textureReleaseProc call is delayed until the
-        conditions for textureDoneProc are met and then they are both called.
-
-        This call is only valid if the SkDeferredDisplayListRecorder is backed by a GPU context.
+        This call is only valid if the SkDeferredDisplayListRecorder is backed by a gpu context.
 
         @param backendFormat       format of promised gpu texture
         @param width               width of promised gpu texture
@@ -112,51 +98,42 @@
         @param colorSpace          range of colors; may be nullptr
         @param textureFulfillProc  function called to get actual gpu texture
         @param textureReleaseProc  function called when texture can be released
-        @param textureDoneProc     function called when we will no longer call textureFulfillProc
+        @param promiseDoneProc     function called when we will no longer call textureFulfillProc
         @param textureContext      state passed to textureFulfillProc and textureReleaseProc
-        @param version             controls when textureReleaseProc is called
         @return                    created SkImage, or nullptr
      */
-    sk_sp<SkImage> makePromiseTexture(
-            const GrBackendFormat& backendFormat,
-            int width,
-            int height,
-            GrMipMapped mipMapped,
-            GrSurfaceOrigin origin,
-            SkColorType colorType,
-            SkAlphaType alphaType,
-            sk_sp<SkColorSpace> colorSpace,
-            PromiseImageTextureFulfillProc textureFulfillProc,
-            PromiseImageTextureReleaseProc textureReleaseProc,
-            PromiseImageTextureDoneProc textureDoneProc,
-            PromiseImageTextureContext textureContext,
-            PromiseImageApiVersion version = PromiseImageApiVersion::kLegacy);
+    sk_sp<SkImage> makePromiseTexture(const GrBackendFormat& backendFormat,
+                                      int width,
+                                      int height,
+                                      GrMipMapped mipMapped,
+                                      GrSurfaceOrigin origin,
+                                      SkColorType colorType,
+                                      SkAlphaType alphaType,
+                                      sk_sp<SkColorSpace> colorSpace,
+                                      PromiseImageTextureFulfillProc textureFulfillProc,
+                                      PromiseImageTextureReleaseProc textureReleaseProc,
+                                      PromiseImageTextureDoneProc textureDoneProc,
+                                      PromiseImageTextureContext textureContext);
 
     /**
-        This entry point operates like 'makePromiseTexture' but it is used to construct a SkImage
-        from YUV[A] data. The source data may be planar (i.e. spread across multiple textures). In
-        the extreme Y, U, V, and A are all in different planes and thus the image is specified by
-        four textures. 'yuvaIndices' specifies the mapping from texture color channels to Y, U, V,
-        and possibly A components. It therefore indicates how many unique textures compose the full
-        image. Separate textureFulfillProc, textureReleaseProc, and textureDoneProc calls are made
-        for each texture and each texture has its own PromiseImageTextureContext. 'yuvFormats',
-        'yuvaSizes', and 'textureContexts' have one entry for each of the up to four textures, as
-        indicated by 'yuvaIndices'.
+        This entry point operates the same as 'makePromiseTexture' except that its
+        textureFulfillProc can be called up to four times to fetch the required YUVA
+        planes (passing a different textureContext to each call). So, if the 'yuvaIndices'
+        indicate that only the first two backend textures are used, 'textureFulfillProc' will
+        be called with the first two 'textureContexts'.
      */
-    sk_sp<SkImage> makeYUVAPromiseTexture(
-            SkYUVColorSpace yuvColorSpace,
-            const GrBackendFormat yuvaFormats[],
-            const SkISize yuvaSizes[],
-            const SkYUVAIndex yuvaIndices[4],
-            int imageWidth,
-            int imageHeight,
-            GrSurfaceOrigin imageOrigin,
-            sk_sp<SkColorSpace> imageColorSpace,
-            PromiseImageTextureFulfillProc textureFulfillProc,
-            PromiseImageTextureReleaseProc textureReleaseProc,
-            PromiseImageTextureDoneProc textureDoneProc,
-            PromiseImageTextureContext textureContexts[],
-            PromiseImageApiVersion version = PromiseImageApiVersion::kLegacy);
+    sk_sp<SkImage> makeYUVAPromiseTexture(SkYUVColorSpace yuvColorSpace,
+                                          const GrBackendFormat yuvaFormats[],
+                                          const SkISize yuvaSizes[],
+                                          const SkYUVAIndex yuvaIndices[4],
+                                          int imageWidth,
+                                          int imageHeight,
+                                          GrSurfaceOrigin imageOrigin,
+                                          sk_sp<SkColorSpace> imageColorSpace,
+                                          PromiseImageTextureFulfillProc textureFulfillProc,
+                                          PromiseImageTextureReleaseProc textureReleaseProc,
+                                          PromiseImageTextureDoneProc textureDoneProc,
+                                          PromiseImageTextureContext textureContexts[]);
 
 private:
     bool init();
diff --git a/include/core/SkYUVAIndex.h b/include/core/SkYUVAIndex.h
index b9bc396..f52786c 100644
--- a/include/core/SkYUVAIndex.h
+++ b/include/core/SkYUVAIndex.h
@@ -49,7 +49,7 @@
     };
     static constexpr int kIndexCount = kLast_Index + 1;
 
-    /** The index is a number between -1..3 which defines which image source to read from, where -1
+    /** The index is a number between -1..3 which definies which image source to read from, where -1
      * means the image source doesn't exist. The assumption is we will always have image sources for
      * each of YUV planes, but optionally have image source for A plane. */
     int            fIndex;
diff --git a/src/core/SkDeferredDisplayListRecorder.cpp b/src/core/SkDeferredDisplayListRecorder.cpp
index e81dbba..8063349 100644
--- a/src/core/SkDeferredDisplayListRecorder.cpp
+++ b/src/core/SkDeferredDisplayListRecorder.cpp
@@ -34,8 +34,7 @@
         PromiseImageTextureFulfillProc textureFulfillProc,
         PromiseImageTextureReleaseProc textureReleaseProc,
         PromiseImageTextureDoneProc textureDoneProc,
-        PromiseImageTextureContext textureContext,
-        PromiseImageApiVersion) {
+        PromiseImageTextureContext textureContext) {
     return nullptr;
 }
 
@@ -51,8 +50,7 @@
         PromiseImageTextureFulfillProc textureFulfillProc,
         PromiseImageTextureReleaseProc textureReleaseProc,
         PromiseImageTextureDoneProc textureDoneProc,
-        PromiseImageTextureContext textureContexts[],
-        PromiseImageApiVersion) {
+        PromiseImageTextureContext textureContexts[]) {
     return nullptr;
 }
 
@@ -235,8 +233,7 @@
         PromiseImageTextureFulfillProc textureFulfillProc,
         PromiseImageTextureReleaseProc textureReleaseProc,
         PromiseImageTextureDoneProc textureDoneProc,
-        PromiseImageTextureContext textureContext,
-        PromiseImageApiVersion version) {
+        PromiseImageTextureContext textureContext) {
     if (!fContext) {
         return nullptr;
     }
@@ -253,8 +250,7 @@
                                            textureFulfillProc,
                                            textureReleaseProc,
                                            textureDoneProc,
-                                           textureContext,
-                                           version);
+                                           textureContext);
 }
 
 sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
@@ -269,8 +265,7 @@
         PromiseImageTextureFulfillProc textureFulfillProc,
         PromiseImageTextureReleaseProc textureReleaseProc,
         PromiseImageTextureDoneProc textureDoneProc,
-        PromiseImageTextureContext textureContexts[],
-        PromiseImageApiVersion version) {
+        PromiseImageTextureContext textureContexts[]) {
     if (!fContext) {
         return nullptr;
     }
@@ -287,8 +282,7 @@
                                                    textureFulfillProc,
                                                    textureReleaseProc,
                                                    textureDoneProc,
-                                                   textureContexts,
-                                                   version);
+                                                   textureContexts);
 }
 
 #endif
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index 4fec2ea..33f77cf 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -405,8 +405,7 @@
                                                PromiseImageTextureFulfillProc textureFulfillProc,
                                                PromiseImageTextureReleaseProc textureReleaseProc,
                                                PromiseImageTextureDoneProc textureDoneProc,
-                                               PromiseImageTextureContext textureContext,
-                                               PromiseImageApiVersion version) {
+                                               PromiseImageTextureContext textureContext) {
     // The contract here is that if 'promiseDoneProc' is passed in it should always be called,
     // even if creation of the SkImage fails. Once we call MakePromiseImageLazyProxy it takes
     // responsibility for calling the done proc.
@@ -437,7 +436,7 @@
     callDone.clear();
     auto proxy = MakePromiseImageLazyProxy(context, width, height, origin, config, backendFormat,
                                            mipMapped, textureFulfillProc, textureReleaseProc,
-                                           textureDoneProc, textureContext, version);
+                                           textureDoneProc, textureContext);
     if (!proxy) {
         return nullptr;
     }
diff --git a/src/image/SkImage_Gpu.h b/src/image/SkImage_Gpu.h
index 39ba49e..e05ec6c 100644
--- a/src/image/SkImage_Gpu.h
+++ b/src/image/SkImage_Gpu.h
@@ -55,8 +55,7 @@
                                              PromiseImageTextureFulfillProc textureFulfillProc,
                                              PromiseImageTextureReleaseProc textureReleaseProc,
                                              PromiseImageTextureDoneProc textureDoneProc,
-                                             PromiseImageTextureContext textureContext,
-                                             PromiseImageApiVersion);
+                                             PromiseImageTextureContext textureContext);
 
     static sk_sp<SkImage> ConvertYUVATexturesToRGB(GrContext*, SkYUVColorSpace yuvColorSpace,
                                                    const GrBackendTexture yuvaTextures[],
diff --git a/src/image/SkImage_GpuBase.cpp b/src/image/SkImage_GpuBase.cpp
index 8d64cd0..2618dd4 100644
--- a/src/image/SkImage_GpuBase.cpp
+++ b/src/image/SkImage_GpuBase.cpp
@@ -386,8 +386,7 @@
         PromiseImageTextureFulfillProc fulfillProc,
         PromiseImageTextureReleaseProc releaseProc,
         PromiseImageTextureDoneProc doneProc,
-        PromiseImageTextureContext textureContext,
-        PromiseImageApiVersion version) {
+        PromiseImageTextureContext textureContext) {
     SkASSERT(context);
     SkASSERT(width > 0 && height > 0);
     SkASSERT(doneProc);
@@ -426,12 +425,8 @@
                                        PromiseImageTextureReleaseProc releaseProc,
                                        PromiseImageTextureDoneProc doneProc,
                                        PromiseImageTextureContext context,
-                                       GrPixelConfig config,
-                                       PromiseImageApiVersion version)
-                : fFulfillProc(fulfillProc)
-                , fReleaseProc(releaseProc)
-                , fConfig(config)
-                , fVersion(version) {
+                                       GrPixelConfig config)
+                : fFulfillProc(fulfillProc), fReleaseProc(releaseProc), fConfig(config) {
             fDoneCallback = sk_make_sp<GrRefCntedCallback>(doneProc, context);
         }
         PromiseLazyInstantiateCallback(PromiseLazyInstantiateCallback&&) = default;
@@ -485,10 +480,7 @@
                     return sk_sp<GrTexture>();
                 }
             }
-            auto releaseIdleState = fVersion == PromiseImageApiVersion::kLegacy
-                                            ? GrTexture::IdleState::kFinished
-                                            : GrTexture::IdleState::kFlushed;
-            tex->addIdleProc(std::move(releaseCallback), releaseIdleState);
+            tex->addIdleProc(std::move(releaseCallback), GrTexture::IdleState::kFinished);
             tex->addIdleProc(std::move(fDoneCallback), GrTexture::IdleState::kFinished);
             promiseTexture->addKeyToInvalidate(tex->getContext()->priv().contextID(), key);
             return std::move(tex);
@@ -499,8 +491,7 @@
         PromiseImageTextureReleaseProc fReleaseProc;
         sk_sp<GrRefCntedCallback> fDoneCallback;
         GrPixelConfig fConfig;
-        PromiseImageApiVersion fVersion;
-    } callback(fulfillProc, releaseProc, doneProc, textureContext, config, version);
+    } callback(fulfillProc, releaseProc, doneProc, textureContext, config);
 
     GrProxyProvider* proxyProvider = context->priv().proxyProvider();
 
diff --git a/src/image/SkImage_GpuBase.h b/src/image/SkImage_GpuBase.h
index ad5fc1d..0058711 100644
--- a/src/image/SkImage_GpuBase.h
+++ b/src/image/SkImage_GpuBase.h
@@ -78,7 +78,6 @@
     using PromiseImageTextureDoneProc = SkDeferredDisplayListRecorder::PromiseImageTextureDoneProc;
 
 protected:
-    using PromiseImageApiVersion = SkDeferredDisplayListRecorder::PromiseImageApiVersion;
     // Helper for making a lazy proxy for a promise image. The PromiseDoneProc we be called,
     // if not null, immediately if this function fails. Othwerwise, it is installed in the
     // proxy along with the TextureFulfillProc and TextureReleaseProc. PromiseDoneProc must not
@@ -86,7 +85,7 @@
     static sk_sp<GrTextureProxy> MakePromiseImageLazyProxy(
             GrContext*, int width, int height, GrSurfaceOrigin, GrPixelConfig, GrBackendFormat,
             GrMipMapped, PromiseImageTextureFulfillProc, PromiseImageTextureReleaseProc,
-            PromiseImageTextureDoneProc, PromiseImageTextureContext, PromiseImageApiVersion);
+            PromiseImageTextureDoneProc, PromiseImageTextureContext);
 
     static bool RenderYUVAToRGBA(GrContext* ctx, GrRenderTargetContext* renderTargetContext,
                                  const SkRect& rect, SkYUVColorSpace yuvColorSpace,
diff --git a/src/image/SkImage_GpuYUVA.cpp b/src/image/SkImage_GpuYUVA.cpp
index ffa801c..fe3eb92 100644
--- a/src/image/SkImage_GpuYUVA.cpp
+++ b/src/image/SkImage_GpuYUVA.cpp
@@ -282,8 +282,7 @@
         PromiseImageTextureFulfillProc textureFulfillProc,
         PromiseImageTextureReleaseProc textureReleaseProc,
         PromiseImageTextureDoneProc promiseDoneProc,
-        PromiseImageTextureContext textureContexts[],
-        PromiseImageApiVersion version) {
+        PromiseImageTextureContext textureContexts[]) {
     int numTextures;
     bool valid = SkYUVAIndex::AreValidIndices(yuvaIndices, &numTextures);
 
@@ -343,7 +342,7 @@
         proxies[texIdx] = MakePromiseImageLazyProxy(
                 context, yuvaSizes[texIdx].width(), yuvaSizes[texIdx].height(), imageOrigin, config,
                 yuvaFormats[texIdx], GrMipMapped::kNo, textureFulfillProc, textureReleaseProc,
-                promiseDoneProc, textureContexts[texIdx], version);
+                promiseDoneProc, textureContexts[texIdx]);
         ++proxiesCreated;
         if (!proxies[texIdx]) {
             return nullptr;
diff --git a/src/image/SkImage_GpuYUVA.h b/src/image/SkImage_GpuYUVA.h
index 4f01735..33bea53 100644
--- a/src/image/SkImage_GpuYUVA.h
+++ b/src/image/SkImage_GpuYUVA.h
@@ -73,8 +73,7 @@
                                                  PromiseImageTextureFulfillProc textureFulfillProc,
                                                  PromiseImageTextureReleaseProc textureReleaseProc,
                                                  PromiseImageTextureDoneProc textureDoneProc,
-                                                 PromiseImageTextureContext textureContexts[],
-                                                 PromiseImageApiVersion);
+                                                 PromiseImageTextureContext textureContexts[]);
 
 private:
     SkImage_GpuYUVA(const SkImage_GpuYUVA* image, sk_sp<SkColorSpace>);
diff --git a/tests/DeferredDisplayListTest.cpp b/tests/DeferredDisplayListTest.cpp
index c7584f6..8adc90b 100644
--- a/tests/DeferredDisplayListTest.cpp
+++ b/tests/DeferredDisplayListTest.cpp
@@ -675,8 +675,7 @@
                 dummy_fulfill_proc,
                 dummy_release_proc,
                 dummy_done_proc,
-                nullptr,
-                SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
+                nullptr);
         REPORTER_ASSERT(reporter, !image);
     }
 
@@ -780,8 +779,7 @@
                     dummy_fulfill_proc,
                     dummy_release_proc,
                     dummy_done_proc,
-                    nullptr,
-                    SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
+                    nullptr);
             if (GR_GL_TEXTURE_2D != target && mipMapped == GrMipMapped::kYes) {
                 REPORTER_ASSERT(reporter, !image);
                 continue;
diff --git a/tests/PromiseImageTest.cpp b/tests/PromiseImageTest.cpp
index 40b68ed..93a09ca 100644
--- a/tests/PromiseImageTest.cpp
+++ b/tests/PromiseImageTest.cpp
@@ -63,100 +63,66 @@
     }
 };
 
-enum class ReleaseBalanceExpectation {
+enum class ReleaseBalanceExpecation {
     kBalanced,
-    kAllUnbalanced,
-    kUnbalancedByOne,
+    kBalancedOrPlusOne,
+    kAny
 };
 
-enum class DoneBalanceExpectation {
-    kBalanced,
-    kAllUnbalanced,
-    kUnknown,
-    kUnbalancedByOne,
-    kBalancedOrOffByOne,
-};
-
-static void check_fulfill_and_release_cnts(skiatest::Reporter* reporter,
-                                           const PromiseTextureChecker& promiseChecker,
+static bool check_fulfill_and_release_cnts(const PromiseTextureChecker& promiseChecker,
+                                           ReleaseBalanceExpecation balanceExpecation,
                                            int expectedFulfillCnt,
-                                           ReleaseBalanceExpectation releaseBalanceExpecation,
-                                           DoneBalanceExpectation doneBalanceExpecation) {
-    REPORTER_ASSERT(reporter, promiseChecker.fFulfillCount == expectedFulfillCnt);
-    if (!expectedFulfillCnt) {
-        // Release and Done should only ever be called after Fulfill.
-        REPORTER_ASSERT(reporter, !promiseChecker.fReleaseCount);
-        REPORTER_ASSERT(reporter, !promiseChecker.fDoneCount);
-        return;
+                                           int expectedReleaseCnt,
+                                           bool expectedRequired,
+                                           int expectedDoneCnt,
+                                           skiatest::Reporter* reporter) {
+    bool result = true;
+    int countDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
+    // FulfillCount should always equal ReleaseCount or be at most one higher
+    if (countDiff != 0) {
+        if (balanceExpecation == ReleaseBalanceExpecation::kBalanced) {
+            result = false;
+            REPORTER_ASSERT(reporter, 0 == countDiff);
+        } else if (countDiff != 1 &&
+                   balanceExpecation == ReleaseBalanceExpecation::kBalancedOrPlusOne) {
+            result = false;
+            REPORTER_ASSERT(reporter, 0 == countDiff || 1 == countDiff);
+        } else if (countDiff < 0) {
+            result = false;
+            REPORTER_ASSERT(reporter, countDiff >= 0);
+        }
     }
-    int releaseDiff = promiseChecker.fFulfillCount - promiseChecker.fReleaseCount;
-    switch (releaseBalanceExpecation) {
-        case ReleaseBalanceExpectation::kBalanced:
-            REPORTER_ASSERT(reporter, !releaseDiff);
-            break;
-        case ReleaseBalanceExpectation::kAllUnbalanced:
-            REPORTER_ASSERT(reporter, releaseDiff == promiseChecker.fFulfillCount);
-            break;
-        case ReleaseBalanceExpectation::kUnbalancedByOne:
-            REPORTER_ASSERT(reporter, releaseDiff == 1);
-            break;
+
+    int fulfillDiff = expectedFulfillCnt - promiseChecker.fFulfillCount;
+    REPORTER_ASSERT(reporter, fulfillDiff >= 0);
+    if (fulfillDiff != 0) {
+        if (expectedRequired) {
+            result = false;
+            REPORTER_ASSERT(reporter, expectedFulfillCnt == promiseChecker.fFulfillCount);
+        } else if (fulfillDiff > 1) {
+            result = false;
+            REPORTER_ASSERT(reporter, fulfillDiff <= 1);
+        }
     }
-    int doneDiff = promiseChecker.fFulfillCount - promiseChecker.fDoneCount;
-    switch (doneBalanceExpecation) {
-        case DoneBalanceExpectation::kBalanced:
-            REPORTER_ASSERT(reporter, !doneDiff);
-            break;
-        case DoneBalanceExpectation::kAllUnbalanced:
-            REPORTER_ASSERT(reporter, doneDiff == promiseChecker.fFulfillCount);
-            break;
-        case DoneBalanceExpectation::kUnknown:
-            REPORTER_ASSERT(reporter, doneDiff >= 0 && doneDiff <= promiseChecker.fFulfillCount);
-            break;
-        case DoneBalanceExpectation::kUnbalancedByOne:
-            REPORTER_ASSERT(reporter, doneDiff == 1);
-            break;
-        case DoneBalanceExpectation::kBalancedOrOffByOne:
-            REPORTER_ASSERT(reporter, doneDiff == 0 || doneDiff == 1);
-            break;
+
+    int releaseDiff = expectedReleaseCnt - promiseChecker.fReleaseCount;
+    REPORTER_ASSERT(reporter, releaseDiff >= 0);
+    if (releaseDiff != 0) {
+        if (expectedRequired) {
+            result = false;
+            REPORTER_ASSERT(reporter, expectedReleaseCnt == promiseChecker.fReleaseCount);
+        } else if (releaseDiff > 1) {
+            result = false;
+            REPORTER_ASSERT(reporter, releaseDiff <= 1);
+        }
     }
-}
 
-static void check_unfulfilled(const PromiseTextureChecker& promiseChecker,
-                              skiatest::Reporter* reporter) {
-    check_fulfill_and_release_cnts(reporter, promiseChecker, 0,
-                                   ReleaseBalanceExpectation::kBalanced,
-                                   DoneBalanceExpectation::kBalanced);
-}
-
-static void check_only_fulfilled(skiatest::Reporter* reporter,
-                                 const PromiseTextureChecker& promiseChecker,
-                                 int expectedFulfillCnt = 1) {
-    check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
-                                   ReleaseBalanceExpectation::kAllUnbalanced,
-                                   DoneBalanceExpectation::kAllUnbalanced);
-}
-
-static void check_all_flushed_but_not_synced(skiatest::Reporter* reporter,
-                                             const PromiseTextureChecker& promiseChecker,
-                                             GrBackendApi api,
-                                             int expectedFulfillCnt = 1) {
-    DoneBalanceExpectation doneBalanceExpectation = DoneBalanceExpectation::kBalanced;
-    // On Vulkan Done isn't guaranteed to be called until a sync has occurred.
-    if (api == GrBackendApi::kVulkan) {
-        doneBalanceExpectation = expectedFulfillCnt == 1
-                                         ? DoneBalanceExpectation::kBalancedOrOffByOne
-                                         : DoneBalanceExpectation::kUnknown;
+    if (expectedDoneCnt != promiseChecker.fDoneCount) {
+        result = false;
+        REPORTER_ASSERT(reporter, expectedDoneCnt == promiseChecker.fDoneCount);
     }
-    check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
-                                   ReleaseBalanceExpectation::kBalanced, doneBalanceExpectation);
-}
 
-static void check_all_done(skiatest::Reporter* reporter,
-                           const PromiseTextureChecker& promiseChecker,
-                           int expectedFulfillCnt = 1) {
-    check_fulfill_and_release_cnts(reporter, promiseChecker, expectedFulfillCnt,
-                                   ReleaseBalanceExpectation::kBalanced,
-                                   DoneBalanceExpectation::kBalanced);
+    return result;
 }
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(PromiseImageTest, reporter, ctxInfo) {
@@ -184,22 +150,47 @@
                     PromiseTextureChecker::Fulfill,
                     PromiseTextureChecker::Release,
                     PromiseTextureChecker::Done,
-                    &promiseChecker,
-                    SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
+                    &promiseChecker));
 
     SkImageInfo info = SkImageInfo::MakeN32Premul(kWidth, kHeight);
     sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(ctx, SkBudgeted::kNo, info);
     SkCanvas* canvas = surface->getCanvas();
 
-    canvas->drawImage(refImg, 0, 0);
-    check_unfulfilled(promiseChecker, reporter);
+    int expectedFulfillCnt = 0;
+    int expectedReleaseCnt = 0;
+    int expectedDoneCnt = 0;
+    ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kBalanced;
 
+    canvas->drawImage(refImg, 0, 0);
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             true,
+                                                             expectedDoneCnt,
+                                                             reporter));
+
+    bool isVulkan = GrBackendApi::kVulkan == ctx->backend();
     surface->flush();
-    // We still own the image so we should not have called Release or Done.
-    check_only_fulfilled(reporter, promiseChecker);
+    expectedFulfillCnt++;
+    // Because we've delayed release, we expect a +1 balance.
+    balanceExpecation = ReleaseBalanceExpecation::kBalancedOrPlusOne;
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             !isVulkan,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     gpu->testingOnly_flushGpuAndSync();
-    check_only_fulfilled(reporter, promiseChecker);
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             true,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     canvas->drawImage(refImg, 0, 0);
     canvas->drawImage(refImg, 0, 0);
@@ -207,25 +198,49 @@
     surface->flush();
 
     gpu->testingOnly_flushGpuAndSync();
-    // Image should still be fulfilled from the first time we drew/flushed it.
-    check_only_fulfilled(reporter, promiseChecker);
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             true,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     canvas->drawImage(refImg, 0, 0);
     surface->flush();
-    check_only_fulfilled(reporter, promiseChecker);
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             !isVulkan,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     canvas->drawImage(refImg, 0, 0);
+
     refImg.reset();
-    // We no longer own the image but the last draw is still unflushed.
-    check_only_fulfilled(reporter, promiseChecker);
+
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             !isVulkan,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     surface->flush();
-    // Flushing should have called Release. Depending on the backend and timing it may have called
-    // done.
-    check_all_flushed_but_not_synced(reporter, promiseChecker, ctx->backend());
     gpu->testingOnly_flushGpuAndSync();
-    // Now Done should definitely have been called.
-    check_all_done(reporter, promiseChecker);
+    // We released the image already and we flushed and synced.
+    balanceExpecation = ReleaseBalanceExpecation::kBalanced;
+    expectedReleaseCnt++;
+    expectedDoneCnt++;
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             !isVulkan,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     gpu->deleteTestingOnlyBackendTexture(backendTex);
 }
@@ -265,23 +280,32 @@
             ctx, backendTex1.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
             kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
             PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
-            PromiseTextureChecker::Done, &promiseChecker,
-            SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
+            PromiseTextureChecker::Done, &promiseChecker));
     REPORTER_ASSERT(reporter, alphaImg);
 
     sk_sp<SkImage> grayImg(SkImage_Gpu::MakePromiseTexture(
             ctx, backendTex1.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
             kBottomLeft_GrSurfaceOrigin, kGray_8_SkColorType, kOpaque_SkAlphaType, nullptr,
             PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
-            PromiseTextureChecker::Done, &promiseChecker,
-            SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
+            PromiseTextureChecker::Done, &promiseChecker));
     REPORTER_ASSERT(reporter, grayImg);
 
     canvas->drawImage(alphaImg, 0, 0);
     canvas->drawImage(grayImg, 1, 1);
     surface->flush();
     gpu->testingOnly_flushGpuAndSync();
-    check_only_fulfilled(reporter, promiseChecker, 2);
+
+    int expectedFulfillCnt = 2;
+    int expectedReleaseCnt = 0;
+    int expectedDoneCnt = 0;
+    ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kAny;
+    REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                             balanceExpecation,
+                                                             expectedFulfillCnt,
+                                                             expectedReleaseCnt,
+                                                             true,
+                                                             expectedDoneCnt,
+                                                             reporter));
 
     // Because they use different configs, each image should have created a different GrTexture
     // and they both should still be cached.
@@ -299,7 +323,7 @@
         }
     }
 
-    // Invalidate the backing texture, this should invalidate the keys.
+    // Change the backing texture, this should invalidate the keys.
     promiseChecker.releaseTexture();
     ctx->priv().getResourceCache()->purgeAsNeeded();
 
@@ -307,12 +331,6 @@
         auto surf = ctx->priv().resourceProvider()->findByUniqueKey<GrSurface>(key);
         REPORTER_ASSERT(reporter, !surf);
     }
-    alphaImg.reset();
-    check_fulfill_and_release_cnts(reporter, promiseChecker, 2,
-                                   ReleaseBalanceExpectation::kUnbalancedByOne,
-                                   DoneBalanceExpectation::kUnbalancedByOne);
-    grayImg.reset();
-    check_all_done(reporter, promiseChecker, 2);
     gpu->deleteTestingOnlyBackendTexture(backendTex1);
 }
 
@@ -364,8 +382,7 @@
                     ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
                     kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
                     PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
-                    PromiseTextureChecker::Done, &promiseChecker,
-                    SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
+                    PromiseTextureChecker::Done, &promiseChecker));
             REPORTER_ASSERT(reporter, image);
 
             canvas->drawImage(image, 0, 0);
@@ -377,7 +394,17 @@
             ctx->flush();
             contextDeath(&factory, ctx);
 
-            check_all_done(reporter, promiseChecker);
+            int expectedFulfillCnt = 1;
+            int expectedReleaseCnt = 1;
+            int expectedDoneCnt = 1;
+            ReleaseBalanceExpecation balanceExpecation = ReleaseBalanceExpecation::kBalanced;
+            REPORTER_ASSERT(reporter, check_fulfill_and_release_cnts(promiseChecker,
+                                                                     balanceExpecation,
+                                                                     expectedFulfillCnt,
+                                                                     expectedReleaseCnt,
+                                                                     true,
+                                                                     expectedDoneCnt,
+                                                                     reporter));
         }
     }
 }
@@ -403,8 +430,7 @@
             ctx, backendTex.getBackendFormat(), kWidth, kHeight, GrMipMapped::kNo,
             kTopLeft_GrSurfaceOrigin, kAlpha_8_SkColorType, kPremul_SkAlphaType, nullptr,
             PromiseTextureChecker::Fulfill, PromiseTextureChecker::Release,
-            PromiseTextureChecker::Done, &promiseChecker,
-            SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew));
+            PromiseTextureChecker::Done, &promiseChecker));
     REPORTER_ASSERT(reporter, image);
 
     // Make the cache full. This tests that we don't preemptively purge cached textures for
diff --git a/tools/DDLPromiseImageHelper.cpp b/tools/DDLPromiseImageHelper.cpp
index 5e56952..bb922c4 100644
--- a/tools/DDLPromiseImageHelper.cpp
+++ b/tools/DDLPromiseImageHelper.cpp
@@ -202,20 +202,18 @@
             sizes[i] = SkISize::MakeEmpty();
         }
 
-        image = recorder->makeYUVAPromiseTexture(
-                curImage.yuvColorSpace(),
-                backendFormats,
-                sizes,
-                curImage.yuvaIndices(),
-                curImage.overallWidth(),
-                curImage.overallHeight(),
-                GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
-                curImage.refOverallColorSpace(),
-                DDLPromiseImageHelper::PromiseImageFulfillProc,
-                DDLPromiseImageHelper::PromiseImageReleaseProc,
-                DDLPromiseImageHelper::PromiseImageDoneProc,
-                contexts,
-                SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
+        image = recorder->makeYUVAPromiseTexture(curImage.yuvColorSpace(),
+                                                 backendFormats,
+                                                 sizes,
+                                                 curImage.yuvaIndices(),
+                                                 curImage.overallWidth(),
+                                                 curImage.overallHeight(),
+                                                 GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
+                                                 curImage.refOverallColorSpace(),
+                                                 DDLPromiseImageHelper::PromiseImageFulfillProc,
+                                                 DDLPromiseImageHelper::PromiseImageReleaseProc,
+                                                 DDLPromiseImageHelper::PromiseImageDoneProc,
+                                                 contexts);
         for (int i = 0; i < textureCount; ++i) {
             curImage.callbackContext(i)->wasAddedToImage();
         }
@@ -237,20 +235,18 @@
         // Each DDL recorder gets its own ref on the promise callback context for the
         // promise images it creates.
         // DDL TODO: sort out mipmapping
-        image = recorder->makePromiseTexture(
-                backendFormat,
-                curImage.overallWidth(),
-                curImage.overallHeight(),
-                GrMipMapped::kNo,
-                GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
-                curImage.overallColorType(),
-                curImage.overallAlphaType(),
-                curImage.refOverallColorSpace(),
-                DDLPromiseImageHelper::PromiseImageFulfillProc,
-                DDLPromiseImageHelper::PromiseImageReleaseProc,
-                DDLPromiseImageHelper::PromiseImageDoneProc,
-                (void*)curImage.refCallbackContext(0).release(),
-                SkDeferredDisplayListRecorder::PromiseImageApiVersion::kNew);
+        image = recorder->makePromiseTexture(backendFormat,
+                                             curImage.overallWidth(),
+                                             curImage.overallHeight(),
+                                             GrMipMapped::kNo,
+                                             GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin,
+                                             curImage.overallColorType(),
+                                             curImage.overallAlphaType(),
+                                             curImage.refOverallColorSpace(),
+                                             DDLPromiseImageHelper::PromiseImageFulfillProc,
+                                             DDLPromiseImageHelper::PromiseImageReleaseProc,
+                                             DDLPromiseImageHelper::PromiseImageDoneProc,
+                                             (void*)curImage.refCallbackContext(0).release());
         curImage.callbackContext(0)->wasAddedToImage();
     }
     perRecorderContext->fPromiseImages->push_back(image);