Re-re-reland "Rewrite switch statements in GLSL strict-ES2 mode."

This reverts commit 6f06bab632490b82a3cc73be76f8c5ad119ac092.

Reason for revert: glslGeneration is more trustworthy than GR_GL_VER

Original change's description:
> Revert "Re-reland "Rewrite switch statements in GLSL strict-ES2 mode."""
>
> This reverts commit 64560c7cd59b369c792f207cb0295b26978e2724.
>
> Reason for revert: Nexus5, also
>
> Original change's description:
> > Re-reland "Rewrite switch statements in GLSL strict-ES2 mode.""
> >
> > This reverts commit c4c355940c9f5be879d1c1997724a4cf61e68b53.
> >
> > Reason for revert: disabled offending tests
> >
> > Original change's description:
> > > Revert "Reland "Rewrite switch statements in GLSL strict-ES2 mode.""
> > >
> > > This reverts commit c81edd0e8cd999a92ae943f284ee31c25f0f9373.
> > >
> > > Reason for revert: ANGLE still unhappy
> > > Original change's description:
> > > > Reland "Rewrite switch statements in GLSL strict-ES2 mode."
> > > >
> > > > This reverts commit d26d0e6a47aea2575f29b4582a4f662a17a8fff2.
> > > >
> > > > Reason for revert: uses dedicated caps bit
> > > >
> > > > Original change's description:
> > > > > Revert "Rewrite switch statements in GLSL strict-ES2 mode."
> > > > >
> > > > > This reverts commit 45e3838006df8bc393fe6f4ca1cff999b41167f4.
> > > > >
> > > > > Reason for revert: Also need to rewrite them in actual ES2 mode.
> > > > >
> > > > > Original change's description:
> > > > > > Rewrite switch statements in GLSL strict-ES2 mode.
> > > > > >
> > > > > > Once this lands, switch statements will work everywhere--Metal, SPIR-V,
> > > > > > GLSL, and SkVM.
> > > > > >
> > > > > > Change-Id: I2797d0a872de8be77bb9f7aa6acb93421d571d70
> > > > > > Bug: skia:12450
> > > > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452356
> > > > > > Commit-Queue: John Stiles <johnstiles@google.com>
> > > > > > Auto-Submit: John Stiles <johnstiles@google.com>
> > > > > > Reviewed-by: Brian Osman <brianosman@google.com>
> > > > >
> > > > > Bug: skia:12450
> > > > > Change-Id: I92656ed40289872405c0873f2c56a52b04e35b1d
> > > > > No-Presubmit: true
> > > > > No-Tree-Checks: true
> > > > > No-Try: true
> > > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452556
> > > > > Auto-Submit: Brian Osman <brianosman@google.com>
> > > > > Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> > > > > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> > > >
> > > > Bug: skia:12450
> > > > Change-Id: I0d3b0969d2040dbb4ee808132146687767c97442
> > > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452560
> > > > Commit-Queue: John Stiles <johnstiles@google.com>
> > > > Commit-Queue: Brian Osman <brianosman@google.com>
> > > > Auto-Submit: John Stiles <johnstiles@google.com>
> > > > Reviewed-by: Brian Osman <brianosman@google.com>
> > >
> > > Bug: skia:12450
> > > Change-Id: I869cf3e2c47fe94981aa2ffa6c1f0b3e4d6e6862
> > > No-Presubmit: true
> > > No-Tree-Checks: true
> > > No-Try: true
> > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452717
> > > Auto-Submit: Brian Osman <brianosman@google.com>
> > > Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> > > Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> >
> > Bug: skia:12450
> > Change-Id: Ia0e23e20794ea707e54be50123b5323369354a03
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452721
> > Commit-Queue: John Stiles <johnstiles@google.com>
> > Commit-Queue: Brian Osman <brianosman@google.com>
> > Auto-Submit: John Stiles <johnstiles@google.com>
> > Reviewed-by: Brian Osman <brianosman@google.com>
>
> Bug: skia:12450
> Change-Id: Id0c0cdfbf146000ec532e57e380c18ff391ca1da
> No-Presubmit: true
> No-Tree-Checks: true
> No-Try: true
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452896
> Auto-Submit: Brian Osman <brianosman@google.com>
> Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>

Bug: skia:12450
Change-Id: I4bac3a468ae20967fe6ec372561dd44f67c6b730
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/452897
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp b/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp
index d4479db..dc25460 100644
--- a/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLGLSLCodeGenerator.cpp
@@ -1354,9 +1354,67 @@
 }
 
 void GLSLCodeGenerator::writeSwitchStatement(const SwitchStatement& s) {
-    if (fProgram.fConfig->strictES2Mode()) {
-        // TODO(skia:12450): write switch compatibility code
-        fContext.fErrors->error(s.fOffset, "switch statements are not supported");
+    if (this->caps().rewriteSwitchStatements()) {
+        String fallthroughVar = "_tmpSwitchFallthrough" + to_string(fVarCount++);
+        String valueVar = "_tmpSwitchValue" + to_string(fVarCount++);
+        String loopVar = "_tmpSwitchLoop" + to_string(fVarCount++);
+        this->write("int ");
+        this->write(valueVar);
+        this->write(" = ");
+        this->writeExpression(*s.value(), Precedence::kAssignment);
+        this->write(", ");
+        this->write(fallthroughVar);
+        this->writeLine(" = 0;");
+        this->write("for (int ");
+        this->write(loopVar);
+        this->write(" = 0; ");
+        this->write(loopVar);
+        this->write(" < 1; ");
+        this->write(loopVar);
+        this->writeLine("++) {");
+        fIndentation++;
+
+        bool firstCase = true;
+        for (const std::unique_ptr<Statement>& stmt : s.cases()) {
+            const SwitchCase& c = stmt->as<SwitchCase>();
+            if (c.value()) {
+                this->write("if ((");
+                if (firstCase) {
+                    firstCase = false;
+                } else {
+                    this->write(fallthroughVar);
+                    this->write(" > 0) || (");
+                }
+                this->write(valueVar);
+                this->write(" == ");
+                this->writeExpression(*c.value(), Precedence::kEquality);
+                this->writeLine(")) {");
+                fIndentation++;
+
+                // We write the entire case-block statement here, and then set `switchFallthrough`
+                // to 1. If the case-block had a break statement in it, we break out of the outer
+                // for-loop entirely, meaning the `switchFallthrough` assignment never occurs, nor
+                // does any code after it inside the switch. We've forbidden `continue` statements
+                // inside switch case-blocks entirely, so we don't need to consider their effect on
+                // control flow; see the Finalizer in FunctionDefinition::Convert.
+                this->writeStatement(*c.statement());
+                this->finishLine();
+                this->write(fallthroughVar);
+                this->write(" = 1;");
+                this->writeLine();
+
+                fIndentation--;
+                this->writeLine("}");
+            } else {
+                // This is the default case. Since it's always last, we can just dump in the code.
+                this->writeStatement(*c.statement());
+                this->finishLine();
+            }
+        }
+
+        fIndentation--;
+        this->writeLine("}");
+        return;
     }
 
     this->write("switch (");