Reland "Initiate regeneration of mipmaps from proxy DAG land"

This is a reland of fe19203eb7d7e8bef528287494d82c2eb4efff0e

Original change's description:
> 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>

Change-Id: Ic904d0b1bcb451bcb74cfae2204fb7297eaff108
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/234016
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/tests/GrMipMappedTest.cpp b/tests/GrMipMappedTest.cpp
index c635349..be88c28 100644
--- a/tests/GrMipMappedTest.cpp
+++ b/tests/GrMipMappedTest.cpp
@@ -14,6 +14,7 @@
 #include "include/gpu/GrContext.h"
 #include "src/gpu/GrBackendTextureImageGenerator.h"
 #include "src/gpu/GrContextPriv.h"
+#include "src/gpu/GrDrawingManager.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrRenderTargetContext.h"
 #include "src/gpu/GrSemaphore.h"
@@ -336,3 +337,112 @@
     surface->flush();
 }
 
+// Create a new render target and draw 'mipmapProxy' into it using the provided 'filter'.
+static sk_sp<GrRenderTargetContext> draw_mipmap_into_new_render_target(
+        GrDrawingManager* drawingManager, GrProxyProvider* proxyProvider, GrColorType colorType,
+        sk_sp<GrTextureProxy> mipmapProxy, GrSamplerState::Filter filter) {
+    GrSurfaceDesc desc;
+    desc.fWidth = 1;
+    desc.fHeight = 1;
+    desc.fConfig = mipmapProxy->config();
+    sk_sp<GrSurfaceProxy> renderTarget = proxyProvider->createProxy(
+            mipmapProxy->backendFormat(), desc, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin,
+            SkBackingFit::kApprox, SkBudgeted::kYes, GrProtected::kNo);
+    sk_sp<GrRenderTargetContext> rtc = drawingManager->makeRenderTargetContext(
+            std::move(renderTarget), colorType, nullptr, nullptr, true);
+    rtc->drawTexture(GrNoClip(), mipmapProxy, filter, SkBlendMode::kSrcOver, {1,1,1,1},
+                     SkRect::MakeWH(4, 4), SkRect::MakeWH(1,1), GrAA::kYes, GrQuadAAFlags::kAll,
+                     SkCanvas::kFast_SrcRectConstraint, SkMatrix::I(), nullptr);
+    return rtc;
+}
+
+// Test that two opLists using the same mipmaps both depend on the same GrTextureResolveRenderTask.
+DEF_GPUTEST_FOR_ALL_CONTEXTS(GrManyDependentsMipMappedTest, reporter, ctxInfo) {
+    GrContext* context = ctxInfo.grContext();
+    if (!context->priv().caps()->mipMapSupport()) {
+        return;
+    }
+
+    GrBackendFormat format = context->defaultBackendFormat(
+            kRGBA_8888_SkColorType, GrRenderable::kYes);
+    GrPixelConfig config = kRGBA_8888_GrPixelConfig;
+    GrColorType colorType = GrColorType::kRGBA_8888;
+
+    GrDrawingManager* drawingManager = context->priv().drawingManager();
+    GrProxyProvider* proxyProvider = context->priv().proxyProvider();
+
+    // Create a mipmapped render target.
+    GrSurfaceDesc desc;
+    desc.fWidth = 4;
+    desc.fHeight = 4;
+    desc.fConfig = config;
+    sk_sp<GrTextureProxy> mipmapProxy = proxyProvider->createMipMapProxy(
+            format, desc, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin, SkBudgeted::kYes,
+            GrProtected::kNo);
+
+    // Render something to dirty the mips.
+    sk_sp<GrRenderTargetContext> mipmapRTC = drawingManager->makeRenderTargetContext(
+            mipmapProxy, colorType, nullptr, nullptr, true);
+    mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, GrRenderTargetContext::CanClearFullscreen::kYes);
+    REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
+    REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
+    // mipmapProxy's last render task should just be the opList containing the clear at this point.
+    REPORTER_ASSERT(
+            reporter, mipmapRTC->testingOnly_PeekLastOpList() == mipmapProxy->getLastRenderTask());
+
+    // Draw the dirty mipmap texture into a render target.
+    sk_sp<GrRenderTargetContext> rtc1 = draw_mipmap_into_new_render_target(
+            drawingManager, proxyProvider, colorType, mipmapProxy, GrSamplerState::Filter::kMipMap);
+
+    // Make sure the texture's mipmaps are now clean, and its last render task has switched from the
+    // opList that drew to it, to the task that resolved its mips.
+    GrRenderTask* initialMipmapRegenTask = mipmapProxy->getLastRenderTask();
+    REPORTER_ASSERT(reporter, initialMipmapRegenTask);
+    REPORTER_ASSERT(reporter, initialMipmapRegenTask != mipmapRTC->testingOnly_PeekLastOpList());
+    REPORTER_ASSERT(
+            reporter, rtc1->testingOnly_PeekLastOpList()->dependsOn(initialMipmapRegenTask));
+    REPORTER_ASSERT(reporter, !mipmapProxy->mipMapsAreDirty());
+    SkASSERT(!mipmapProxy->mipMapsAreDirty());
+
+    // Draw the now-clean mipmap texture into a second target.
+    sk_sp<GrRenderTargetContext> rtc2 = draw_mipmap_into_new_render_target(
+            drawingManager, proxyProvider, colorType, mipmapProxy, GrSamplerState::Filter::kMipMap);
+
+    // Make sure the mipmap texture still has the same regen task.
+    REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask() == initialMipmapRegenTask);
+    REPORTER_ASSERT(
+            reporter, rtc2->testingOnly_PeekLastOpList()->dependsOn(initialMipmapRegenTask));
+    SkASSERT(!mipmapProxy->mipMapsAreDirty());
+
+    // Reset everything so we can go again, this time with the first draw not mipmapped.
+    context->flush();
+
+    // Render something to dirty the mips.
+    mipmapRTC->clear(nullptr, {.1f,.2f,.3f,.4f}, GrRenderTargetContext::CanClearFullscreen::kYes);
+    REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
+    REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
+    // mipmapProxy's last render task should just be the opList containing the clear at this point.
+    REPORTER_ASSERT(
+            reporter, mipmapRTC->testingOnly_PeekLastOpList() == mipmapProxy->getLastRenderTask());
+
+    // Draw the dirty mipmap texture into a render target, but don't do mipmap filtering.
+    rtc1 = draw_mipmap_into_new_render_target(
+            drawingManager, proxyProvider, colorType, mipmapProxy, GrSamplerState::Filter::kBilerp);
+
+    // Make sure the texture's mipmaps are still dirty, and its last render task has not changed.
+    REPORTER_ASSERT(reporter, mipmapProxy->mipMapsAreDirty());
+    REPORTER_ASSERT(
+            reporter, mipmapRTC->testingOnly_PeekLastOpList() == mipmapProxy->getLastRenderTask());
+
+    // Draw the stil-dirty mipmap texture into a second target.
+    rtc2 = draw_mipmap_into_new_render_target(
+            drawingManager, proxyProvider, colorType, mipmapProxy, GrSamplerState::Filter::kMipMap);
+
+    // Make sure the mipmap texture now has a new last render task.
+    REPORTER_ASSERT(reporter, mipmapProxy->getLastRenderTask());
+    REPORTER_ASSERT(reporter,
+            mipmapRTC->testingOnly_PeekLastOpList() != mipmapProxy->getLastRenderTask());
+    REPORTER_ASSERT(reporter,
+            rtc2->testingOnly_PeekLastOpList()->dependsOn(mipmapProxy->getLastRenderTask()));
+    SkASSERT(!mipmapProxy->mipMapsAreDirty());
+}