Roll external/skia bf341ae88..99ccc0ca8 (20 commits)

https://skia.googlesource.com/skia.git/+log/bf341ae88..99ccc0ca8

2019-03-27 mtklein@google.com lazy svg parsing in TestSVGTypeface
2019-03-27 mtklein@google.com split up skia_srcs() in public.bzl
2019-03-27 skia-autoroll@skia-public.iam.gserviceaccount.com Roll third_party/externals/angle2 518c679da109..c240abe4ef2c (1 commits)
2019-03-27 bsalomon@google.com Disable texture storage on Android over command buffer.
2019-03-27 mtklein@google.com update DM_SRCS to build tools/HashAndEncode
2019-03-27 skia-autoroll@skia-public.iam.gserviceaccount.com Roll third_party/externals/swiftshader df5b28fdb45c..e43cda5f76de (1 commits)
2019-03-27 michaelludwig@google.com Fix paint filter quality in draw_image_set GM
2019-03-27 enne@chromium.org Add a function to compute texture sizes
2019-03-27 mtklein@google.com FM, a dumber new testing tool
2019-03-27 rmistry@google.com Fix RecreateSKPs bot page sets III
2019-03-27 robertphillips@google.com Minor cleanup of GrResourceAllocator
2019-03-27 fmalita@chromium.org [skottie] Fix handling of hidden shapes and layers
2019-03-27 robertphillips@google.com Fix bug in GrResourceAllocator's intermediate flushing (take 2)
2019-03-27 skia-autoroll@skia-public.iam.gserviceaccount.com Roll third_party/externals/swiftshader e747b3c3c9d9..df5b28fdb45c (1 commits)
2019-03-27 skia-recreate-skps@skia-swarming-bots.iam.gserviceaccount.com Update go_deps asset
2019-03-27 skia-recreate-skps@skia-swarming-bots.iam.gserviceaccount.com Update SKP version
2019-03-27 skia-recreate-skps@skia-swarming-bots.iam.gserviceaccount.com Update SKP version
2019-03-27 skia-autoroll@skia-public.iam.gserviceaccount.com Roll third_party/externals/angle2 a47e2a23ab4c..518c679da109 (3 commits)
2019-03-27 skia-autoroll@skia-public.iam.gserviceaccount.com Roll ../src 4035f6c897d0..83d44af5c208 (535 commits)
2019-03-27 recipe-mega-autoroller@chops-service-accounts.iam.gserviceaccount.com Roll recipe dependencies (trivial).

The AutoRoll server is located here: https://autoroll-internal.skia.org/r/android-master-autoroll

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

If the roll is causing failures, please contact the current sheriff, who should
be CC'd on the roll, and stop the roller if necessary.

Test: Presubmit checks will test this change.
Change-Id: I7d3553a8d645fe1048f7999cca212a60d7b47f5c
Exempt-From-Owner-Approval: The autoroll bot does not require owner approval.
diff --git a/Android.bp b/Android.bp
index 6b270ee..4556c66 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1843,6 +1843,7 @@
         "tools/CrashHandler.cpp",
         "tools/DDLPromiseImageHelper.cpp",
         "tools/DDLTileHelper.cpp",
+        "tools/HashAndEncode.cpp",
         "tools/LsanSuppressions.cpp",
         "tools/ProcStats.cpp",
         "tools/Resources.cpp",
diff --git a/BUILD.gn b/BUILD.gn
index 7ee1d9b..7e67d9d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1850,6 +1850,34 @@
         ":skia",
       ]
     }
