Initiate regeneration of mipmaps from proxy DAG land

This allows us to resolve all the textures before executing a command
buffer, rather than interrupting execution as is currently done in the
GL backend.

Change-Id: I998546b312d24cf47fc2c837e7c94fbf95571af0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/230636
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrRenderTask.cpp b/src/gpu/GrRenderTask.cpp
index 66b6c3e..3b572fc 100644
--- a/src/gpu/GrRenderTask.cpp
+++ b/src/gpu/GrRenderTask.cpp
@@ -24,7 +24,6 @@
         : fTarget(std::move(target))
         , fUniqueID(CreateUniqueID())
         , fFlags(0) {
-    fTarget->setLastRenderTask(this);
 }
 
 GrRenderTask::~GrRenderTask() {
@@ -69,13 +68,44 @@
 }
 
 // Convert from a GrSurface-based dependency to a GrRenderTask one
-void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped, GrTextureResolveManager,
+void GrRenderTask::addDependency(GrSurfaceProxy* dependedOn, GrMipMapped mipMapped,
+                                 GrTextureResolveManager textureResolveManager,
                                  const GrCaps& caps) {
-    if (dependedOn->getLastRenderTask()) {
+    GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask();
+
+    GrTextureProxy* textureProxy = dependedOn->asTextureProxy();
+    SkASSERT(GrMipMapped::kNo == mipMapped || textureProxy);
+
+    // Does this proxy have mipmaps that need to be regenerated?
+    if (GrMipMapped::kYes == mipMapped && textureProxy->mipMapsAreDirty()) {
+        // We only read our own target during dst reads, and we shouldn't use mipmaps in that case.
+        SkASSERT(dependedOnTask != this);
+
+        // Create an opList that resolves the texture's mipmap data.
+        GrRenderTask* textureResolveTask = textureResolveManager.newTextureResolveRenderTask(
+                sk_ref_sp(textureProxy), GrTextureResolveFlags::kMipMaps, caps);
+
+        // The GrTextureResolveRenderTask factory should have called addDependency (in this
+        // instance, recursively) on the textureProxy.
+        SkASSERT(!dependedOnTask || textureResolveTask->dependsOn(dependedOnTask));
+        SkASSERT(!textureProxy->texPriv().isDeferred() ||
+                 textureResolveTask->fDeferredProxies.back() == textureProxy);
+
+        // The GrTextureResolveRenderTask factory should have also marked the mipmaps clean and set
+        // the last opList on the textureProxy to textureResolveTask.
+        SkASSERT(!textureProxy->mipMapsAreDirty());
+        SkASSERT(textureProxy->getLastRenderTask() == textureResolveTask);
+
+        // Fall through and add textureResolveTask as a dependency of "this".
+        dependedOnTask = textureResolveTask;
+    } else if (textureProxy && textureProxy->texPriv().isDeferred()) {
+        fDeferredProxies.push_back(textureProxy);
+    }
+
+    if (dependedOnTask) {
         // If it is still receiving dependencies, this GrRenderTask shouldn't be closed
         SkASSERT(!this->isClosed());
 
-        GrRenderTask* dependedOnTask = dependedOn->getLastRenderTask();
         if (dependedOnTask == this) {
             // self-read - presumably for dst reads. We can't make it closed in the self-read case.
         } else {
@@ -87,12 +117,6 @@
             dependedOnTask->makeClosed(caps);
         }
     }
-
-    if (GrTextureProxy* textureProxy = dependedOn->asTextureProxy()) {
-        if (textureProxy->texPriv().isDeferred()) {
-            fDeferredProxies.push_back(textureProxy);
-        }
-    }
 }
 
 bool GrRenderTask::dependsOn(const GrRenderTask* dependedOn) const {