Defer stencil attachment until opsTask execution

Change-Id: I34cc35d16966d35e26561c40a0300112b2da2fa1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/253546
Reviewed-by: Robert Phillips <robertphillips@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrOpsTask.cpp b/src/gpu/GrOpsTask.cpp
index 62a94cd..06d3733 100644
--- a/src/gpu/GrOpsTask.cpp
+++ b/src/gpu/GrOpsTask.cpp
@@ -484,9 +484,9 @@
         return false;
     }
 
-    GrSurfaceProxy* proxy = fTargetView.proxy();
+    SkASSERT(fTargetView.proxy());
+    GrRenderTargetProxy* proxy = fTargetView.proxy()->asRenderTargetProxy();
     SkASSERT(proxy);
-    SkASSERT(proxy->peekRenderTarget());
     TRACE_EVENT0("skia.gpu", TRACE_FUNC);
 
     // Make sure load ops are not kClear if the GPU needs to use draws for clears
@@ -496,7 +496,18 @@
     const GrCaps& caps = *flushState->gpu()->caps();
     GrRenderTarget* renderTarget = proxy->peekRenderTarget();
     SkASSERT(renderTarget);
-    GrStencilAttachment* stencil = renderTarget->renderTargetPriv().getStencilAttachment();
+
+    GrStencilAttachment* stencil = nullptr;
+    if (int numStencilSamples = proxy->numStencilSamples()) {
+        if (!flushState->resourceProvider()->attachStencilAttachment(
+                renderTarget, numStencilSamples)) {
+            SkDebugf("WARNING: failed to attach a stencil buffer. Rendering will be skipped.\n");
+            return false;
+        }
+        stencil = renderTarget->renderTargetPriv().getStencilAttachment();
+    }
+
+    SkASSERT(!stencil || stencil->numSamples() >= proxy->numStencilSamples());
 
     GrLoadOp stencilLoadOp;
     switch (fInitialStencilContent) {
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index fa7f669..8268269 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -83,8 +83,8 @@
     if (this->isLazy()) {
         return false;
     }
-    if (!this->instantiateImpl(resourceProvider, fSampleCnt, fNumStencilSamples, GrRenderable::kYes,
-                               GrMipMapped::kNo, nullptr)) {
+    if (!this->instantiateImpl(resourceProvider, fSampleCnt, GrRenderable::kYes, GrMipMapped::kNo,
+                               nullptr)) {
         return false;
     }
 
@@ -103,8 +103,8 @@
 }
 
 sk_sp<GrSurface> GrRenderTargetProxy::createSurface(GrResourceProvider* resourceProvider) const {
-    sk_sp<GrSurface> surface = this->createSurfaceImpl(
-            resourceProvider, fSampleCnt, fNumStencilSamples, GrRenderable::kYes, GrMipMapped::kNo);
+    sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, fSampleCnt,
+                                                       GrRenderable::kYes, GrMipMapped::kNo);
     if (!surface) {
         return nullptr;
     }
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index 4699893..b1a5a8b 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -262,21 +262,6 @@
         return false;
     }
 
-    int minStencilSampleCount = (proxy->asRenderTargetProxy())
-            ? proxy->asRenderTargetProxy()->numStencilSamples()
-            : 0;
-
-    if (minStencilSampleCount) {
-        GrRenderTarget* rt = proxy->peekRenderTarget();
-        SkASSERT(rt);
-
-        GrStencilAttachment* stencil = rt->renderTargetPriv().getStencilAttachment();
-        if (!stencil) {
-            return false;
-        }
-        SkASSERT(stencil->numSamples() >= minStencilSampleCount);
-    }
-
     GrSurface* surface = proxy->peekSurface();
     if (surface->wasDestroyed()) {
         return false;
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 576dfc4..110e38b 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -76,19 +76,6 @@
     SkASSERT(!fAssigned);  // We shouldn't be adding any intervals after (or during) assignment
 
     if (proxy->canSkipResourceAllocator()) {
-        // If the proxy is still not instantiated at this point but will need stencil, it will
-        // attach its own stencil buffer upon onFlush instantiation.
-        if (proxy->isInstantiated()) {
-            auto rt = proxy->asRenderTargetProxy();
-            int minStencilSampleCount = rt ? rt->numStencilSamples() : 0;
-            if (minStencilSampleCount) {
-                if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
-                        fResourceProvider, proxy->peekSurface(), minStencilSampleCount)) {
-                    SkDebugf("WARNING: failed to attach stencil buffer. "
-                             "Rendering may be incorrect.\n");
-                }
-            }
-        }
         return;
     }
 
