Add flag to force high-precision RP

Change-Id: I9388458ae186f7b2a8b8534859147b9a1035276f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/432016
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Commit-Queue: Mike Reed <reed@google.com>
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp
index b5e79e9..c486028 100644
--- a/bench/nanobench.cpp
+++ b/bench/nanobench.cpp
@@ -65,6 +65,7 @@
 #include <thread>
 
 extern bool gSkForceRasterPipelineBlitter;
+extern bool gForceHighPrecisionRasterPipeline;
 extern bool gUseSkVMBlitter;
 extern bool gSkVMAllowJIT;
 extern bool gSkVMJITViaDylib;
@@ -140,6 +141,7 @@
         "piping, playback, skcodec, etc.");
 
 static DEFINE_bool(forceRasterPipeline, false, "sets gSkForceRasterPipelineBlitter");
+static DEFINE_bool(forceRasterPipelineHP, false, "sets gSkForceRasterPipelineBlitter and gForceHighPrecisionRasterPipeline");
 static DEFINE_bool(skvm, false, "sets gUseSkVMBlitter");
 static DEFINE_bool(jit, true, "JIT SkVM?");
 static DEFINE_bool(dylib, false, "JIT via dylib (much slower compile but easier to debug/profile)");
@@ -1285,7 +1287,8 @@
 
     SetAnalyticAAFromCommonFlags();
 
-    gSkForceRasterPipelineBlitter = FLAGS_forceRasterPipeline;
+    gSkForceRasterPipelineBlitter     = FLAGS_forceRasterPipelineHP || FLAGS_forceRasterPipeline;
+    gForceHighPrecisionRasterPipeline = FLAGS_forceRasterPipelineHP;
     gUseSkVMBlitter = FLAGS_skvm;
     gSkVMAllowJIT = FLAGS_jit;
     gSkVMJITViaDylib = FLAGS_dylib;
diff --git a/src/core/SkRasterPipeline.cpp b/src/core/SkRasterPipeline.cpp
index 4017e7e..b5d30be 100644
--- a/src/core/SkRasterPipeline.cpp
+++ b/src/core/SkRasterPipeline.cpp
@@ -13,6 +13,8 @@
 #include "src/core/SkRasterPipeline.h"
 #include <algorithm>
 
+bool gForceHighPrecisionRasterPipeline;
+
 SkRasterPipeline::SkRasterPipeline(SkArenaAlloc* alloc) : fAlloc(alloc) {
     this->reset();
 }
@@ -335,24 +337,26 @@
 }
 
 SkRasterPipeline::StartPipelineFn SkRasterPipeline::build_pipeline(void** ip) const {
-    // We'll try to build a lowp pipeline, but if that fails fallback to a highp float pipeline.
-    void** reset_point = ip;
+    if (!gForceHighPrecisionRasterPipeline) {
+        // We'll try to build a lowp pipeline, but if that fails fallback to a highp float pipeline.
+        void** reset_point = ip;
 
-    // Stages are stored backwards in fStages, so we reverse here, back to front.
-    *--ip = (void*)SkOpts::just_return_lowp;
-    for (const StageList* st = fStages; st; st = st->prev) {
-        if (auto fn = SkOpts::stages_lowp[st->stage]) {
-            if (st->ctx) {
-                *--ip = st->ctx;
+        // Stages are stored backwards in fStages, so we reverse here, back to front.
+        *--ip = (void*)SkOpts::just_return_lowp;
+        for (const StageList* st = fStages; st; st = st->prev) {
+            if (auto fn = SkOpts::stages_lowp[st->stage]) {
+                if (st->ctx) {
+                    *--ip = st->ctx;
+                }
+                *--ip = (void*)fn;
+            } else {
+                ip = reset_point;
+                break;
             }
-            *--ip = (void*)fn;
-        } else {
-            ip = reset_point;
-            break;
         }
-    }
-    if (ip != reset_point) {
-        return SkOpts::start_pipeline_lowp;
+        if (ip != reset_point) {
+            return SkOpts::start_pipeline_lowp;
+        }
     }
 
     *--ip = (void*)SkOpts::just_return_highp;