[skottie] Apply fully opaque masks as clips

We already have a clip optimization when there is only one opaque mask.

Extend to cover multiple opaque masks, using Merge scene nodes.

TBR=
Change-Id: I24b61f0c0d080b13438c6777e98a8e2fefd09fdd
Reviewed-on: https://skia-review.googlesource.com/140002
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Florin Malita <fmalita@chromium.org>
diff --git a/modules/sksg/src/SkSGMerge.cpp b/modules/sksg/src/SkSGMerge.cpp
index be1ff41..ff50021 100644
--- a/modules/sksg/src/SkSGMerge.cpp
+++ b/modules/sksg/src/SkSGMerge.cpp
@@ -12,17 +12,16 @@
 
 namespace sksg {
 
-Merge::Merge(std::vector<sk_sp<GeometryNode>>&& geos, Mode mode)
-    : fGeos(std::move(geos))
-    , fMode(mode) {
-    for (const auto& geo : fGeos) {
-        this->observeInval(geo);
+Merge::Merge(std::vector<Rec>&& recs)
+    : fRecs(std::move(recs)) {
+    for (const auto& rec : fRecs) {
+        this->observeInval(rec.fGeo);
     }
 }
 
 Merge::~Merge() {
-    for (const auto& geo : fGeos) {
-        this->unobserveInval(geo);
+    for (const auto& rec : fRecs) {
+        this->unobserveInval(rec.fGeo);
     }
 }
 
@@ -60,21 +59,34 @@
 SkRect Merge::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
     SkASSERT(this->hasInval());
 
-    const auto op = mode_to_op(fMode);
     SkOpBuilder builder;
 
     fMerged.reset();
+    bool in_builder = false;
 
-    for (const auto& geo : fGeos) {
-        geo->revalidate(ic, ctm);
-        if (fMode == Mode::kMerge) {
-            fMerged.addPath(geo->asPath());
-        } else {
-            builder.add(geo->asPath(), geo == fGeos.front() ? kUnion_SkPathOp : op);
+    for (const auto& rec : fRecs) {
+        rec.fGeo->revalidate(ic, ctm);
+
+        // Merge is not currently supported by SkOpBuidler.
+        if (rec.fMode == Mode::kMerge) {
+            if (in_builder) {
+                builder.resolve(&fMerged);
+                in_builder = false;
+            }
+
+            fMerged.addPath(rec.fGeo->asPath());
+            continue;
         }
+
+        if (!in_builder) {
+            builder.add(fMerged, kUnion_SkPathOp);
+            in_builder = true;
+        }
+
+        builder.add(rec.fGeo->asPath(), mode_to_op(rec.fMode));
     }
 
-    if (fMode != Mode::kMerge) {
+    if (in_builder) {
         builder.resolve(&fMerged);
     }