@@ -265,19 +252,11 @@
 
 // First try to reuse one of the recently allocated/used GrSurfaces in the free pool.
 // If we can't find a useable one, create a new one.
-sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(const GrSurfaceProxy* proxy,
-                                                     int minStencilSampleCount) {
-
+sk_sp<GrSurface> GrResourceAllocator::findSurfaceFor(const GrSurfaceProxy* proxy) {
     if (proxy->asTextureProxy() && proxy->asTextureProxy()->getUniqueKey().isValid()) {
         // First try to reattach to a cached version if the proxy is uniquely keyed
-        sk_sp<GrSurface> surface = fResourceProvider->findByUniqueKey<GrSurface>(
-                                                        proxy->asTextureProxy()->getUniqueKey());
-        if (surface) {
-            if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(fResourceProvider, surface.get(),
-                                                           minStencilSampleCount)) {
-                return nullptr;
-            }
-
+        if (sk_sp<GrSurface> surface = fResourceProvider->findByUniqueKey<GrSurface>(
+                proxy->asTextureProxy()->getUniqueKey())) {
             return surface;
         }
     }
@@ -298,11 +277,6 @@
             // match budgeted proxies w/ budgeted surfaces and unbudgeted w/ unbudgeted.
             surface->resourcePriv().makeBudgeted();
         }
-
-        if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(fResourceProvider, surface.get(),
-                                                       minStencilSampleCount)) {
-            return nullptr;
-        }
         SkASSERT(!surface->getUniqueKey().isValid());
         return surface;
     }
@@ -405,16 +379,7 @@
 
         this->expire(cur->start());
 
