Prepare ddl skp rendering for prime time

Change-Id: I87742b8ef043588c4e835ab6ec49b217dd49f829
Reviewed-on: https://skia-review.googlesource.com/114289
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 6f2025f..a6cb97f 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -97,8 +97,6 @@
 DEFINE_string(mskps, "", "Directory to read mskps from, or a single mskp file.");
 DEFINE_bool(forceRasterPipeline, false, "sets gSkForceRasterPipelineBlitter");
 
-DEFINE_bool(ddl, false, "If true, use DeferredDisplayLists for GPU SKP rendering.");
-
 DEFINE_bool(ignoreSigInt, false, "ignore SIGINT signals during test execution");
 
 DEFINE_string(dont_write, "", "File extensions to skip writing to --writePath.");  // See skia:6821
@@ -790,7 +788,7 @@
         push_src("gm", "", new GMSrc(r->factory()));
     }
 
-    if (FLAGS_ddl) {
+    if (FLAGS_ddl > 0) {
         gather_file_srcs<DDLSKPSrc>(FLAGS_skps, "skp");
     } else {
         gather_file_srcs<SKPSrc>(FLAGS_skps, "skp");
diff --git a/dm/DMSrcSink.cpp b/dm/DMSrcSink.cpp
index 9772700..7256348 100644
--- a/dm/DMSrcSink.cpp
+++ b/dm/DMSrcSink.cpp
@@ -1207,12 +1207,8 @@
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
-static const int kNumDDLXTiles = 3;
-static const int kNumDDLYTiles = 3;
-static const int kDDLTileSize = 1024;
-static const SkRect kDDLSKPViewport = { 0, 0,
-                                        kNumDDLXTiles * kDDLTileSize,
-                                        kNumDDLYTiles * kDDLTileSize };
+static const int kDDLViewportSize = 2048;
+static const SkRect kDDLSKPViewport = { 0, 0, kDDLViewportSize, kDDLViewportSize };
 
 DDLSKPSrc::DDLSKPSrc(Path path) : fPath(path) { }
 
@@ -1317,12 +1313,26 @@
     return image;
 };
 
+// DDL TODO: it would be great if we could draw the DDL directly into the destination SkSurface
 Error DDLSKPSrc::draw(SkCanvas* canvas) const {
     GrContext* context = canvas->getGrContext();
     if (!context) {
         return SkStringPrintf("DDLs are GPU only\n");
     }
 
+    if (1 == FLAGS_ddl) {
+        // If the number of x & y tiles is one just perform normal (non-DDL) rendering for
+        // comparison purposes
+        sk_sp<SkPicture> picture = read_skp(fPath.c_str());
+        if (!picture) {
+            return SkStringPrintf("Couldn't read %s.", fPath.c_str());
+        }
+
+        canvas->clipRect(kDDLSKPViewport);
+        canvas->drawPicture(std::move(picture));
+        return "";
+    }
+
     class TileData {
     public:
         // Note: we could just pass in surface characterization
@@ -1394,7 +1404,8 @@
 
     SkTArray<PromiseImageInfo> imageInfo;
     sk_sp<SkData> compressedPictureData;
-    SkRect pictureCullRect;
+
+    SkIRect viewport;  // this is our ultimate final drawing area/rect
 
     // DDL TODO: should we also be deduping in the following preprocessing?
 
@@ -1426,7 +1437,9 @@
                 return SkStringPrintf("Couldn't read %s.", fPath.c_str());
             }
 
-            pictureCullRect = firstPassPicture->cullRect();
+            SkRect pictureCullRect = firstPassPicture->cullRect();
+            SkAssertResult(pictureCullRect.intersect(kDDLSKPViewport));
+            viewport = pictureCullRect.roundOut();
         }
 
         // In the second pass we convert the SkPicture into SkData replacing all the SkImages
@@ -1477,20 +1490,23 @@
         }
     }
 
-    // All the destination tiles are the same size
-    const SkImageInfo tileII = SkImageInfo::MakeN32Premul(kDDLTileSize, kDDLTileSize);
+    int xTileSize = viewport.width()/FLAGS_ddl;
+    int yTileSize = viewport.height()/FLAGS_ddl;
 
     // First, create the destination tiles
-    for (int y = 0; y < kNumDDLYTiles; ++y) {
-        for (int x = 0; x < kNumDDLXTiles; ++x) {
-            SkRect clip = SkRect::MakeXYWH(x * kDDLTileSize, y * kDDLTileSize,
-                                           kDDLTileSize, kDDLTileSize);
+    for (int y = 0, yOff = 0; y < FLAGS_ddl; ++y, yOff += yTileSize) {
+        int ySize = (y < FLAGS_ddl-1) ? yTileSize : viewport.height()-yOff;
 
-            if (!clip.intersect(pictureCullRect)) {
-                continue;
-            }
+        for (int x = 0, xOff = 0; x < FLAGS_ddl; ++x, xOff += xTileSize) {
+            int xSize = (x < FLAGS_ddl-1) ? xTileSize : viewport.width()-xOff;
 
-            tileData.push_back(TileData(canvas->makeSurface(tileII), clip.roundOut()));
+            SkIRect clip = SkIRect::MakeXYWH(xOff, yOff, xSize, ySize);
+
+            SkASSERT(viewport.contains(clip));
+
+            SkImageInfo tileII = SkImageInfo::MakeN32Premul(xSize, ySize);
+
+            tileData.push_back(TileData(canvas->makeSurface(tileII), clip));
         }
     }
 
diff --git a/tools/flags/SkCommonFlags.cpp b/tools/flags/SkCommonFlags.cpp
index 4f89505..b78b7d4 100644
--- a/tools/flags/SkCommonFlags.cpp
+++ b/tools/flags/SkCommonFlags.cpp
@@ -63,6 +63,9 @@
 DEFINE_string(jsons, "jsons", "Directory to read (Bodymovin) jsons from.");
 #endif
 
+DEFINE_int32(ddl, 0, "If > 0, the # of x & y divisions used for DeferredDisplayList-based "
+                     "GPU SKP rendering.");
+
 DEFINE_bool(nativeFonts, true, "If true, use native font manager and rendering. "
                                "If false, fonts will draw as portably as possible.");
 
diff --git a/tools/flags/SkCommonFlags.h b/tools/flags/SkCommonFlags.h
index 1f0c8d1..cdd0d84 100644
--- a/tools/flags/SkCommonFlags.h
+++ b/tools/flags/SkCommonFlags.h
@@ -24,7 +24,7 @@
 DECLARE_bool(abandonGpuContext);
 DECLARE_bool(releaseAndAbandonGpuContext);
 DECLARE_string(skps);
-DECLARE_bool(ddl);
+DECLARE_int32(ddl);
 DECLARE_string(jpgs);
 DECLARE_string(jsons);
 DECLARE_string(svgs);