Add new DM via, "ddl2" which records/draws DDLs for each test twice.

Clears between the two DDL runs.

Also, fix up proxy unique key checks in GrSurfaceProxy.

Change-Id: I492e791ebc57a42063f3b828c10d8bf5fee70b1b
Reviewed-on: https://skia-review.googlesource.com/c/178262
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 043e553..1694676 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -969,7 +969,8 @@
     VIA("tiles",     ViaTiles, 256, 256, nullptr,            wrapped);
     VIA("tiles_rt",  ViaTiles, 256, 256, new SkRTreeFactory, wrapped);
 
-    VIA("ddl",       ViaDDL, 3,            wrapped);
+    VIA("ddl",       ViaDDL, 1, 3,         wrapped);
+    VIA("ddl2",      ViaDDL, 2, 3,         wrapped);
 
     if (FLAGS_matrix.count() == 4) {
         SkMatrix m;
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 14311c4..cd9f099 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1939,10 +1939,8 @@
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
-ViaDDL::ViaDDL(int numDivisions, Sink* sink)
-    : Via(sink)
-    , fNumDivisions(numDivisions) {
-}
+ViaDDL::ViaDDL(int numReplays, int numDivisions, Sink* sink)
+        : Via(sink), fNumReplays(numReplays), fNumDivisions(numDivisions) {}
 
 Error ViaDDL::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
     auto size = src.size();
@@ -1962,42 +1960,49 @@
     if (!compressedPictureData) {
         return SkStringPrintf("ViaDDL: Couldn't deflate SkPicture");
     }
+    auto draw = [&](SkCanvas* canvas) -> Error {
+        GrContext* context = canvas->getGrContext();
+        if (!context || !context->contextPriv().getGpu()) {
+            return SkStringPrintf("DDLs are GPU only");
+        }
 
-    return draw_to_canvas(fSink.get(), bitmap, stream, log, size,
-                [&](SkCanvas* canvas) -> Error {
-                    GrContext* context = canvas->getGrContext();
-                    if (!context || !context->contextPriv().getGpu()) {
-                        return SkStringPrintf("DDLs are GPU only");
-                    }
+        // This is here bc this is the first point where we have access to the context
+        promiseImageHelper.uploadAllToGPU(context);
+        // We draw N times, with a clear between.
+        for (int replay = 0; replay < fNumReplays; ++replay) {
+            if (replay > 0) {
+                // Clear the drawing of the previous replay
+                canvas->clear(SK_ColorWHITE);
+            }
+            // First, create all the tiles (including their individual dest surfaces)
+            DDLTileHelper tiles(canvas, viewport, fNumDivisions);
 
-                    // This is here bc this is the first point where we have access to the context
-                    promiseImageHelper.uploadAllToGPU(context);
+            // Second, reinflate the compressed picture individually for each thread
+            tiles.createSKPPerTile(compressedPictureData.get(), promiseImageHelper);
 
-                    // First, create all the tiles (including their individual dest surfaces)
-                    DDLTileHelper tiles(canvas, viewport, fNumDivisions);
+            // Third, create the DDLs in parallel
+            tiles.createDDLsInParallel();
 
-                    // Second, reinflate the compressed picture individually for each thread
-                    tiles.createSKPPerTile(compressedPictureData.get(), promiseImageHelper);
+            if (replay == fNumReplays - 1) {
+                // This drops the promiseImageHelper's refs on all the promise images if we're in
+                // the last run.
+                promiseImageHelper.reset();
+            }
 
-                    // Third, create the DDLs in parallel
-                    tiles.createDDLsInParallel();
+            // Fourth, synchronously render the display lists into the dest tiles
+            // TODO: it would be cool to not wait until all the tiles are drawn to begin
+            // drawing to the GPU and composing to the final surface
+            tiles.drawAllTilesAndFlush(context, false);
 
-                    // This drops the promiseImageHelper's refs on all the promise images
-                    promiseImageHelper.reset();
-
-                    // Fourth, synchronously render the display lists into the dest tiles
-                    // TODO: it would be cool to not wait until all the tiles are drawn to begin
-                    // drawing to the GPU and composing to the final surface
-                    tiles.drawAllTilesAndFlush(context, false);
-
-                    // Finally, compose the drawn tiles into the result
-                    // Note: the separation between the tiles and the final composition better
-                    // matches Chrome but costs us a copy
-                    tiles.composeAllTiles(canvas);
-
-                    context->flush();
-                    return "";
-                });
+            // Finally, compose the drawn tiles into the result
+            // Note: the separation between the tiles and the final composition better
+            // matches Chrome but costs us a copy
+            tiles.composeAllTiles(canvas);
+            context->flush();
+        }
+        return "";
+    };
+    return draw_to_canvas(fSink.get(), bitmap, stream, log, size, draw);
 }
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
diff --git a/dm/DMSrcSink.h b/dm/DMSrcSink.h
index 954aff3..5875b15 100644
--- a/dm/DMSrcSink.h
+++ b/dm/DMSrcSink.h
@@ -543,9 +543,10 @@
 
 class ViaDDL : public Via {
 public:
-    ViaDDL(int numDivisions, Sink* sink);
+    ViaDDL(int numReplays, int numDivisions, Sink* sink);
     Error draw(const Src&, SkBitmap*, SkWStream*, SkString*) const override;
 private:
+    const int fNumReplays;
     const int fNumDivisions;
 };
 
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 617f2aa..a8ee43f 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -222,8 +222,8 @@
                                      GrMipMapped mipMapped, const GrUniqueKey* uniqueKey) {
     SkASSERT(LazyState::kNot == this->lazyInstantiationState());
     if (fTarget) {
-        if (uniqueKey) {
-            SkASSERT(fTarget->getUniqueKey() == *uniqueKey);
+        if (uniqueKey && uniqueKey->isValid()) {
+            SkASSERT(fTarget->getUniqueKey().isValid() && fTarget->getUniqueKey() == *uniqueKey);
         }
         return GrSurfaceProxyPriv::AttachStencilIfNeeded(resourceProvider, fTarget, needsStencil);
     }