-        int minStencilSampleCount = (cur->proxy()->asRenderTargetProxy())
-                ? cur->proxy()->asRenderTargetProxy()->numStencilSamples()
-                : 0;
-
         if (cur->proxy()->isInstantiated()) {
-            if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
-                        fResourceProvider, cur->proxy()->peekSurface(), minStencilSampleCount)) {
-                *outError = AssignError::kFailedProxyInstantiation;
-            }
-
             fActiveIntvls.insertByIncreasingEnd(cur);
 
             if (fResourceProvider->overBudget()) {
@@ -432,8 +397,7 @@
             if (!cur->proxy()->priv().doLazyInstantiation(fResourceProvider)) {
                 *outError = AssignError::kFailedProxyInstantiation;
             }
-        } else if (sk_sp<GrSurface> surface =
-                           this->findSurfaceFor(cur->proxy(), minStencilSampleCount)) {
+        } else if (sk_sp<GrSurface> surface = this->findSurfaceFor(cur->proxy())) {
             // TODO: make getUniqueKey virtual on GrSurfaceProxy
             GrTextureProxy* texProxy = cur->proxy()->asTextureProxy();
 
diff --git a/src/gpu/GrResourceAllocator.h b/src/gpu/GrResourceAllocator.h
index 6108b54..da3c735 100644
--- a/src/gpu/GrResourceAllocator.h
+++ b/src/gpu/GrResourceAllocator.h
@@ -121,7 +121,7 @@
 
     // These two methods wrap the interactions with the free pool
     void recycleSurface(sk_sp<GrSurface> surface);
-    sk_sp<GrSurface> findSurfaceFor(const GrSurfaceProxy* proxy, int minStencilSampleCount);
+    sk_sp<GrSurface> findSurfaceFor(const GrSurfaceProxy* proxy);
 
     struct FreePoolTraits {
         static const GrScratchKey& GetKey(const GrSurface& s) {
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 80f6cd8..310b91f 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -129,26 +129,8 @@
     SkASSERT(!fLastRenderTask);
 }
 
-bool GrSurfaceProxyPriv::AttachStencilIfNeeded(GrResourceProvider* resourceProvider,
-                                               GrSurface* surface, int minStencilSampleCount) {
-    if (minStencilSampleCount) {
-        GrRenderTarget* rt = surface->asRenderTarget();
-        if (!rt) {
-            SkASSERT(0);
-            return false;
-        }
-
-        if (!resourceProvider->attachStencilAttachment(rt, minStencilSampleCount)) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
 sk_sp<GrSurface> GrSurfaceProxy::createSurfaceImpl(GrResourceProvider* resourceProvider,
                                                    int sampleCnt,
-                                                   int minStencilSampleCount,
                                                    GrRenderable renderable,
                                                    GrMipMapped mipMapped) const {
     SkASSERT(mipMapped == GrMipMapped::kNo || fFit == SkBackingFit::kExact);
@@ -171,11 +153,6 @@
         return nullptr;
     }
 
-    if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, surface.get(),
-                                                   minStencilSampleCount)) {
-        return nullptr;
-    }
-
     return surface;
 }
 
@@ -204,11 +181,6 @@
 #ifdef SK_DEBUG
     if (this->asRenderTargetProxy()) {
         SkASSERT(fTarget->asRenderTarget());
-        if (int minStencilSampleCount = this->asRenderTargetProxy()->numStencilSamples()) {
-            auto* stencil = fTarget->asRenderTarget()->renderTargetPriv().getStencilAttachment();
-            SkASSERT(stencil);
-            SkASSERT(stencil->numSamples() >= minStencilSampleCount);
-        }
     }
 
     if (kInvalidGpuMemorySize != this->getRawGpuMemorySize_debugOnly()) {
@@ -218,19 +190,18 @@
 }
 
 bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
-                                     int minStencilSampleCount, GrRenderable renderable,
-                                     GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
+                                     GrRenderable renderable, GrMipMapped mipMapped,
+                                     const GrUniqueKey* uniqueKey) {
     SkASSERT(!this->isLazy());
     if (fTarget) {
         if (uniqueKey && uniqueKey->isValid()) {
             SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
         }
-        return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget.get(),
-                                                         minStencilSampleCount);
+        return true;
     }
 
-    sk_sp<GrSurface> surface = this->createSurfaceImpl(
-            resourceProvider, sampleCnt, minStencilSampleCount, renderable, mipMapped);
+    sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, sampleCnt, renderable,
+                                                       mipMapped);
     if (!surface) {
         return false;
     }
@@ -451,14 +422,6 @@
     SkASSERT(fProxy->width() <= surface->width());
     SkASSERT(fProxy->height() <= surface->height());
 
-    auto rt = fProxy->asRenderTargetProxy();
-    int minStencilSampleCount = rt ? rt->numSamples() : 0;
-
-    if (!GrSurfaceProxyPriv::AttachStencilIfNeeded(
-            resourceProvider, surface.get(), minStencilSampleCount)) {
-        return false;
-    }
-
     if (GrTextureProxy* texProxy = fProxy->asTextureProxy()) {
         texProxy->setTargetKeySync(syncKey);
         if (syncKey) {
diff --git a/src/gpu/GrSurfaceProxy.h b/src/gpu/GrSurfaceProxy.h
index 1b0ad12..d835957 100644
--- a/src/gpu/GrSurfaceProxy.h
+++ b/src/gpu/GrSurfaceProxy.h
@@ -354,8 +354,8 @@
     virtual sk_sp<GrSurface> createSurface(GrResourceProvider*) const = 0;
     void assign(sk_sp<GrSurface> surface);
 
-    sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt,
-                                       int minStencilSampleCount, GrRenderable, GrMipMapped) const;
+    sk_sp<GrSurface> createSurfaceImpl(GrResourceProvider*, int sampleCnt, GrRenderable,
+                                       GrMipMapped) const;
 
     // Once the dimensions of a fully-lazy proxy are decided, and before it gets instantiated, the
     // client can use this optional method to specify the proxy's dimensions. (A proxy's dimensions
@@ -367,8 +367,8 @@
         fDimensions = dimensions;
     }
 