+    test_lib("hash_and_encode") {
+      public_include_dirs = [ "tools" ]
+      sources = [
+        "tools/HashAndEncode.cpp",
+        "tools/HashAndEncode.h",
+      ]
+      deps = [
+        ":flags",
+        ":skia",
+        "//third_party/libpng",
+      ]
+    }
+    test_app("fm") {
+      sources = [
+        "tools/fm/fm.cpp",
+      ]
+      deps = [
+        ":common_flags_aa",
+        ":common_flags_gpu",
+        ":flags",
+        ":gm",
+        ":gpu_tool_utils",
+        ":hash_and_encode",
+        ":skia",
+        ":tool_utils",
+        ":trace",
+      ]
+    }
     test_app("dm") {
       sources = [
         "dm/DM.cpp",
@@ -1866,6 +1894,7 @@
         ":flags",
         ":gm",
         ":gpu_tool_utils",
+        ":hash_and_encode",
         ":skia",
         ":tests",
         ":tool_utils",
@@ -1873,7 +1902,6 @@
         "modules/skottie",
         "modules/skottie:utils",
         "modules/sksg",
-        "//third_party/libpng",
       ]
 
       # NIMA does not build on Windows clang
diff --git a/DEPS b/DEPS
index 968e26c..91dab34 100644
--- a/DEPS
+++ b/DEPS
@@ -7,7 +7,7 @@
 deps = {
   "buildtools"                            : "https://chromium.googlesource.com/chromium/buildtools.git@505de88083136eefd056e5ee4ca0f01fe9b33de8",
   "common"                                : "https://skia.googlesource.com/common.git@9737551d7a52c3db3262db5856e6bcd62c462b92",
-  "third_party/externals/angle2"          : "https://chromium.googlesource.com/angle/angle.git@a47e2a23ab4c86edcda3f2555ba44573797fe1c2",
+  "third_party/externals/angle2"          : "https://chromium.googlesource.com/angle/angle.git@c240abe4ef2c07895125a0cb0263f3b3b403019c",
   "third_party/externals/dng_sdk"         : "https://android.googlesource.com/platform/external/dng_sdk.git@96443b262250c390b0caefbf3eed8463ba35ecae",
   "third_party/externals/egl-registry"    : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae",
   "third_party/externals/expat"           : "https://android.googlesource.com/platform/external/expat.git@android-6.0.1_r55",
@@ -28,7 +28,7 @@
   "third_party/externals/sfntly"          : "https://chromium.googlesource.com/external/github.com/googlei18n/sfntly.git@b55ff303ea2f9e26702b514cf6a3196a2e3e2974",
   "third_party/externals/spirv-headers"   : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@661ad91124e6af2272afd00f804d8aa276e17107",
   "third_party/externals/spirv-tools"     : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@e9e4393b1c5aad7553c05782acefbe32b42644bd",
-  "third_party/externals/swiftshader"     : "https://swiftshader.googlesource.com/SwiftShader@e747b3c3c9d94a97187e134ff79fda0a08cdb3e0",
+  "third_party/externals/swiftshader"     : "https://swiftshader.googlesource.com/SwiftShader@e43cda5f76de4de28797cdd1ec38ee4fab41de8e",
   #"third_party/externals/v8"              : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4",
   "third_party/externals/wuffs"           : "https://skia.googlesource.com/external/github.com/google/wuffs.git@ae6e8db4ad4236654e7b8c68d24f41a37e5f4f96",
   "third_party/externals/zlib"            : "https://chromium.googlesource.com/chromium/src/third_party/zlib@47af7c547f8551bd25424e56354a2ae1e9062859",
@@ -36,7 +36,7 @@
   "third_party/externals/Nima-Math-Cpp"   : "https://skia.googlesource.com/external/github.com/2d-inc/Nima-Math-Cpp.git@e0c12772093fa8860f55358274515b86885f0108",
 
   "../src": {
-    "url": "https://chromium.googlesource.com/chromium/src.git@4035f6c897d0c92b7ddaf58587544762326615e7",
+    "url": "https://chromium.googlesource.com/chromium/src.git@83d44af5c2085975bdd83c67c9042d3945981cfa",
     "condition": "checkout_chromium",
   },
 }
diff --git a/dm/DM.cpp b/dm/DM.cpp
index 90b8abc..4cdfe76 100644
--- a/dm/DM.cpp
+++ b/dm/DM.cpp
@@ -11,6 +11,7 @@
 #include "DMJsonWriter.h"
 #include "DMSrcSink.h"
 #include "EventTracingPriv.h"
+#include "HashAndEncode.h"
 #include "ProcStats.h"
 #include "Resources.h"
 #include "SkBBHFactory.h"
@@ -25,7 +26,6 @@
 #include "SkFontMgr.h"
 #include "SkGraphics.h"
 #include "SkHalf.h"
-#include "SkICC.h"
 #include "SkLeanWindows.h"
 #include "SkMD5.h"
 #include "SkMutex.h"
@@ -41,8 +41,6 @@
 
 #include <vector>
 
-#include "png.h"
-
 #include <stdlib.h>
 
 #ifndef SK_BUILD_FOR_WIN
@@ -360,163 +358,6 @@
 
 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 
-class HashAndEncode {
-public:
-    explicit HashAndEncode(const SkBitmap&);
-
-    void write(SkWStream*) const;
-
-    bool writePngTo(const char* path, const char* md5) const;
-
-private:
-    const SkISize               fSize;
-    std::unique_ptr<uint64_t[]> fPixels;
-};
-
-HashAndEncode::HashAndEncode(const SkBitmap& bitmap) : fSize(bitmap.info().dimensions()) {
-    skcms_AlphaFormat srcAlpha;
-    switch (bitmap.alphaType()) {
-        case kUnknown_SkAlphaType: SkASSERT(false); return;
-
-        case kOpaque_SkAlphaType:
-        case kUnpremul_SkAlphaType: srcAlpha = skcms_AlphaFormat_Unpremul;        break;
-        case kPremul_SkAlphaType:   srcAlpha = skcms_AlphaFormat_PremulAsEncoded; break;
-    }
-
-    skcms_PixelFormat srcFmt;
-    switch (bitmap.colorType()) {
-        case kUnknown_SkColorType: SkASSERT(false); return;
-
-        case kAlpha_8_SkColorType:      srcFmt = skcms_PixelFormat_A_8;          break;
-        case kRGB_565_SkColorType:      srcFmt = skcms_PixelFormat_BGR_565;      break;
-        case kARGB_4444_SkColorType:    srcFmt = skcms_PixelFormat_ABGR_4444;    break;
-        case kRGBA_8888_SkColorType:    srcFmt = skcms_PixelFormat_RGBA_8888;    break;
-        case kBGRA_8888_SkColorType:    srcFmt = skcms_PixelFormat_BGRA_8888;    break;
-        case kRGBA_1010102_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102; break;
-        case kGray_8_SkColorType:       srcFmt = skcms_PixelFormat_G_8;          break;
-        case kRGBA_F16Norm_SkColorType: srcFmt = skcms_PixelFormat_RGBA_hhhh;    break;
-        case kRGBA_F16_SkColorType:     srcFmt = skcms_PixelFormat_RGBA_hhhh;    break;
-        case kRGBA_F32_SkColorType:     srcFmt = skcms_PixelFormat_RGBA_ffff;    break;
-
-        case kRGB_888x_SkColorType:     srcFmt = skcms_PixelFormat_RGBA_8888;
-                                        srcAlpha = skcms_AlphaFormat_Opaque;       break;
-        case kRGB_101010x_SkColorType:  srcFmt = skcms_PixelFormat_RGBA_1010102;
-                                        srcAlpha = skcms_AlphaFormat_Opaque;       break;
-    }
-
-    skcms_ICCProfile srcProfile = *skcms_sRGB_profile();
-    if (auto cs = bitmap.colorSpace()) {
-        cs->toProfile(&srcProfile);
-    }
-
-    // Our common format that can represent anything we draw and encode as a PNG:
-    //   - 16-bit big-endian RGBA
-    //   - unpremul
-    //   - Rec. 2020 gamut and transfer function
-    skcms_PixelFormat dstFmt   = skcms_PixelFormat_RGBA_16161616BE;
-    skcms_AlphaFormat dstAlpha = skcms_AlphaFormat_Unpremul;
-    skcms_ICCProfile dstProfile;
-    rec2020()->toProfile(&dstProfile);
-
-    int N = fSize.width() * fSize.height();
-    fPixels.reset(new uint64_t[N]);
-
-    if (!skcms_Transform(bitmap.getPixels(), srcFmt, srcAlpha, &srcProfile,
-                         fPixels.get(),      dstFmt, dstAlpha, &dstProfile, N)) {
-        SkASSERT(false);
-        fPixels.reset(nullptr);
-    }
-}
-
-void HashAndEncode::write(SkWStream* st) const {
-    st->write(&fSize, sizeof(fSize));
-    if (const uint64_t* px = fPixels.get()) {
-        st->write(px, sizeof(*px) * fSize.width() * fSize.height());
-    }
-
-    // N.B. changing salt will change the hash of all images produced by DM,
-    // and will cause tens of thousands of new images to be uploaded to Gold.
-    int salt = 1;
-    st->write(&salt, sizeof(salt));
-}
-
-bool HashAndEncode::writePngTo(const char* path, const char* md5) const {
-    if (!fPixels) {
-        return false;
-    }
-
-    FILE* f = fopen(path, "wb");
-    if (!f) {
-        return false;
-    }
-
-    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
-    if (!png) {
-        fclose(f);
-        return false;
-    }
-
-    png_infop info = png_create_info_struct(png);
-    if (!info) {
-        png_destroy_write_struct(&png, &info);
-        fclose(f);
-        return false;
-    }
-
-    SkString description;
-    description.append("Key: ");
-    for (int i = 0; i < FLAGS_key.count(); i++) {
-        description.appendf("%s ", FLAGS_key[i]);
-    }
-    description.append("Properties: ");
-    for (int i = 0; i < FLAGS_properties.count(); i++) {
-        description.appendf("%s ", FLAGS_properties[i]);
-    }
-    description.appendf("MD5: %s", md5);
-
-    png_text text[2];
-    text[0].key  = (png_charp)"Author";
-    text[0].text = (png_charp)"DM unified Rec.2020";
-    text[0].compression = PNG_TEXT_COMPRESSION_NONE;
-    text[1].key  = (png_charp)"Description";
-    text[1].text = (png_charp)description.c_str();
-    text[1].compression = PNG_TEXT_COMPRESSION_NONE;
-    png_set_text(png, info, text, SK_ARRAY_COUNT(text));
-
-    png_init_io(png, f);
-    png_set_IHDR(png, info, (png_uint_32)fSize.width()
-                          , (png_uint_32)fSize.height()
-                          , 16/*bits per channel*/
-                          , PNG_COLOR_TYPE_RGB_ALPHA
-                          , PNG_INTERLACE_NONE
-                          , PNG_COMPRESSION_TYPE_DEFAULT
-                          , PNG_FILTER_TYPE_DEFAULT);
-
-    // Fastest encoding and decoding, at slight file size cost is no filtering, compression 1.
-    png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
-    // TODO(mtklein): set back to 1 after all the bots have cycled through new images / hashes?
-    png_set_compression_level(png, 9);
-
-    static const sk_sp<SkData> profile = SkWriteICCProfile(k2020_TF, SkNamedGamut::kRec2020);
-    png_set_iCCP(png, info,
-                 "Rec.2020",
-                 0/*compression type... no idea what options are available here*/,
-                 (png_const_bytep)profile->data(),
-                 (png_uint_32)    profile->size());
-
-    png_write_info(png, info);
-    for (int y = 0; y < fSize.height(); y++) {
-        png_write_row(png, (png_bytep)(fPixels.get() + y*fSize.width()));
-    }
-    png_write_end(png, info);
-
-    png_destroy_write_struct(&png, &info);
-    fclose(f);
-    return true;
-}
-
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
 struct Gold : public SkString {
     Gold() : SkString("") {}
     Gold(const SkString& sink, const SkString& src,
@@ -1491,7 +1332,10 @@
 
         if (bitmap) {
             SkASSERT(hashAndEncode);
-            if (!hashAndEncode->writePngTo(path.c_str(), result.md5.c_str())) {
+            if (!hashAndEncode->writePngTo(path.c_str(),
+                                           result.md5.c_str(),
+                                           FLAGS_key,
+                                           FLAGS_properties)) {
                 fail(SkStringPrintf("Can't encode PNG to %s.\n", path.c_str()));
                 return;
             }
diff --git a/gm/drawimageset.cpp b/gm/drawimageset.cpp
index d687958..edd27b1 100644
--- a/gm/drawimageset.cpp
+++ b/gm/drawimageset.cpp
@@ -121,9 +121,9 @@
         SkAssertResult(matrices[3].setPolyToPoly(src, dst, 4));
         matrices[3].postTranslate(100.f, d);
         for (auto fm : {kNone_SkFilterQuality, kLow_SkFilterQuality}) {
-            SkPaint paint;
-            paint.setFilterQuality(fm);
-            paint.setBlendMode(SkBlendMode::kSrcOver);
+            SkPaint setPaint;
+            setPaint.setFilterQuality(fm);
+            setPaint.setBlendMode(SkBlendMode::kSrcOver);
 
             for (size_t m = 0; m < SK_ARRAY_COUNT(matrices); ++m) {
                 // Draw grid of red lines at interior tile boundaries.
@@ -149,7 +149,7 @@
                 }
                 canvas->save();
                 canvas->concat(matrices[m]);
-                canvas->experimental_DrawEdgeAAImageSet(fSet, kM * kN, nullptr, nullptr, &paint,
+                canvas->experimental_DrawEdgeAAImageSet(fSet, kM * kN, nullptr, nullptr, &setPaint,
                                                         SkCanvas::kFast_SrcRectConstraint);
                 canvas->restore();
             }
@@ -164,8 +164,8 @@
             canvas->save();
             canvas->rotate(3.f);
 
-            paint.setBlendMode(SkBlendMode::kExclusion);
-            canvas->experimental_DrawEdgeAAImageSet(&entry, 1, nullptr, nullptr, &paint,
+            setPaint.setBlendMode(SkBlendMode::kExclusion);
+            canvas->experimental_DrawEdgeAAImageSet(&entry, 1, nullptr, nullptr, &setPaint,
                                                     SkCanvas::kFast_SrcRectConstraint);
             canvas->restore();
             canvas->translate(2 * d, 0);
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index 09f3ca4..72aa9c8 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -283,6 +283,9 @@
 
     void storeVkPipelineCacheData();
 
+    static size_t ComputeTextureSize(SkColorType type, int width, int height, GrMipMapped,
+                                     bool useNextPow2 = false);
+
 protected:
     GrContext(GrBackendApi, const GrContextOptions&, int32_t contextID = SK_InvalidGenID);
 
diff --git a/infra/bots/assets/go_deps/VERSION b/infra/bots/assets/go_deps/VERSION
index 681cf04..725cdcd 100644
--- a/infra/bots/assets/go_deps/VERSION
+++ b/infra/bots/assets/go_deps/VERSION
@@ -1 +1 @@
-192
\ No newline at end of file
+193
\ No newline at end of file
diff --git a/infra/bots/assets/skp/VERSION b/infra/bots/assets/skp/VERSION
index 12e2555..cde50ca 100644
--- a/infra/bots/assets/skp/VERSION
+++ b/infra/bots/assets/skp/VERSION
@@ -1 +1 @@
-177
\ No newline at end of file
+179
\ No newline at end of file
diff --git a/infra/bots/tasks.json b/infra/bots/tasks.json
index 8780d92..54ceec8 100755
--- a/infra/bots/tasks.json
+++ b/infra/bots/tasks.json
@@ -21086,7 +21086,7 @@
         {
           "name": "skia/bots/go_deps",
           "path": "go_deps",
-          "version": "version:192"
+          "version": "version:193"
         }
       ],
       "command": [
@@ -21109,7 +21109,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         }
       ],
       "command": [
@@ -29222,7 +29222,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -29334,7 +29334,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -29446,7 +29446,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -29563,7 +29563,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -29675,7 +29675,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -29792,7 +29792,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -29904,7 +29904,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30016,7 +30016,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30128,7 +30128,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30245,7 +30245,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30357,7 +30357,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30469,7 +30469,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30581,7 +30581,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30698,7 +30698,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30810,7 +30810,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -30921,7 +30921,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31032,7 +31032,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31148,7 +31148,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31269,7 +31269,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31385,7 +31385,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31506,7 +31506,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31622,7 +31622,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31743,7 +31743,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31859,7 +31859,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -31975,7 +31975,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -32091,7 +32091,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -32597,7 +32597,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -32709,7 +32709,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -32821,7 +32821,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -32932,7 +32932,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33043,7 +33043,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33154,7 +33154,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33265,7 +33265,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33376,7 +33376,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33487,7 +33487,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33598,7 +33598,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33709,7 +33709,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33820,7 +33820,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -33931,7 +33931,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34042,7 +34042,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34154,7 +34154,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34266,7 +34266,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34378,7 +34378,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34489,7 +34489,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34600,7 +34600,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34711,7 +34711,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34823,7 +34823,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -34940,7 +34940,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35057,7 +35057,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35169,7 +35169,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35286,7 +35286,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35403,7 +35403,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35526,7 +35526,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35642,7 +35642,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35758,7 +35758,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35874,7 +35874,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -35990,7 +35990,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36106,7 +36106,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36222,7 +36222,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36338,7 +36338,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36454,7 +36454,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36570,7 +36570,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36686,7 +36686,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36803,7 +36803,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -36920,7 +36920,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -37037,7 +37037,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -37154,7 +37154,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -37271,7 +37271,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -37697,7 +37697,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -37813,7 +37813,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -37929,7 +37929,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38045,7 +38045,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38161,7 +38161,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38277,7 +38277,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38393,7 +38393,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38509,7 +38509,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38625,7 +38625,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38741,7 +38741,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38857,7 +38857,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -38973,7 +38973,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39089,7 +39089,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39205,7 +39205,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39321,7 +39321,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39437,7 +39437,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39553,7 +39553,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39669,7 +39669,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39785,7 +39785,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -39901,7 +39901,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40017,7 +40017,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40133,7 +40133,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40249,7 +40249,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40365,7 +40365,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40481,7 +40481,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40597,7 +40597,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40713,7 +40713,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40829,7 +40829,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -40945,7 +40945,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41061,7 +41061,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41177,7 +41177,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41293,7 +41293,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41409,7 +41409,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41525,7 +41525,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41641,7 +41641,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41757,7 +41757,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41873,7 +41873,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -41989,7 +41989,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42105,7 +42105,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42222,7 +42222,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42339,7 +42339,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42456,7 +42456,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42573,7 +42573,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42691,7 +42691,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42809,7 +42809,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -42927,7 +42927,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43045,7 +43045,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43163,7 +43163,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43281,7 +43281,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43399,7 +43399,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43515,7 +43515,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43631,7 +43631,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -43747,7 +43747,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -54450,7 +54450,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -54562,7 +54562,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -54674,7 +54674,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -54791,7 +54791,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -54903,7 +54903,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55020,7 +55020,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55132,7 +55132,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55244,7 +55244,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55356,7 +55356,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55468,7 +55468,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55580,7 +55580,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55697,7 +55697,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55809,7 +55809,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -55921,7 +55921,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56033,7 +56033,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56145,7 +56145,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56257,7 +56257,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56369,7 +56369,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56486,7 +56486,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56597,7 +56597,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56708,7 +56708,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56820,7 +56820,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -56932,7 +56932,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57048,7 +57048,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57169,7 +57169,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57285,7 +57285,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57406,7 +57406,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57519,7 +57519,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57635,7 +57635,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57751,7 +57751,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57872,7 +57872,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -57988,7 +57988,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58109,7 +58109,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58235,7 +58235,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58356,7 +58356,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58482,7 +58482,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58603,7 +58603,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58719,7 +58719,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58840,7 +58840,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -58966,7 +58966,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59087,7 +59087,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59213,7 +59213,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59334,7 +59334,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59455,7 +59455,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59571,7 +59571,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59687,7 +59687,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -59803,7 +59803,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60309,7 +60309,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60421,7 +60421,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60533,7 +60533,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60645,7 +60645,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60757,7 +60757,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60868,7 +60868,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -60979,7 +60979,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61090,7 +61090,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61201,7 +61201,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61312,7 +61312,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61423,7 +61423,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61534,7 +61534,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61645,7 +61645,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61756,7 +61756,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61867,7 +61867,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -61978,7 +61978,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62089,7 +62089,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62200,7 +62200,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62311,7 +62311,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62422,7 +62422,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62533,7 +62533,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62644,7 +62644,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62755,7 +62755,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62867,7 +62867,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -62979,7 +62979,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63091,7 +63091,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63202,7 +63202,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63313,7 +63313,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63424,7 +63424,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63535,7 +63535,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63646,7 +63646,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63762,7 +63762,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63873,7 +63873,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -63989,7 +63989,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64100,7 +64100,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64216,7 +64216,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64332,7 +64332,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64448,7 +64448,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64559,7 +64559,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64675,7 +64675,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64791,7 +64791,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -64907,7 +64907,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65028,7 +65028,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65139,7 +65139,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65255,7 +65255,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65372,7 +65372,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65489,7 +65489,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65611,7 +65611,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65727,7 +65727,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65843,7 +65843,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -65959,7 +65959,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66075,7 +66075,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66191,7 +66191,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66307,7 +66307,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66423,7 +66423,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66539,7 +66539,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66655,7 +66655,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66771,7 +66771,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -66887,7 +66887,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67003,7 +67003,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67119,7 +67119,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67235,7 +67235,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67356,7 +67356,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67472,7 +67472,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67588,7 +67588,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67704,7 +67704,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67820,7 +67820,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -67936,7 +67936,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68057,7 +68057,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68173,7 +68173,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68289,7 +68289,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68405,7 +68405,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68521,7 +68521,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68637,7 +68637,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68753,7 +68753,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68869,7 +68869,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -68985,7 +68985,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69101,7 +69101,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69217,7 +69217,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69333,7 +69333,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69449,7 +69449,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69565,7 +69565,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69681,7 +69681,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69797,7 +69797,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -69913,7 +69913,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70029,7 +70029,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70145,7 +70145,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70261,7 +70261,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70377,7 +70377,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70493,7 +70493,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70609,7 +70609,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70725,7 +70725,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70841,7 +70841,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -70957,7 +70957,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71073,7 +71073,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71189,7 +71189,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71305,7 +71305,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71421,7 +71421,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71537,7 +71537,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71653,7 +71653,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71769,7 +71769,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -71885,7 +71885,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72001,7 +72001,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72117,7 +72117,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72233,7 +72233,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72349,7 +72349,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72465,7 +72465,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72581,7 +72581,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72697,7 +72697,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72813,7 +72813,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -72929,7 +72929,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73045,7 +73045,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73161,7 +73161,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73277,7 +73277,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73393,7 +73393,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73509,7 +73509,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73625,7 +73625,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73743,7 +73743,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73861,7 +73861,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -73979,7 +73979,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74097,7 +74097,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74215,7 +74215,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74333,7 +74333,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74451,7 +74451,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74569,7 +74569,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74687,7 +74687,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74805,7 +74805,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -74923,7 +74923,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75041,7 +75041,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75159,7 +75159,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75277,7 +75277,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75395,7 +75395,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75511,7 +75511,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75627,7 +75627,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75743,7 +75743,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75859,7 +75859,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -75975,7 +75975,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -76091,7 +76091,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -76207,7 +76207,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -76323,7 +76323,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
@@ -76439,7 +76439,7 @@
         {
           "name": "skia/bots/skp",
           "path": "skp",
-          "version": "version:177"
+          "version": "version:179"
         },
         {
           "name": "skia/bots/svg",
diff --git a/infra/config/recipes.cfg b/infra/config/recipes.cfg
index 0dfd1cd..cd9a635 100644
--- a/infra/config/recipes.cfg
+++ b/infra/config/recipes.cfg
@@ -14,12 +14,12 @@
   "deps": {
     "depot_tools": {
       "branch": "master",
-      "revision": "5d732177c04f9235e9ec44a07890ebc4b5b22302",
+      "revision": "c74cce1e7a8c12695b82d25c9d24052a93325ce6",
       "url": "https://chromium.googlesource.com/chromium/tools/depot_tools.git"
     },
     "recipe_engine": {
       "branch": "master",
-      "revision": "a4f9a8b3ac3195aab9c10e1dfa15a46edc4fb190",
+      "revision": "b37679d2f44240b461114360ae38e0d974f44119",
       "url": "https://chromium.googlesource.com/infra/luci/recipes-py.git"
     }
   },
diff --git a/modules/skottie/src/SkottieLayer.cpp b/modules/skottie/src/SkottieLayer.cpp
index 03ca93b..222d252 100644
--- a/modules/skottie/src/SkottieLayer.cpp
+++ b/modules/skottie/src/SkottieLayer.cpp
@@ -501,7 +501,10 @@
 
 sk_sp<sksg::RenderNode> AnimationBuilder::attachLayer(const skjson::ObjectValue* jlayer,
                                                       AttachLayerContext* layerCtx) const {
-    if (!jlayer) return nullptr;
+    if (!jlayer || ParseDefault<bool>((*jlayer)["hd"], false)) {
+        // Ignore hidden layers.
+        return nullptr;
+    }
 
     const LayerInfo layer_info = {
         ParseDefault<float>((*jlayer)["ip"], 0.0f),
diff --git a/modules/skottie/src/SkottieShapeLayer.cpp b/modules/skottie/src/SkottieShapeLayer.cpp
index 50a6988..de9c655 100644
--- a/modules/skottie/src/SkottieShapeLayer.cpp
+++ b/modules/skottie/src/SkottieShapeLayer.cpp
@@ -563,6 +563,11 @@
             continue;
         }
 
+        if (ParseDefault<bool>((*shape)["hd"], false)) {
+            // Ignore hidden shapes.
+            continue;
+        }
+
         recs.push_back({ *shape, *info });
 
         switch (info->fShapeType) {
diff --git a/modules/skottie/tests/hidden-shapes-layers.json b/modules/skottie/tests/hidden-shapes-layers.json
new file mode 100644
index 0000000..6ee850d
--- /dev/null
+++ b/modules/skottie/tests/hidden-shapes-layers.json
@@ -0,0 +1 @@
+{"v":"5.4.4","fr":60,"ip":0,"op":300,"w":500,"h":500,"nm":"Hidden shapes and layers","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Hidden stroke","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[100,100,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"st","c":{"a":0,"k":[1,0,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":83,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":true},{"ty":"fl","c":{"a":0,"k":[0,1,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Hidden fill","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,102,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[50,50],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":true},{"ty":"st","c":{"a":0,"k":[0,1,0,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Hidden geometry","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[400,100,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":true},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,1,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Hidden group","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[100,250,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":true},{"ty":"fl","c":{"a":0,"k":[1,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":true},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":true},{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"a":0,"k":[100,100],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":0,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0,1,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":1,"nm":"Hidden layer","hd":true,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sw":100,"sh":100,"sc":"#ff0000","ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":1,"nm":"Visible layer","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[50,50,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"sw":100,"sh":100,"sc":"#00ff00","ip":0,"op":300,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file
diff --git a/public.bzl b/public.bzl
index 77b4cf0..037acb8 100644
--- a/public.bzl
+++ b/public.bzl
@@ -278,10 +278,14 @@
         ]
     return native.glob(["src/codec/*.cpp", "third_party/etc1/*.cpp", "third_party/gif/*.cpp"], exclude = exclude)
 
-# Platform-dependent SRCS for google3-default platform.
-BASE_SRCS_UNIX = struct(
+GL_SRCS_UNIX = struct(
     include = [
         "src/gpu/gl/GrGLMakeNativeInterface_none.cpp",
+    ],
+    exclude = [],
+)
+PORTS_SRCS_UNIX = struct(
+    include = [
         "src/ports/**/*.cpp",
         "src/ports/**/*.h",
     ],
@@ -305,10 +309,14 @@
     ],
 )
 
-# Platform-dependent SRCS for google3-default Android.
-BASE_SRCS_ANDROID = struct(
+GL_SRCS_ANDROID = struct(
     include = [
         "src/gpu/gl/android/*.cpp",
+    ],
+    exclude = [],
+)
+PORTS_SRCS_ANDROID = struct(
+    include = [
         "src/ports/**/*.cpp",
         "src/ports/**/*.h",
     ],
@@ -333,10 +341,14 @@
     ],
 )
 
-# Platform-dependent SRCS for google3-default iOS.
-BASE_SRCS_IOS = struct(
+GL_SRCS_IOS = struct(
     include = [
         "src/gpu/gl/iOS/GrGLMakeNativeInterface_iOS.cpp",
+    ],
+    exclude = [],
+)
+PORTS_SRCS_IOS = struct(
+    include = [
         "src/ports/**/*.cpp",
         "src/ports/**/*.h",
         "src/utils/mac/*.cpp",
@@ -365,19 +377,28 @@
     ],
 )
 
-################################################################################
-## skia_srcs()
-################################################################################
-def skia_srcs(os_conditions):
-    """Sources to be compiled into the skia library."""
-    return skia_glob(BASE_SRCS_ALL) + skia_select(
-        os_conditions,
+def base_srcs():
+    return skia_glob(BASE_SRCS_ALL)
+
+def ports_srcs(os_conditions):
+     return skia_select( os_conditions,
         [
-            skia_glob(BASE_SRCS_UNIX),
-            skia_glob(BASE_SRCS_ANDROID),
-            skia_glob(BASE_SRCS_IOS),
-        ],
-    )
+            skia_glob(PORTS_SRCS_UNIX),
+            skia_glob(PORTS_SRCS_ANDROID),
+            skia_glob(PORTS_SRCS_IOS),
+        ])
+
+def gl_srcs(os_conditions):
+   return skia_select(os_conditions,
+        [
+            skia_glob(GL_SRCS_UNIX),
+            skia_glob(GL_SRCS_ANDROID),
+            skia_glob(GL_SRCS_IOS),
+        ])
+
+def skia_srcs(os_conditions):
+    return base_srcs() + ports_srcs(os_conditions) + gl_srcs(os_conditions)
+
 
 ################################################################################
 ## INCLUDES
@@ -443,6 +464,8 @@
         "tools/DDLPromiseImageHelper.h",
         "tools/DDLTileHelper.cpp",
         "tools/DDLTileHelper.h",
+        "tools/HashAndEncode.cpp",
+        "tools/HashAndEncode.h",
         "tools/ProcStats.cpp",
         "tools/ProcStats.h",
         "tools/Registry.h",
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 9713beb..6e19511 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -214,6 +214,13 @@
     return fResourceCache->getPurgeableBytes();
 }
 
+size_t GrContext::ComputeTextureSize(SkColorType type, int width, int height, GrMipMapped mipMapped,
+                                     bool useNextPow2) {
+    int colorSamplesPerPixel = 1;
+    return GrSurface::ComputeSize(SkColorType2GrPixelConfig(type), width, height,
+                                  colorSamplesPerPixel, mipMapped, useNextPow2);
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 
 int GrContext::maxTextureSize() const { return this->caps()->maxTextureSize(); }
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 10da8f9..ae36031 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -285,7 +285,8 @@
     bool flushed = false;
 
     {
-        GrResourceAllocator alloc(resourceProvider, flushState.deinstantiateProxyTracker());
+        GrResourceAllocator alloc(resourceProvider, flushState.deinstantiateProxyTracker()
+                                  SkDEBUGCODE(, fDAG.numOpLists()));
         for (int i = 0; i < fDAG.numOpLists(); ++i) {
             if (fDAG.opList(i)) {
                 fDAG.opList(i)->gatherProxyIntervals(&alloc);
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index bab24ca..66300df 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -611,7 +611,6 @@
 }
 
 void GrRenderTargetOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
-    unsigned int cur = alloc->numOps();
 
     for (int i = 0; i < fDeferredProxies.count(); ++i) {
         SkASSERT(!fDeferredProxies[i]->isInstantiated());
@@ -625,23 +624,25 @@
 
     // Add the interval for all the writes to this opList's target
     if (fOpChains.count()) {
+        unsigned int cur = alloc->curOp();
+
         alloc->addInterval(fTarget.get(), cur, cur + fOpChains.count() - 1);
     } else {
         // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
         // still need to add an interval for the destination so we create a fake op# for
         // the missing clear op.
-        alloc->addInterval(fTarget.get());
+        alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp());
         alloc->incOps();
     }
 
     auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p) {
-        alloc->addInterval(p SkDEBUGCODE(, fTarget.get() == p));
+        alloc->addInterval(p, alloc->curOp(), alloc->curOp() SkDEBUGCODE(, fTarget.get() == p));
     };
     for (const OpChain& recordedOp : fOpChains) {
         // only diff from the GrTextureOpList version
         recordedOp.visitProxies(gather, GrOp::VisitorType::kAllocatorGather);
 
-        // Even though the op may have been moved we still need to increment the op count to
+        // Even though the op may have been (re)moved we still need to increment the op count to
         // keep all the math consistent.
         alloc->incOps();
     }
diff --git a/src/gpu/GrResourceAllocator.cpp b/src/gpu/GrResourceAllocator.cpp
index 0d3c34e..2142b06 100644
--- a/src/gpu/GrResourceAllocator.cpp
+++ b/src/gpu/GrResourceAllocator.cpp
@@ -47,6 +47,7 @@
     }
 
     fEndOfOpListOpIndices.push_back(this->curOp()); // This is the first op index of the next opList
+    SkASSERT(fEndOfOpListOpIndices.count() <= fNumOpLists);
 }
 
 GrResourceAllocator::~GrResourceAllocator() {
@@ -309,6 +310,34 @@
     }
 }
 
+bool GrResourceAllocator::onOpListBoundary() const {
+    if (fIntvlList.empty()) {
+        SkASSERT(fCurOpListIndex+1 <= fNumOpLists);
+        // Although technically on an opList boundary there is no need to force an
+        // intermediate flush here
+        return false;
+    }
+
+    const Interval* tmp = fIntvlList.peekHead();
+    return fEndOfOpListOpIndices[fCurOpListIndex] <= tmp->start();
+}
+
+void GrResourceAllocator::forceIntermediateFlush(int* stopIndex) {
+    *stopIndex = fCurOpListIndex+1;
+
+    // This is interrupting the allocation of resources for this flush. We need to
+    // proactively clear the active interval list of any intervals that aren't
+    // guaranteed to survive the partial flush lest they become zombies (i.e.,
+    // holding a deleted surface proxy).
+    const Interval* tmp = fIntvlList.peekHead();
+    SkASSERT(fEndOfOpListOpIndices[fCurOpListIndex] <= tmp->start());
+
+    fCurOpListIndex++;
+    SkASSERT(fCurOpListIndex < fNumOpLists);
+
+    this->expire(tmp->start());
+}
+
 bool GrResourceAllocator::assign(int* startIndex, int* stopIndex, AssignError* outError) {
     SkASSERT(outError);
     *outError = AssignError::kNoError;
@@ -318,9 +347,22 @@
         return false;          // nothing to render
     }
 
+    SkASSERT(fCurOpListIndex < fNumOpLists);
+    SkASSERT(fNumOpLists == fEndOfOpListOpIndices.count());
+
     *startIndex = fCurOpListIndex;
     *stopIndex = fEndOfOpListOpIndices.count();
 
+#if GR_ALLOCATION_SPEW
+    SkDebugf("assigning opLists %d through %d out of %d numOpLists\n",
+             *startIndex, *stopIndex, fNumOpLists);
+    SkDebugf("EndOfOpListIndices: ");
+    for (int i = 0; i < fEndOfOpListOpIndices.count(); ++i) {
+        SkDebugf("%d ", fEndOfOpListOpIndices[i]);
+    }
+    SkDebugf("\n");
+#endif
+
     if (!fResourceProvider->explicitlyAllocateGPUResources()) {
         fIntvlList.detachAll(); // arena allocator will clean these up for us
         return true;
@@ -332,8 +374,9 @@
     this->dumpIntervals();
 #endif
     while (Interval* cur = fIntvlList.popHead()) {
-        if (fEndOfOpListOpIndices[fCurOpListIndex] < cur->start()) {
+        if (fEndOfOpListOpIndices[fCurOpListIndex] <= cur->start()) {
             fCurOpListIndex++;
+            SkASSERT(fCurOpListIndex < fNumOpLists);
         }
 
         this->expire(cur->start());
@@ -352,19 +395,8 @@
 
             if (fResourceProvider->overBudget()) {
                 // Only force intermediate draws on opList boundaries
-                if (!fIntvlList.empty() &&
-                    fEndOfOpListOpIndices[fCurOpListIndex] < fIntvlList.peekHead()->start()) {
-                    *stopIndex = fCurOpListIndex+1;
-
-                    // This is interrupting the allocation of resources for this flush. We need to
-                    // proactively clear the active interval list of any intervals that aren't
-                    // guaranteed to survive the partial flush lest they become zombies (i.e.,
-                    // holding a deleted surface proxy).
-                    if (const Interval* tmp = fIntvlList.peekHead()) {
-                        this->expire(tmp->start());
-                    } else {
-                        this->expire(std::numeric_limits<unsigned int>::max());
-                    }
+                if (this->onOpListBoundary()) {
+                    this->forceIntermediateFlush(stopIndex);
                     return true;
                 }
             }
@@ -409,19 +441,8 @@
 
         if (fResourceProvider->overBudget()) {
             // Only force intermediate draws on opList boundaries
-            if (!fIntvlList.empty() &&
-                fEndOfOpListOpIndices[fCurOpListIndex] < fIntvlList.peekHead()->start()) {
-                *stopIndex = fCurOpListIndex+1;
-
-                // This is interrupting the allocation of resources for this flush. We need to
-                // proactively clear the active interval list of any intervals that aren't
-                // guaranteed to survive the partial flush lest they become zombies (i.e.,
-                // holding a deleted surface proxy).
-                if (const Interval* tmp = fIntvlList.peekHead()) {
-                    this->expire(tmp->start());
-                } else {
-                    this->expire(std::numeric_limits<unsigned int>::max());
-                }
+            if (this->onOpListBoundary()) {
+                this->forceIntermediateFlush(stopIndex);
                 return true;
             }
         }
@@ -434,9 +455,9 @@
 
 #if GR_ALLOCATION_SPEW
 void GrResourceAllocator::dumpIntervals() {
-
     // Print all the intervals while computing their range
-    unsigned int min = fNumOps+1;
+    SkDebugf("------------------------------------------------------------\n");
+    unsigned int min = std::numeric_limits<unsigned int>::max();
     unsigned int max = 0;
     for(const Interval* cur = fIntvlList.peekHead(); cur; cur = cur->next()) {
         SkDebugf("{ %3d,%3d }: [%2d, %2d] - proxyRefs:%d surfaceRefs:%d R:%d W:%d\n",
diff --git a/src/gpu/GrResourceAllocator.h b/src/gpu/GrResourceAllocator.h
index ea1250f..fabaf00 100644
--- a/src/gpu/GrResourceAllocator.h
+++ b/src/gpu/GrResourceAllocator.h
@@ -42,27 +42,24 @@
  */
 class GrResourceAllocator {
 public:
-    GrResourceAllocator(GrResourceProvider* resourceProvider, GrDeinstantiateProxyTracker* tracker)
-            : fResourceProvider(resourceProvider), fDeinstantiateTracker(tracker) {}
+    GrResourceAllocator(GrResourceProvider* resourceProvider,
+                        GrDeinstantiateProxyTracker* tracker
+                        SkDEBUGCODE(, int numOpLists))
+            : fResourceProvider(resourceProvider)
+            , fDeinstantiateTracker(tracker)
+            SkDEBUGCODE(, fNumOpLists(numOpLists)) {
+    }
 
     ~GrResourceAllocator();
 
     unsigned int curOp() const { return fNumOps; }
     void incOps() { fNumOps++; }
-    unsigned int numOps() const { return fNumOps; }
 
     // Add a usage interval from 'start' to 'end' inclusive. This is usually used for renderTargets.
     // If an existing interval already exists it will be expanded to include the new range.
     void addInterval(GrSurfaceProxy*, unsigned int start, unsigned int end
                      SkDEBUGCODE(, bool isDirectDstRead = false));
 
-    // Add an interval that spans just the current op. Usually this is for texture uses.
-    // If an existing interval already exists it will be expanded to include the new operation.
-    void addInterval(GrSurfaceProxy* proxy
-                     SkDEBUGCODE(, bool isDirectDstRead = false)) {
-        this->addInterval(proxy, fNumOps, fNumOps SkDEBUGCODE(, isDirectDstRead));
-    }
-
     enum class AssignError {
         kNoError,
         kFailedProxyInstantiation
@@ -88,6 +85,9 @@
     // Remove dead intervals from the active list
     void expire(unsigned int curIndex);
 
+    bool onOpListBoundary() const;
+    void forceIntermediateFlush(int* stopIndex);
+
     // These two methods wrap the interactions with the free pool
     void recycleSurface(sk_sp<GrSurface> surface);
     sk_sp<GrSurface> findSurfaceFor(const GrSurfaceProxy* proxy, bool needsStencil);
@@ -218,11 +218,11 @@
 
     IntervalList                 fIntvlList;         // All the intervals sorted by increasing start
     IntervalList                 fActiveIntvls;      // List of live intervals during assignment
-                                               // (sorted by increasing end)
-    unsigned int                 fNumOps = 1;        // op # 0 is reserved for uploads at the start
-                                               // of a flush
+                                                     // (sorted by increasing end)
+    unsigned int                 fNumOps = 0;
     SkTArray<unsigned int>       fEndOfOpListOpIndices;
     int                          fCurOpListIndex = 0;
+    SkDEBUGCODE(const int        fNumOpLists = -1;)
 
     SkDEBUGCODE(bool             fAssigned = false;)
 
diff --git a/src/gpu/GrTextureOpList.cpp b/src/gpu/GrTextureOpList.cpp
index ba07add..2d93f77 100644
--- a/src/gpu/GrTextureOpList.cpp
+++ b/src/gpu/GrTextureOpList.cpp
@@ -181,21 +181,22 @@
 }
 
 void GrTextureOpList::gatherProxyIntervals(GrResourceAllocator* alloc) const {
-    unsigned int cur = alloc->numOps();
 
     // Add the interval for all the writes to this opList's target
     if (fRecordedOps.count()) {
+        unsigned int cur = alloc->curOp();
+
         alloc->addInterval(fTarget.get(), cur, cur+fRecordedOps.count()-1);
     } else {
         // This can happen if there is a loadOp (e.g., a clear) but no other draws. In this case we
         // still need to add an interval for the destination so we create a fake op# for
         // the missing clear op.
-        alloc->addInterval(fTarget.get());
+        alloc->addInterval(fTarget.get(), alloc->curOp(), alloc->curOp());
         alloc->incOps();
     }
 
     auto gather = [ alloc SkDEBUGCODE(, this) ] (GrSurfaceProxy* p) {
-        alloc->addInterval(p SkDEBUGCODE(, p == fTarget.get()));
+        alloc->addInterval(p, alloc->curOp(), alloc->curOp() SkDEBUGCODE(, p == fTarget.get()));
     };
     for (int i = 0; i < fRecordedOps.count(); ++i) {
         const GrOp* op = fRecordedOps[i].get(); // only diff from the GrRenderTargetOpList version
@@ -203,7 +204,7 @@
             op->visitProxies(gather, GrOp::VisitorType::kAllocatorGather);
         }
 
-        // Even though the op may have been moved we still need to increment the op count to
+        // Even though the op may have been (re)moved we still need to increment the op count to
         // keep all the math consistent.
         alloc->incOps();
     }
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 80121fe..df8e60e 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1417,7 +1417,13 @@
     if (fDriverBugWorkarounds.disable_texture_storage) {
         texStorageSupported = false;
     }
-
+#ifdef SK_BUILD_FOR_ANDROID
+    // crbug.com/945506. Telemetry reported a memory usage regression for Android Go Chrome/WebView
+    // when using glTexStorage2D.
+    if (ctxInfo.driver() == kChromium_GrGLDriver) {
+        texStorageSupported = false;
+    }
+#endif
     bool textureRedSupport = false;
 
     if (!disableTextureRedForMesa) {
diff --git a/tests/ResourceAllocatorTest.cpp b/tests/ResourceAllocatorTest.cpp
index a71221d..0a1a19a 100644
--- a/tests/ResourceAllocatorTest.cpp
+++ b/tests/ResourceAllocatorTest.cpp
@@ -28,6 +28,7 @@
     SkBackingFit    fFit;
     int             fSampleCnt;
     GrSurfaceOrigin fOrigin;
+    SkBudgeted      fBudgeted;
     // TODO: do we care about mipmapping
 };
 
@@ -45,7 +46,7 @@
 
     const GrBackendFormat format = caps->getBackendFormatFromColorType(p.fColorType);
 
-    auto tmp = proxyProvider->createProxy(format, desc, p.fOrigin, p.fFit, SkBudgeted::kNo);
+    auto tmp = proxyProvider->createProxy(format, desc, p.fOrigin, p.fFit, p.fBudgeted);
     if (!tmp) {
         return nullptr;
     }
@@ -91,10 +92,12 @@
 static void overlap_test(skiatest::Reporter* reporter, GrResourceProvider* resourceProvider,
                          GrSurfaceProxy* p1, GrSurfaceProxy* p2, bool expectedResult) {
     GrDeinstantiateProxyTracker deinstantiateTracker;
-    GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker);
+    GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker SkDEBUGCODE(, 1));
 
     alloc.addInterval(p1, 0, 4);
+    alloc.incOps();
     alloc.addInterval(p2, 1, 2);
+    alloc.incOps();
     alloc.markEndOfOpList(0);
 
     int startIndex, stopIndex;
@@ -114,7 +117,14 @@
                              GrSurfaceProxy* p1, GrSurfaceProxy* p2,
                              bool expectedResult) {
     GrDeinstantiateProxyTracker deinstantiateTracker;
-    GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker);
+    GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker SkDEBUGCODE(, 1));
+
+    alloc.incOps();
+    alloc.incOps();
+    alloc.incOps();
+    alloc.incOps();
+    alloc.incOps();
+    alloc.incOps();
 
     alloc.addInterval(p1, 0, 2);
     alloc.addInterval(p2, 3, 5);
@@ -167,14 +177,16 @@
     const GrSurfaceOrigin kTL = kTopLeft_GrSurfaceOrigin;
     const GrSurfaceOrigin kBL = kBottomLeft_GrSurfaceOrigin;
 
+    const SkBudgeted kNotB = SkBudgeted::kNo;
+
     //--------------------------------------------------------------------------------------------
     TestCase gOverlappingTests[] = {
         //----------------------------------------------------------------------------------------
         // Two proxies with overlapping intervals and compatible descriptors should never share
         // RT version
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kDontShare },
+        { { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, kDontShare },
         // non-RT version
-        { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
+        { { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, kDontShare },
     };
 
     for (auto test : gOverlappingTests) {
@@ -195,28 +207,28 @@
         //----------------------------------------------------------------------------------------
         // Two non-overlapping intervals w/ compatible proxies should share
         // both same size & approx
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kShare },
-        { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
+        { { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, kShare },
+        { { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, kConditionallyShare },
         // diffs sizes but still approx
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 50,    kRT, kRGBA, kA, 0, kTL }, kShare },
-        { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 50, kNotRT, kRGBA, kA, 0, kTL }, kConditionallyShare },
+        { { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, { 50,    kRT, kRGBA, kA, 0, kTL, kNotB }, kShare },
+        { { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, { 50, kNotRT, kRGBA, kA, 0, kTL, kNotB }, kConditionallyShare },
         // sames sizes but exact
-        { { 64,    kRT, kRGBA, kE, 0, kTL }, { 64,    kRT, kRGBA, kE, 0, kTL }, kShare },
-        { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kConditionallyShare },
+        { { 64,    kRT, kRGBA, kE, 0, kTL, kNotB }, { 64,    kRT, kRGBA, kE, 0, kTL, kNotB }, kShare },
+        { { 64, kNotRT, kRGBA, kE, 0, kTL, kNotB }, { 64, kNotRT, kRGBA, kE, 0, kTL, kNotB }, kConditionallyShare },
         //----------------------------------------------------------------------------------------
         // Two non-overlapping intervals w/ different exact sizes should not share
-        { { 56,    kRT, kRGBA, kE, 0, kTL }, { 54,    kRT, kRGBA, kE, 0, kTL }, kDontShare },
+        { { 56,    kRT, kRGBA, kE, 0, kTL, kNotB }, { 54,    kRT, kRGBA, kE, 0, kTL, kNotB }, kDontShare },
         // Two non-overlapping intervals w/ _very different_ approx sizes should not share
-        { { 255,   kRT, kRGBA, kA, 0, kTL }, { 127,   kRT, kRGBA, kA, 0, kTL }, kDontShare },
+        { { 255,   kRT, kRGBA, kA, 0, kTL, kNotB }, { 127,   kRT, kRGBA, kA, 0, kTL, kNotB }, kDontShare },
         // Two non-overlapping intervals w/ different MSAA sample counts should not share
-        { { 64,    kRT, kRGBA, kA, k2, kTL },{ 64,    kRT, kRGBA, kA, k4, kTL}, k2 == k4 },
+        { { 64,    kRT, kRGBA, kA, k2, kTL, kNotB },{ 64,    kRT, kRGBA, kA, k4,kTL, kNotB}, k2 == k4 },
         // Two non-overlapping intervals w/ different configs should not share
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kBGRA, kA, 0, kTL }, kDontShare },
+        { { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, { 64,    kRT, kBGRA, kA, 0, kTL, kNotB }, kDontShare },
         // Two non-overlapping intervals w/ different RT classifications should never share
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64, kNotRT, kRGBA, kA, 0, kTL }, kDontShare },
-        { { 64, kNotRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kTL }, kDontShare },
+        { { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, kDontShare },
+        { { 64, kNotRT, kRGBA, kA, 0, kTL, kNotB }, { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, kDontShare },
         // Two non-overlapping intervals w/ different origins should share
-        { { 64,    kRT, kRGBA, kA, 0, kTL }, { 64,    kRT, kRGBA, kA, 0, kBL }, kShare },
+        { { 64,    kRT, kRGBA, kA, 0, kTL, kNotB }, { 64,    kRT, kRGBA, kA, 0, kBL, kNotB }, kShare },
     };
 
     for (auto test : gNonOverlappingTests) {
@@ -236,7 +248,7 @@
     {
         // Wrapped backend textures should never be reused
         TestCase t[1] = {
-            { { 64, kNotRT, kRGBA, kE, 0, kTL }, { 64, kNotRT, kRGBA, kE, 0, kTL }, kDontShare }
+            { { 64, kNotRT, kRGBA, kE, 0, kTL, kNotB }, { 64, kNotRT, kRGBA, kE, 0, kTL, kNotB }, kDontShare }
         };
 
         GrBackendTexture backEndTex;
@@ -315,7 +327,7 @@
                                   : GrSurfaceProxy::LazyInstantiationType ::kSingleUse;
     GrInternalSurfaceFlags flags = GrInternalSurfaceFlags::kNone;
     return proxyProvider->createLazyProxy(callback, format, desc, p.fOrigin, GrMipMapped::kNo,
-                                          flags, p.fFit, SkBudgeted::kNo, lazyType);
+                                          flags, p.fFit, p.fBudgeted, lazyType);
 }
 
 DEF_GPUTEST_FOR_RENDERING_CONTEXTS(LazyDeinstantiation, reporter, ctxInfo) {
@@ -330,6 +342,7 @@
         texParams.fIsRT = false;
         texParams.fSampleCnt = 1;
         texParams.fSize = 100;
+        texParams.fBudgeted = SkBudgeted::kNo;
         ProxyParams rtParams = texParams;
         rtParams.fIsRT = true;
         auto proxyProvider = context->priv().proxyProvider();
@@ -342,11 +355,12 @@
 
         GrDeinstantiateProxyTracker deinstantiateTracker;
         {
-            GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker);
+            GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker SkDEBUGCODE(, 1));
             alloc.addInterval(p0.get(), 0, 1);
             alloc.addInterval(p1.get(), 0, 1);
             alloc.addInterval(p2.get(), 0, 1);
             alloc.addInterval(p3.get(), 0, 1);
+            alloc.incOps();
             alloc.markEndOfOpList(0);
             int startIndex, stopIndex;
             GrResourceAllocator::AssignError error;
@@ -359,3 +373,67 @@
         REPORTER_ASSERT(reporter, p3->isInstantiated());
     }
 }
+
+// Set up so there are two opLists that need to be flushed but the resource allocator thinks
+// it is over budget. The two opLists should be flushed separately and the opList indices
+// returned from assign should be correct.
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ResourceAllocatorOverBudgetTest, reporter, ctxInfo) {
+    GrContext* context = ctxInfo.grContext();
+    const GrCaps* caps = context->priv().caps();
+    GrProxyProvider* proxyProvider = context->priv().proxyProvider();
+    GrResourceProvider* resourceProvider = context->priv().resourceProvider();
+
+    bool orig = resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(true);
+
+    int origMaxNum;
+    size_t origMaxBytes;
+    context->getResourceCacheLimits(&origMaxNum, &origMaxBytes);
+
+    // Force the resource allocator to always believe it is over budget
+    context->setResourceCacheLimits(0, 0);
+
+    const ProxyParams params  = { 64, false, kRGBA_8888_SkColorType,
+                                  SkBackingFit::kExact, 0, kTopLeft_GrSurfaceOrigin,
+                                  SkBudgeted::kYes };
+
+    {
+        GrSurfaceProxy* p1 = make_deferred(proxyProvider, caps, params);
+        GrSurfaceProxy* p2 = make_deferred(proxyProvider, caps, params);
+        GrSurfaceProxy* p3 = make_deferred(proxyProvider, caps, params);
+        GrSurfaceProxy* p4 = make_deferred(proxyProvider, caps, params);
+
+        GrDeinstantiateProxyTracker deinstantiateTracker;
+        GrResourceAllocator alloc(resourceProvider, &deinstantiateTracker SkDEBUGCODE(, 2));
+
+        alloc.addInterval(p1, 0, 0);
+        alloc.incOps();
+        alloc.addInterval(p2, 1, 1);
+        alloc.incOps();
+        alloc.markEndOfOpList(0);
+
+        alloc.addInterval(p3, 2, 2);
+        alloc.incOps();
+        alloc.addInterval(p4, 3, 3);
+        alloc.incOps();
+        alloc.markEndOfOpList(1);
+
+        int startIndex, stopIndex;
+        GrResourceAllocator::AssignError error;
+
+        alloc.assign(&startIndex, &stopIndex, &error);
+        REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
+        REPORTER_ASSERT(reporter, 0 == startIndex && 1 == stopIndex);
+
+        alloc.assign(&startIndex, &stopIndex, &error);
+        REPORTER_ASSERT(reporter, GrResourceAllocator::AssignError::kNoError == error);
+        REPORTER_ASSERT(reporter, 1 == startIndex && 2 == stopIndex);
+
+        p1->completedRead();
+        p2->completedRead();
+        p3->completedRead();
+        p4->completedRead();
+    }
+
+    context->setResourceCacheLimits(origMaxNum, origMaxBytes);
+    resourceProvider->testingOnly_setExplicitlyAllocateGPUResources(orig);
+}
diff --git a/tools/HashAndEncode.cpp b/tools/HashAndEncode.cpp
new file mode 100644
index 0000000..91814fc
--- /dev/null
+++ b/tools/HashAndEncode.cpp
@@ -0,0 +1,160 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "HashAndEncode.h"
+#include "SkICC.h"
+#include "SkString.h"
+#include "png.h"
+
+static constexpr skcms_TransferFunction k2020_TF =
+    {2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0};
+
+static sk_sp<SkColorSpace> rec2020() {
+    return SkColorSpace::MakeRGB(k2020_TF, SkNamedGamut::kRec2020);
+}
+
+HashAndEncode::HashAndEncode(const SkBitmap& bitmap) : fSize(bitmap.info().dimensions()) {
+    skcms_AlphaFormat srcAlpha;
+    switch (bitmap.alphaType()) {
+        case kUnknown_SkAlphaType: SkASSERT(false); return;
+
+        case kOpaque_SkAlphaType:
+        case kUnpremul_SkAlphaType: srcAlpha = skcms_AlphaFormat_Unpremul;        break;
+        case kPremul_SkAlphaType:   srcAlpha = skcms_AlphaFormat_PremulAsEncoded; break;
+    }
+
+    skcms_PixelFormat srcFmt;
+    switch (bitmap.colorType()) {
+        case kUnknown_SkColorType: SkASSERT(false); return;
+
+        case kAlpha_8_SkColorType:      srcFmt = skcms_PixelFormat_A_8;          break;
+        case kRGB_565_SkColorType:      srcFmt = skcms_PixelFormat_BGR_565;      break;
+        case kARGB_4444_SkColorType:    srcFmt = skcms_PixelFormat_ABGR_4444;    break;
+        case kRGBA_8888_SkColorType:    srcFmt = skcms_PixelFormat_RGBA_8888;    break;
+        case kBGRA_8888_SkColorType:    srcFmt = skcms_PixelFormat_BGRA_8888;    break;
+        case kRGBA_1010102_SkColorType: srcFmt = skcms_PixelFormat_RGBA_1010102; break;
+        case kGray_8_SkColorType:       srcFmt = skcms_PixelFormat_G_8;          break;
+        case kRGBA_F16Norm_SkColorType: srcFmt = skcms_PixelFormat_RGBA_hhhh;    break;
+        case kRGBA_F16_SkColorType:     srcFmt = skcms_PixelFormat_RGBA_hhhh;    break;
+        case kRGBA_F32_SkColorType:     srcFmt = skcms_PixelFormat_RGBA_ffff;    break;
+
+        case kRGB_888x_SkColorType:     srcFmt = skcms_PixelFormat_RGBA_8888;
+                                        srcAlpha = skcms_AlphaFormat_Opaque;       break;
+        case kRGB_101010x_SkColorType:  srcFmt = skcms_PixelFormat_RGBA_1010102;
+                                        srcAlpha = skcms_AlphaFormat_Opaque;       break;
+    }
+
+    skcms_ICCProfile srcProfile = *skcms_sRGB_profile();
+    if (auto cs = bitmap.colorSpace()) {
+        cs->toProfile(&srcProfile);
+    }
+
+    // Our common format that can represent anything we draw and encode as a PNG:
+    //   - 16-bit big-endian RGBA
+    //   - unpremul
+    //   - Rec. 2020 gamut and transfer function
+    skcms_PixelFormat dstFmt   = skcms_PixelFormat_RGBA_16161616BE;
+    skcms_AlphaFormat dstAlpha = skcms_AlphaFormat_Unpremul;
+    skcms_ICCProfile dstProfile;
+    rec2020()->toProfile(&dstProfile);
+
+    int N = fSize.width() * fSize.height();
+    fPixels.reset(new uint64_t[N]);
+
+    if (!skcms_Transform(bitmap.getPixels(), srcFmt, srcAlpha, &srcProfile,
+                         fPixels.get(),      dstFmt, dstAlpha, &dstProfile, N)) {
+        SkASSERT(false);
+        fPixels.reset(nullptr);
+    }
+}
+
+void HashAndEncode::write(SkWStream* st) const {
+    st->write(&fSize, sizeof(fSize));
+    if (const uint64_t* px = fPixels.get()) {
+        st->write(px, sizeof(*px) * fSize.width() * fSize.height());
+    }
+
+    // N.B. changing salt will change the hash of all images produced by DM,
+    // and will cause tens of thousands of new images to be uploaded to Gold.
+    int salt = 1;
+    st->write(&salt, sizeof(salt));
+}
+
+bool HashAndEncode::writePngTo(const char* path,
+                               const char* md5,
+                               CommandLineFlags::StringArray key,
+                               CommandLineFlags::StringArray properties) const {
+    if (!fPixels) {
+        return false;
+    }
+
+    FILE* f = fopen(path, "wb");
+    if (!f) {
+        return false;
+    }
+
+    png_structp png = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
+    if (!png) {
+        fclose(f);
+        return false;
+    }
+
+    png_infop info = png_create_info_struct(png);
+    if (!info) {
+        png_destroy_write_struct(&png, &info);
+        fclose(f);
+        return false;
+    }
+
+    SkString description;
+    description.append("Key: ");
+    for (int i = 0; i < key.count(); i++) {
+        description.appendf("%s ", key[i]);
+    }
+    description.append("Properties: ");
+    for (int i = 0; i < properties.count(); i++) {
+        description.appendf("%s ", properties[i]);
+    }
+    description.appendf("MD5: %s", md5);
+
+    png_text text[2];
+    text[0].key  = (png_charp)"Author";
+    text[0].text = (png_charp)"DM unified Rec.2020";
+    text[0].compression = PNG_TEXT_COMPRESSION_NONE;
+    text[1].key  = (png_charp)"Description";
+    text[1].text = (png_charp)description.c_str();
+    text[1].compression = PNG_TEXT_COMPRESSION_NONE;
+    png_set_text(png, info, text, SK_ARRAY_COUNT(text));
+
+    png_init_io(png, f);
+    png_set_IHDR(png, info, (png_uint_32)fSize.width()
+                          , (png_uint_32)fSize.height()
+                          , 16/*bits per channel*/
+                          , PNG_COLOR_TYPE_RGB_ALPHA
+                          , PNG_INTERLACE_NONE
+                          , PNG_COMPRESSION_TYPE_DEFAULT
+                          , PNG_FILTER_TYPE_DEFAULT);
+
+    // Fastest encoding and decoding, at slight file size cost is no filtering, compression 1.
+    png_set_filter(png, PNG_FILTER_TYPE_BASE, PNG_FILTER_NONE);
+    // TODO(mtklein): set back to 1 after all the bots have cycled through new images / hashes?
+    png_set_compression_level(png, 9);
+
+    static const sk_sp<SkData> profile = SkWriteICCProfile(k2020_TF, SkNamedGamut::kRec2020);
+    png_set_iCCP(png, info,
+                 "Rec.2020",
+                 0/*compression type... no idea what options are available here*/,
+                 (png_const_bytep)profile->data(),
+                 (png_uint_32)    profile->size());
+
+    png_write_info(png, info);
+    for (int y = 0; y < fSize.height(); y++) {
+        png_write_row(png, (png_bytep)(fPixels.get() + y*fSize.width()));
+    }
+    png_write_end(png, info);
+
+    png_destroy_write_struct(&png, &info);
+    fclose(f);
+    return true;
+}
+
diff --git a/tools/HashAndEncode.h b/tools/HashAndEncode.h
new file mode 100644
index 0000000..e3808fc
--- /dev/null
+++ b/tools/HashAndEncode.h
@@ -0,0 +1,25 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#pragma once
+
+#include "CommandLineFlags.h"
+#include "SkBitmap.h"
+#include "SkStream.h"
+
+class HashAndEncode {
+public:
+    explicit HashAndEncode(const SkBitmap&);
+
+    void write(SkWStream*) const;
+
+    bool writePngTo(const char* path,
+                    const char* md5,
+                    CommandLineFlags::StringArray key,
+                    CommandLineFlags::StringArray properties) const;
+
+private:
+    const SkISize               fSize;
+    std::unique_ptr<uint64_t[]> fPixels;
+};
+
diff --git a/tools/fm/fm.cpp b/tools/fm/fm.cpp
new file mode 100644
index 0000000..2b6ebca
--- /dev/null
+++ b/tools/fm/fm.cpp
@@ -0,0 +1,435 @@
+// Copyright 2019 Google LLC.
+// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
+
+#include "CommandLineFlags.h"
+#include "CommonFlags.h"
+#include "EventTracingPriv.h"
+#include "GrContextFactory.h"
+#include "GrContextOptions.h"
+#include "GrContextPriv.h"
+#include "GrGpu.h"
+#include "HashAndEncode.h"
+#include "SkCodec.h"
+#include "SkColorSpace.h"
+#include "SkColorSpacePriv.h"
+#include "SkGraphics.h"
+#include "SkMD5.h"
+#include "SkOSFile.h"
+#include "SkOSPath.h"
+#include "SkPicture.h"
+#include "ToolUtils.h"
+#include "gm.h"
+#include <chrono>
+#include <functional>
+#include <stdio.h>
+#include <stdlib.h>
+
+using sk_gpu_test::GrContextFactory;
+
+static DEFINE_string2(sources, s, "", "Which GMs, .skps, or images to draw.");
+static DEFINE_string2(backend, b, "", "Backend used to create a canvas to draw into.");
+
+static DEFINE_string(ct   ,   "8888", "The color type for any raster backend.");
+static DEFINE_string(at   , "premul", "The alpha type for any raster backend.");
+static DEFINE_string(gamut,   "srgb", "The color gamut for any raster backend.");
+static DEFINE_string(tf   ,   "srgb", "The transfer function for any raster backend.");
+
+static DEFINE_int   (samples ,         0, "Samples per pixel in GPU backends.");
+static DEFINE_bool  (nvpr    ,     false, "Use NV_path_rendering in GPU backends?");
+static DEFINE_bool  (stencils,      true, "If false, avoid stencil buffers in GPU backends.");
+static DEFINE_bool  (dit     ,     false, "Use device-independent text in GPU backends.");
+static DEFINE_string(surf    , "default", "Backing store for GPU backend surfaces.");
+
+static DEFINE_bool(       preAbandonGpuContext, false, "Abandon the GrContext before drawing.");
+static DEFINE_bool(          abandonGpuContext, false, "Abandon the GrContext after drawing.");
+static DEFINE_bool(releaseAndAbandonGpuContext, false,
+                   "Release all GPU resources and abandon the GrContext after drawing.");
+
+static DEFINE_bool(decodeToDst, false,
+                   "Decode images to destination format rather than suggested natural format.");
+
+static DEFINE_bool   (cpuDetect, true, "Detect CPU features for runtime optimizations?");
+static DEFINE_string2(writePath, w, "", "Write .pngs to this directory if set.");
+static DEFINE_bool2  (verbose, v, false, "Print progress to stdout.");
+
+static DEFINE_string(key,        "", "Metadata passed through to .png encoder and .json output.");
+static DEFINE_string(parameters, "", "Metadata passed through to .png encoder and .json output.");
+
+template <typename T>
+struct FlagOption {
+    const char* label;
+    T           value;
+};
+
+template <typename T, int N>
+static bool parse_flag(const CommandLineFlags::StringArray& flag,
+                       const char* flag_name,
+                       const FlagOption<T> (&array)[N],
+                       T* value) {
+    for (auto entry : array) {
+        if (flag.contains(entry.label)) {
+            *value = entry.value;
+            return true;
+        }
+    }
+    fprintf(stderr, "Known values for --%s:\n", flag_name);
+    for (auto entry : array) {
+        fprintf(stderr, "    --%s %s\n", flag_name, entry.label);
+    }
+    return false;
+}
+
+static void exit_with_failure() {
+    // TODO: dump stack trace, debug trap, print currently running job, etc?
+    exit(1);
+}
+
+struct Source {
+    SkString                               name;
+    SkISize                                size;
+    std::function<void(SkCanvas*)>         draw;
+    std::function<void(GrContextOptions*)> tweak;
+};
+
+static Source gm_source(std::shared_ptr<skiagm::GM> gm) {
+    return {
+        SkString{gm->getName()},
+        gm->getISize(),
+        [gm](SkCanvas* canvas) {
+            SkString err;
+            if (skiagm::DrawResult::kFail == gm->draw(canvas, &err)) {
+                fprintf(stderr, "Drawing GM %s failed: %s\n",
+                        gm->getName(), err.c_str());
+                exit_with_failure();
+            }
+        },
+        [gm](GrContextOptions* options) { gm->modifyGrContextOptions(options); },
+    };
+}
+
+static Source picture_source(SkString name, sk_sp<SkPicture> pic) {
+    return {
+        name,
+        pic->cullRect().roundOut().size(),
+        [pic](SkCanvas* canvas) {
+            canvas->drawPicture(pic);
+        },
+        [](GrContextOptions*) {},
+    };
+}
+
+static Source codec_source(SkString name, std::shared_ptr<SkCodec> codec) {
+    return {
+        name,
+        codec->dimensions(),
+        [codec](SkCanvas* canvas) {
+            SkImageInfo info = codec->getInfo();
+            if (FLAGS_decodeToDst) {
+                info = canvas->imageInfo().makeWH(info.width(),
+                                                  info.height());
+            }
+
+            SkBitmap bm;
+            bm.allocPixels(info);
+
+            switch (auto result = codec->getPixels(info, bm.getPixels(), bm.rowBytes())) {
+                case SkCodec::kSuccess:
+                case SkCodec::kErrorInInput:
+                case SkCodec::kIncompleteInput:
+                    canvas->drawBitmap(bm, 0,0);
+                    break;
+                default:
+                    fprintf(stderr, "SkCodec::getPixels failed: %d.", result);
+                    exit_with_failure();
+            }
+        },
+        [](GrContextOptions*) {},
+    };
+}
+
+static sk_sp<SkImage> draw_with_cpu(std::function<void(SkCanvas*)> draw,
+                                    SkImageInfo info) {
+    if (sk_sp<SkSurface> surface = SkSurface::MakeRaster(info)) {
+        draw(surface->getCanvas());
+        return surface->makeImageSnapshot();
+    }
+    return nullptr;
+}
+
+static sk_sp<SkImage> draw_with_gpu(std::function<void(SkCanvas*)> draw,
+                                    SkImageInfo info,
+                                    GrContextFactory::ContextType api,
+                                    GrContextFactory* factory) {
+    enum class SurfaceType { kDefault, kBackendTexture, kBackendRenderTarget };
+    const FlagOption<SurfaceType> kSurfaceTypes[] = {
+        { "default", SurfaceType::kDefault },
+        { "betex"  , SurfaceType::kBackendTexture },
+        { "bert"   , SurfaceType::kBackendRenderTarget },
+    };
+    SurfaceType surfaceType;
+    if (!parse_flag(FLAGS_surf, "surf", kSurfaceTypes, &surfaceType)) {
+        return nullptr;
+    }
+
+    auto overrides = FLAGS_nvpr ? GrContextFactory::ContextOverrides::kRequireNVPRSupport
+                                : GrContextFactory::ContextOverrides::kDisableNVPR;
+    if (!FLAGS_stencils) { overrides |= GrContextFactory::ContextOverrides::kAvoidStencilBuffers; }
+
+    GrContext* context = factory->getContextInfo(api, overrides)
+                                 .grContext();
+
+    uint32_t flags = FLAGS_dit ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag
+                               : 0;
+    SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);
+
+    sk_sp<SkSurface> surface;
+    GrBackendTexture backendTexture;
+    GrBackendRenderTarget backendRT;
+
+    switch (surfaceType) {
+        case SurfaceType::kDefault:
+            surface = SkSurface::MakeRenderTarget(context,
+                                                  SkBudgeted::kNo,
+                                                  info,
+                                                  FLAGS_samples,
+                                                  &props);
+            break;
+
+        case SurfaceType::kBackendTexture:
+            backendTexture = context->priv().getGpu()
+                ->createTestingOnlyBackendTexture(nullptr,
+                                                  info.width(),
+                                                  info.height(),
+                                                  info.colorType(),
+                                                  true,
+                                                  GrMipMapped::kNo);
+            surface = SkSurface::MakeFromBackendTexture(context,
+                                                        backendTexture,
+                                                        kTopLeft_GrSurfaceOrigin,
+                                                        FLAGS_samples,
+                                                        info.colorType(),
+                                                        info.refColorSpace(),
+                                                        &props);
+            break;
+
+        case SurfaceType::kBackendRenderTarget:
+            backendRT = context->priv().getGpu()
+                ->createTestingOnlyBackendRenderTarget(info.width(),
+                                                       info.height(),
+                                                       SkColorTypeToGrColorType(info.colorType()));
+            surface = SkSurface::MakeFromBackendRenderTarget(context,
+                                                             backendRT,
+                                                             kBottomLeft_GrSurfaceOrigin,
+                                                             info.colorType(),
+                                                             info.refColorSpace(),
+                                                             &props);
+            break;
+    }
+
+    if (!surface) {
+        fprintf(stderr, "Could not create GPU surface.\n");
+        return nullptr;
+    }
+
+    if (FLAGS_preAbandonGpuContext) {
+        factory->abandonContexts();
+    }
+
+    draw(surface->getCanvas());
+    sk_sp<SkImage> image = surface->makeImageSnapshot();
+
+    if (FLAGS_abandonGpuContext) {
+        factory->abandonContexts();
+    } else if (FLAGS_releaseAndAbandonGpuContext) {
+        factory->releaseResourcesAndAbandonContexts();
+    }
+
+    if (!context->abandoned()) {
+        surface.reset();
+        if (backendTexture.isValid()) {
+            context->priv().getGpu()->deleteTestingOnlyBackendTexture(backendTexture);
+        }
+        if (backendRT.isValid()) {
+            context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
+        }
+    }
+
+    return image;
+}
+
+int main(int argc, char** argv) {
+    CommandLineFlags::Parse(argc, argv);
+
+    if (FLAGS_cpuDetect) {
+        SkGraphics::Init();
+    }
+    initializeEventTracingForTools();
+    ToolUtils::SetDefaultFontMgr();
+    SetAnalyticAAFromCommonFlags();
+
+    GrContextOptions baseOptions;
+    SetCtxOptionsFromCommonFlags(&baseOptions);
+
+
+    SkTArray<Source> sources;
+    for (skiagm::GMFactory factory : skiagm::GMRegistry::Range()) {
+        std::shared_ptr<skiagm::GM> gm{factory(nullptr)};
+
+        if (FLAGS_sources.isEmpty()) {
+            fprintf(stdout, "%s\n", gm->getName());
+        } else if (FLAGS_sources.contains(gm->getName())) {
+            sources.push_back(gm_source(gm));
+        }
+    }
+    for (const SkString& source : FLAGS_sources) {
+        if (sk_sp<SkData> blob = SkData::MakeFromFileName(source.c_str())) {
+            const SkString name = SkOSPath::Basename(source.c_str());
+
+            if (sk_sp<SkPicture> pic = SkPicture::MakeFromData(blob.get())) {
+                sources.push_back(picture_source(name, pic));
+            }
+            if (std::shared_ptr<SkCodec> codec = SkCodec::MakeFromData(blob)) {
+                sources.push_back(codec_source(name, codec));
+            }
+        }
+    }
+    if (sources.empty()) {
+        return 0;
+    }
+
+    const FlagOption<SkColorType> kColorTypes[] = {
+        { "a8",           kAlpha_8_SkColorType },
+        { "g8",            kGray_8_SkColorType },
+        { "565",          kRGB_565_SkColorType },
+        { "4444",       kARGB_4444_SkColorType },
+        { "8888",             kN32_SkColorType },
+        { "888x",        kRGB_888x_SkColorType },
+        { "1010102", kRGBA_1010102_SkColorType },
+        { "101010x",  kRGB_101010x_SkColorType },
+        { "f16norm", kRGBA_F16Norm_SkColorType },
+        { "f16",         kRGBA_F16_SkColorType },
+        { "f32",         kRGBA_F32_SkColorType },
+        { "rgba",       kRGBA_8888_SkColorType },
+        { "bgra",       kBGRA_8888_SkColorType },
+    };
+    const FlagOption<SkAlphaType> kAlphaTypes[] = {
+        {   "premul",   kPremul_SkAlphaType },
+        { "unpremul", kUnpremul_SkAlphaType },
+    };
+    const FlagOption<skcms_Matrix3x3> kGamuts[] = {
+        { "srgb",    SkNamedGamut::kSRGB },
+        { "p3",      SkNamedGamut::kDCIP3 },
+        { "rec2020", SkNamedGamut::kRec2020 },
+        { "adobe",   SkNamedGamut::kAdobeRGB },
+        { "narrow",  gNarrow_toXYZD50},
+    };
+    const FlagOption<skcms_TransferFunction> kTransferFunctions[] = {
+        { "srgb"   , SkNamedTransferFn::kSRGB },
+        { "rec2020", {2.22222f, 0.909672f, 0.0903276f, 0.222222f, 0.0812429f, 0, 0} },
+        { "2.2"    , SkNamedTransferFn::k2Dot2 },
+        { "linear" , SkNamedTransferFn::kLinear },
+    };
+
+    enum NonGpuBackends {
+        kCPU_Backend = -1,
+    };
+    const FlagOption<int> kBackends[] = {
+        { "cpu"            , kCPU_Backend },
+        { "gl"             , GrContextFactory::kGL_ContextType },
+        { "gles"           , GrContextFactory::kGLES_ContextType },
+        { "angle_d3d9_es2" , GrContextFactory::kANGLE_D3D9_ES2_ContextType },
+        { "angle_d3d11_es2", GrContextFactory::kANGLE_D3D11_ES2_ContextType },
+        { "angle_d3d11_es3", GrContextFactory::kANGLE_D3D11_ES3_ContextType },
+        { "angle_gl_es2"   , GrContextFactory::kANGLE_GL_ES2_ContextType },
+        { "angle_gl_es3"   , GrContextFactory::kANGLE_GL_ES3_ContextType },
+        { "commandbuffer"  , GrContextFactory::kCommandBuffer_ContextType },
+        { "vk"             , GrContextFactory::kVulkan_ContextType },
+        { "mtl"            , GrContextFactory::kMetal_ContextType },
+        { "mock"           , GrContextFactory::kMock_ContextType },
+    };
+
+    SkColorType              ct;
+    SkAlphaType              at;
+    skcms_Matrix3x3          gamut;
+    skcms_TransferFunction   tf;
+    int                      backend;
+
+    if (!parse_flag(FLAGS_ct     , "ct"     , kColorTypes       , &ct)      ||
+        !parse_flag(FLAGS_at     , "at"     , kAlphaTypes       , &at)      ||
+        !parse_flag(FLAGS_gamut  , "gamut"  , kGamuts           , &gamut)   ||
+        !parse_flag(FLAGS_tf     , "tf"     , kTransferFunctions, &tf)      ||
+        !parse_flag(FLAGS_backend, "backend", kBackends         , &backend)) {
+        return 1;
+    }
+
+    const SkImageInfo unsized_info = SkImageInfo::Make(0,0, ct,at, SkColorSpace::MakeRGB(tf,gamut));
+
+    for (auto source : sources) {
+        const auto start = std::chrono::steady_clock::now();
+        if (FLAGS_verbose) {
+            fprintf(stdout, "%50s", source.name.c_str());
+        }
+
+        const SkImageInfo info = unsized_info.makeWH(source.size.width(),
+                                                     source.size.height());
+
+        GrContextOptions options = baseOptions;
+        source.tweak(&options);
+        GrContextFactory factory(options);  // N.B. factory must outlive image
+
+        sk_sp<SkImage> image;
+        switch (backend) {
+            case kCPU_Backend:
+                image = draw_with_cpu(source.draw, info);
+                break;
+            default:
+                image = draw_with_gpu(source.draw, info,
+                                      (GrContextFactory::ContextType)backend, &factory);
+                break;
+        }
+
+        if (!image) {
+            fprintf(stderr, "FM backend returned a null image.\n");
+            exit_with_failure();
+        }
+
+        SkBitmap bitmap;
+        if (!image->asLegacyBitmap(&bitmap)) {
+            fprintf(stderr, "SkImage::asLegacyBitmap() failed.\n");
+            exit_with_failure();
+        }
+
+        HashAndEncode hashAndEncode{bitmap};
+        SkString md5;
+        {
+            SkMD5 hash;
+            hashAndEncode.write(&hash);
+
+            SkMD5::Digest digest;
+            hash.finish(digest);
+            for (int i = 0; i < 16; i++) {
+                md5.appendf("%02x", digest.data[i]);
+            }
+        }
+
+        if (!FLAGS_writePath.isEmpty()) {
+            sk_mkdir(FLAGS_writePath[0]);
+            SkString path = SkStringPrintf("%s/%s.png", FLAGS_writePath[0], source.name.c_str());
+
+            if (!hashAndEncode.writePngTo(path.c_str(), md5.c_str(), FLAGS_key, FLAGS_parameters)) {
+                fprintf(stderr, "Could not write a .png to %s.\n", path.c_str());
+                exit_with_failure();
+            }
+
+        }
+
+        if (FLAGS_verbose) {
+            const auto elapsed = std::chrono::steady_clock::now() - start;
+            fprintf(stdout, "\t%s\t%7dms\n",
+                    md5.c_str(),
+                    (int)std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count());
+        }
+    }
+
+    return 0;
+}
diff --git a/tools/fonts/TestSVGTypeface.cpp b/tools/fonts/TestSVGTypeface.cpp
index d84ef0a..4a78084 100644
--- a/tools/fonts/TestSVGTypeface.cpp
+++ b/tools/fonts/TestSVGTypeface.cpp
@@ -61,25 +61,54 @@
         , fGlyphCount(data.size()) {
     for (size_t i = 0; i < data.size(); ++i) {
         const SkSVGTestTypefaceGlyphData& datum  = data[i];
-        std::unique_ptr<SkStreamAsset>    stream = GetResourceAsStream(datum.fSvgResourcePath);
         fCMap.set(datum.fUnicode, i);
-        fGlyphs[i].fAdvance = datum.fAdvance;
-        fGlyphs[i].fOrigin  = datum.fOrigin;
+        fGlyphs[i].fAdvance      = datum.fAdvance;
+        fGlyphs[i].fOrigin       = datum.fOrigin;
+        fGlyphs[i].fResourcePath = datum.fSvgResourcePath;
+    }
+}
+
+template <typename Fn>
+void TestSVGTypeface::Glyph::withSVG(Fn&& fn) const {
+    SkAutoExclusive lock(fSvgMutex);
+
+    if (!fParsedSvg) {
+        fParsedSvg = true;
+
+        std::unique_ptr<SkStreamAsset> stream = GetResourceAsStream(fResourcePath);
         if (!stream) {
-            continue;
+            return;
         }
+
         sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(*stream.get());
         if (!svg) {
-            continue;
+            return;
         }
 
-        const SkSize& sz = svg->containerSize();
-        if (sz.isEmpty()) {
-            continue;
+        if (svg->containerSize().isEmpty()) {
+            return;
         }
 
-        fGlyphs[i].fSvg = std::move(svg);
+        fSvg = std::move(svg);
     }
+
+    if (fSvg) {
+        fn(*fSvg);
+    }
+}
+
+SkSize TestSVGTypeface::Glyph::size() const {
+    SkSize size = SkSize::MakeEmpty();
+    this->withSVG([&](const SkSVGDOM& svg){
+        size = svg.containerSize();
+    });
+    return size;
+}
+
+void TestSVGTypeface::Glyph::render(SkCanvas* canvas) const {
+    this->withSVG([&](const SkSVGDOM& svg){
+        svg.render(canvas);
+    });
 }
 
 TestSVGTypeface::~TestSVGTypeface() {}
@@ -193,13 +222,10 @@
         this->generateAdvance(glyph);
 
         TestSVGTypeface::Glyph& glyphData = this->getTestSVGTypeface()->fGlyphs[glyphID];
-        if (!glyphData.fSvg) {
-            return;
-        }
 
-        SkSize containerSize = glyphData.fSvg->containerSize();
-        SkRect newBounds     = SkRect::MakeXYWH(glyphData.fOrigin.fX,
-                                            -glyphData.fOrigin.fY,
+        SkSize containerSize = glyphData.size();
+        SkRect newBounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
+                                           -glyphData.fOrigin.fY,
                                             containerSize.fWidth,
                                             containerSize.fHeight);
         fMatrix.mapRect(&newBounds);
@@ -237,10 +263,7 @@
         canvas.concat(fMatrix);
         canvas.translate(glyphData.fOrigin.fX, -glyphData.fOrigin.fY);
 
-        if (glyphData.fSvg) {
-            SkAutoExclusive lock(glyphData.fSvgMutex);
-            glyphData.fSvg->render(&canvas);
-        }
+        glyphData.render(&canvas);
     }
 
     bool generatePath(SkGlyphID glyph, SkPath* path) override {
@@ -911,8 +934,7 @@
     for (int i = 0; i < fGlyphCount; ++i) {
         const TestSVGTypeface::Glyph& glyphData = this->fGlyphs[i];
 
-        SkSize containerSize =
-                glyphData.fSvg ? glyphData.fSvg->containerSize() : SkSize::MakeEmpty();
+        SkSize containerSize = glyphData.size();
         SkRect  bounds  = SkRect::MakeXYWH(glyphData.fOrigin.fX,
                                          -glyphData.fOrigin.fY,
                                          containerSize.fWidth,
@@ -1359,16 +1381,13 @@
     for (int i = 0; i < fGlyphCount; ++i) {
         const TestSVGTypeface::Glyph& glyphData = this->fGlyphs[i];
 
-        SkSize containerSize =
-                glyphData.fSvg ? glyphData.fSvg->containerSize() : SkSize::MakeEmpty();
+        SkSize containerSize = glyphData.size();
         SkRect       bounds = SkRect::MakeXYWH(glyphData.fOrigin.fX,
                                          -glyphData.fOrigin.fY,
                                          containerSize.fWidth,
                                          containerSize.fHeight);
         SkCOLRCanvas canvas(bounds, *this, i, &glyfInfos.emplace_back(), &colors, &glyfOut);
-        if (glyphData.fSvg) {
-            glyphData.fSvg->render(&canvas);
-        }
+        glyphData.render(&canvas);
         canvas.finishGlyph();
     }
     glyfOut.writeText("  </glyf>\n");
diff --git a/tools/fonts/TestSVGTypeface.h b/tools/fonts/TestSVGTypeface.h
index d86b10a..ba0d789 100644
--- a/tools/fonts/TestSVGTypeface.h
+++ b/tools/fonts/TestSVGTypeface.h
@@ -27,6 +27,7 @@
 
 #include <memory>
 
+class SkCanvas;
 class SkDescriptor;
 class SkFontDescriptor;
 class SkFontStyle;
@@ -128,11 +129,25 @@
     struct Glyph {
         Glyph();
         ~Glyph();
-        sk_sp<SkSVGDOM> fSvg;
-        SkMutex         fSvgMutex;
-        SkPoint         fOrigin;
-        SkScalar        fAdvance;
+        SkPoint     fOrigin;
+        SkScalar    fAdvance;
+        const char* fResourcePath;
+
+        SkSize size() const;
+        void render(SkCanvas*) const;
+
+    private:
+        // Lazily parses the SVG from fResourcePath, and manages mutex locking.
+        template <typename Fn> void withSVG(Fn&&) const;
+
+        // The mutex guards lazy parsing of the SVG, but also predates that.
+        // Must be SkSVGDOM::render() is not thread safe?
+        // If not, an SkOnce is enough here.
+        mutable SkMutex         fSvgMutex;
+        mutable bool            fParsedSvg = false;
+        mutable sk_sp<SkSVGDOM> fSvg;
     };
+
     SkString                         fName;
     int                              fUpem;
     const SkFontMetrics              fFontMetrics;
diff --git a/tools/skp/page_sets/skia_booking_mobile.py b/tools/skp/page_sets/skia_booking_mobile.py
index 2f3f1fa..d158bcd 100644
--- a/tools/skp/page_sets/skia_booking_mobile.py
+++ b/tools/skp/page_sets/skia_booking_mobile.py
@@ -21,7 +21,7 @@
 
   def RunNavigateSteps(self, action_runner):
     action_runner.Navigate(self.url)
-    action_runner.Wait(15)
+    action_runner.Wait(30)
 
 
 class SkiaBookingMobilePageSet(story.StorySet):
diff --git a/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py b/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py
index f740dc7..3db39a4 100644
--- a/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py
+++ b/tools/skp/page_sets/skia_capitalvolkswagen_mobile.py
@@ -21,7 +21,7 @@
 
   def RunNavigateSteps(self, action_runner):
     action_runner.Navigate(self.url)
-    action_runner.Wait(15)
+    action_runner.Wait(30)
 
 
 class SkiaCapitalvolkswagenMobilePageSet(story.StorySet):
diff --git a/tools/skp/page_sets/skia_nytimes_mobile.py b/tools/skp/page_sets/skia_nytimes_mobile.py
deleted file mode 100644
index 19755d4..0000000
--- a/tools/skp/page_sets/skia_nytimes_mobile.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaMobilePage(page_module.Page):
-
-  def __init__(self, url, page_set):
-    super(SkiaMobilePage, self).__init__(
-        url=url,
-        name=url,
-        page_set=page_set,
-        shared_page_state_class=shared_page_state.SharedMobilePageState)
-    self.archive_data_file = 'data/skia_nytimes_mobile.json'
-
-  def RunNavigateSteps(self, action_runner):
-    action_runner.Navigate(self.url)
-    action_runner.Wait(15)
-
-
-class SkiaNytimesMobilePageSet(story.StorySet):
-  """ Pages designed to represent the median, not highly optimized web """
-
-  def __init__(self):
-    super(SkiaNytimesMobilePageSet, self).__init__(
-      archive_data_file='data/skia_nytimes_mobile.json')
-
-    urls_list = [
-      # go/skia-skps-3-2019
-      'http://nytimes.com/',
-    ]
-
-    for url in urls_list:
-      self.AddStory(SkiaMobilePage(url, self))
\ No newline at end of file
diff --git a/tools/skp/page_sets/skia_sfgate_desktop.py b/tools/skp/page_sets/skia_sfgate_desktop.py
deleted file mode 100644
index 5c35d51..0000000
--- a/tools/skp/page_sets/skia_sfgate_desktop.py
+++ /dev/null
@@ -1,40 +0,0 @@
-# Copyright 2019 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-# pylint: disable=W0401,W0614
-
-
-from telemetry import story
-from telemetry.page import page as page_module
-from telemetry.page import shared_page_state
-
-
-class SkiaDesktopPage(page_module.Page):
-
-  def __init__(self, url, page_set):
-    super(SkiaDesktopPage, self).__init__(
-        url=url,
-        name=url,
-        page_set=page_set,
-        shared_page_state_class=shared_page_state.SharedDesktopPageState)
-    self.archive_data_file = 'data/skia_sfgate_desktop.json'
-
-  def RunNavigateSteps(self, action_runner):
-    action_runner.Navigate(self.url)
-    action_runner.Wait(30)
-
-
-class SkiaSfgateDesktopPageSet(story.StorySet):
-  """ Pages designed to represent the median, not highly optimized web """
-
-  def __init__(self):
-    super(SkiaSfgateDesktopPageSet, self).__init__(
-      archive_data_file='data/skia_sfgate_desktop.json')
-
-    urls_list = [
-      # go/skia-skps-3-2019
-      'http://www.sfgate.com/news/',
-    ]
-
-    for url in urls_list:
-      self.AddStory(SkiaDesktopPage(url, self))