-    bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt,
-                         int minStencilSampleCount, GrRenderable, GrMipMapped, const GrUniqueKey*);
+    bool instantiateImpl(GrResourceProvider* resourceProvider, int sampleCnt, GrRenderable,
+                         GrMipMapped, const GrUniqueKey*);
 
     // For deferred proxies this will be null until the proxy is instantiated.
     // For wrapped proxies it will point to the wrapped resource.
diff --git a/src/gpu/GrSurfaceProxyPriv.h b/src/gpu/GrSurfaceProxyPriv.h
index 7377651..806fc59 100644
--- a/src/gpu/GrSurfaceProxyPriv.h
+++ b/src/gpu/GrSurfaceProxyPriv.h
@@ -38,10 +38,6 @@
 
     bool doLazyInstantiation(GrResourceProvider*);
 
-
-    static bool SK_WARN_UNUSED_RESULT AttachStencilIfNeeded(GrResourceProvider*, GrSurface*,
-                                                            int minStencilSampleCount);
-
 private:
     explicit GrSurfaceProxyPriv(GrSurfaceProxy* proxy) : fProxy(proxy) {}
     GrSurfaceProxyPriv(const GrSurfaceProxyPriv&) {} // unimpl
diff --git a/src/gpu/GrTextureProxy.cpp b/src/gpu/GrTextureProxy.cpp
index d9c90b7..1cc1178 100644
--- a/src/gpu/GrTextureProxy.cpp
+++ b/src/gpu/GrTextureProxy.cpp
@@ -91,8 +91,8 @@
     if (this->isLazy()) {
         return false;
     }
-    if (!this->instantiateImpl(resourceProvider, 1, /* needsStencil = */ false, GrRenderable::kNo,
-                               fMipMapped, fUniqueKey.isValid() ? &fUniqueKey : nullptr)) {
+    if (!this->instantiateImpl(resourceProvider, 1, GrRenderable::kNo, fMipMapped,
+                               fUniqueKey.isValid() ? &fUniqueKey : nullptr)) {
         return false;
     }
 
@@ -102,9 +102,8 @@
 }
 
 sk_sp<GrSurface> GrTextureProxy::createSurface(GrResourceProvider* resourceProvider) const {
-    sk_sp<GrSurface> surface =
-            this->createSurfaceImpl(resourceProvider, 1,
-                                    /* needsStencil = */ false, GrRenderable::kNo, fMipMapped);
+    sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, 1, GrRenderable::kNo,
+                                                       fMipMapped);
     if (!surface) {
         return nullptr;
     }
diff --git a/src/gpu/GrTextureRenderTargetProxy.cpp b/src/gpu/GrTextureRenderTargetProxy.cpp
index 1e3addd..6675884 100644
--- a/src/gpu/GrTextureRenderTargetProxy.cpp
+++ b/src/gpu/GrTextureRenderTargetProxy.cpp
@@ -123,9 +123,8 @@
 
     const GrUniqueKey& key = this->getUniqueKey();
 
-    if (!this->instantiateImpl(resourceProvider, this->numSamples(), this->numStencilSamples(),
-                               GrRenderable::kYes, this->mipMapped(),
-                               key.isValid() ? &key : nullptr)) {
+    if (!this->instantiateImpl(resourceProvider, this->numSamples(), GrRenderable::kYes,
+                               this->mipMapped(), key.isValid() ? &key : nullptr)) {
         return false;
     }
     if (key.isValid()) {
@@ -140,9 +139,8 @@
 
 sk_sp<GrSurface> GrTextureRenderTargetProxy::createSurface(
                                                     GrResourceProvider* resourceProvider) const {
-    sk_sp<GrSurface> surface =
-            this->createSurfaceImpl(resourceProvider, this->numSamples(), this->numStencilSamples(),
-                                    GrRenderable::kYes, this->mipMapped());
+    sk_sp<GrSurface> surface = this->createSurfaceImpl(resourceProvider, this->numSamples(),
+                                                       GrRenderable::kYes, this->mipMapped());
     if (!surface) {
         return nullptr;
     }