Add the ability to enable/disable GPU path renderers

Adds a bitfield to GrContextOptions that masks out path renderers.
Adds commandline flags support to set this bitfield in tools apps.
Removes GrGLInterfaceRemoveNVPR since we can now accomplish the same
thing in the context options.

BUG=skia:

Change-Id: Icf2a4df36374b3ba2f69ebf0db56e8aedd6cf65f
Reviewed-on: https://skia-review.googlesource.com/8786
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/tools/flags/SkCommonFlagsPathRenderer.h b/tools/flags/SkCommonFlagsPathRenderer.h
new file mode 100644
index 0000000..d3b80f5
--- /dev/null
+++ b/tools/flags/SkCommonFlagsPathRenderer.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SK_COMMON_FLAGS_PATH_RENDERER_H
+#define SK_COMMON_FLAGS_PATH_RENDERER_H
+
+#if SK_SUPPORT_GPU
+
+#include "GrContextFactory.h"
+#include "SkCommandLineFlags.h"
+#include "SkTypes.h"
+
+DECLARE_string(pr);
+
+#define DEFINE_pathrenderer_flag \
+    DEFINE_string(pr, "all", \
+                  "Set of enabled gpu path renderers. Defined as a list of: " \
+                    "[[~]all [~]dashline [~]nvpr [~]msaa [~]aahairline [~]aaconvex " \
+                    "[~]aalinearizing [~]pls [~]sdf [~]tess [~]grdefault]")
+
+inline GrContextOptions::GpuPathRenderers get_named_pathrenderers_flags(const char* name) {
+    using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
+    if (!strcmp(name, "all")) {
+        return GpuPathRenderers::kAll;
+    } else if (!strcmp(name, "dashline")) {
+        return GpuPathRenderers::kDashLine;
+    } else if (!strcmp(name, "nvpr")) {
+        return GpuPathRenderers::kStencilAndCover;
+    } else if (!strcmp(name, "msaa")) {
+        return GpuPathRenderers::kMSAA;
+    } else if (!strcmp(name, "aahairline")) {
+        return GpuPathRenderers::kAAHairline;
+    } else if (!strcmp(name, "aaconvex")) {
+        return GpuPathRenderers::kAAConvex;
+    } else if (!strcmp(name, "aalinearizing")) {
+        return GpuPathRenderers::kAALinearizing;
+    } else if (!strcmp(name, "pls")) {
+        return GpuPathRenderers::kPLS;
+    } else if (!strcmp(name, "sdf")) {
+        return GpuPathRenderers::kDistanceField;
+    } else if (!strcmp(name, "tess")) {
+        return GpuPathRenderers::kTesselating;
+    } else if (!strcmp(name, "grdefault")) {
+        return GpuPathRenderers::kDefault;
+    }
+    SK_ABORT(SkStringPrintf("error: unknown named path renderer \"%s\"\n", name).c_str());
+    return GpuPathRenderers::kNone;
+}
+
+inline GrContextOptions::GpuPathRenderers CollectGpuPathRenderersFromFlags() {
+    using GpuPathRenderers = GrContextOptions::GpuPathRenderers;
+    if (FLAGS_pr.isEmpty()) {
+        return GpuPathRenderers::kAll;
+    }
+    GpuPathRenderers gpuPathRenderers = '~' == FLAGS_pr[0][0] ?
+                                        GpuPathRenderers::kAll : GpuPathRenderers::kNone;
+    for (int i = 0; i < FLAGS_pr.count(); ++i) {
+        const char* name = FLAGS_pr[i];
+        if (name[0] == '~') {
+            gpuPathRenderers &= ~get_named_pathrenderers_flags(&name[1]);
+        } else {
+            gpuPathRenderers |= get_named_pathrenderers_flags(name);
+        }
+    }
+    return gpuPathRenderers;
+}
+
+#endif // SK_SUPPORT_GPU
+
+#endif
diff --git a/tools/gpu/GrContextFactory.cpp b/tools/gpu/GrContextFactory.cpp
index 965e646..637c569 100644
--- a/tools/gpu/GrContextFactory.cpp
+++ b/tools/gpu/GrContextFactory.cpp
@@ -196,12 +196,6 @@
             }
             testCtx.reset(glCtx);
             glInterface.reset(SkRef(glCtx->gl()));
-            if (ContextOverrides::kDisableNVPR & overrides) {
-                glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface.get()));
-                if (!glInterface) {
-                    return ContextInfo();
-                }
-            }
             backendContext = reinterpret_cast<GrBackendContext>(glInterface.get());
             break;
         }
@@ -238,6 +232,9 @@
     testCtx->makeCurrent();
     SkASSERT(testCtx && testCtx->backend() == backend);
     GrContextOptions grOptions = fGlobalOptions;
+    if (ContextOverrides::kDisableNVPR & overrides) {
+        grOptions.fSuppressPathRendering = true;
+    }
     if (ContextOverrides::kUseInstanced & overrides) {
         grOptions.fEnableInstancedRendering = true;
     }
diff --git a/tools/skpbench/skpbench.cpp b/tools/skpbench/skpbench.cpp
index 3887c5e..569c204 100644
--- a/tools/skpbench/skpbench.cpp
+++ b/tools/skpbench/skpbench.cpp
@@ -8,6 +8,7 @@
 #include "GpuTimer.h"
 #include "GrContextFactory.h"
 #include "SkCanvas.h"
+#include "SkCommonFlagsPathRenderer.h"
 #include "SkOSFile.h"
 #include "SkOSPath.h"
 #include "SkPerlinNoiseShader.h"
@@ -46,6 +47,7 @@
 DEFINE_string(png, "", "if set, save a .png proof to disk at this file location");
 DEFINE_int32(verbosity, 4, "level of verbosity (0=none to 5=debug)");
 DEFINE_bool(suppressHeader, false, "don't print a header row before the results");
+DEFINE_pathrenderer_flag;
 
 static const char* header =
 "   accum    median       max       min   stddev  samples  sample_ms  clock  metric  config    bench";
@@ -271,7 +273,9 @@
     }
 
     // Create a context.
-    sk_gpu_test::GrContextFactory factory;
+    GrContextOptions ctxOptions;
+    ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+    sk_gpu_test::GrContextFactory factory(ctxOptions);
     sk_gpu_test::ContextInfo ctxInfo =
         factory.getContextInfo(config->getContextType(), config->getContextOverrides());
     GrContext* ctx = ctxInfo.grContext();
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 57185d2..092910a 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -16,6 +16,7 @@
 #include "SkATrace.h"
 #include "SkCanvas.h"
 #include "SkCommandLineFlags.h"
+#include "SkCommonFlagsPathRenderer.h"
 #include "SkDashPathEffect.h"
 #include "SkGraphics.h"
 #include "SkImagePriv.h"
@@ -134,6 +135,8 @@
 
 static DEFINE_bool(atrace, false, "Enable support for using ATrace. ATrace is only supported on Android.");
 
+DEFINE_pathrenderer_flag;
+
 const char *kBackendTypeStrings[sk_app::Window::kBackendTypeCount] = {
     " [OpenGL]",
 #ifdef SK_VULKAN
diff --git a/tools/viewer/sk_app/GLWindowContext.cpp b/tools/viewer/sk_app/GLWindowContext.cpp
index 501f272..fac0c32 100644
--- a/tools/viewer/sk_app/GLWindowContext.cpp
+++ b/tools/viewer/sk_app/GLWindowContext.cpp
@@ -7,6 +7,7 @@
  */
 
 #include "GrContext.h"
+#include "SkCommonFlagsPathRenderer.h"
 #include "SkSurface.h"
 #include "GLWindowContext.h"
 
@@ -30,12 +31,13 @@
 
 void GLWindowContext::initializeContext() {
     this->onInitializeContext();
-    sk_sp<const GrGLInterface> glInterface;
-    glInterface.reset(GrGLCreateNativeInterface());
-    fBackendContext.reset(GrGLInterfaceRemoveNVPR(glInterface.get()));
-
     SkASSERT(nullptr == fContext);
-    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fBackendContext.get());
+
+    GrContextOptions ctxOptions;
+    ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+    fBackendContext.reset(GrGLCreateNativeInterface());
+    fContext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fBackendContext.get(),
+                                 ctxOptions);
 
     // We may not have real sRGB support (ANGLE, in particular), so check for
     // that, and fall back to L32:
diff --git a/tools/viewer/sk_app/VulkanWindowContext.cpp b/tools/viewer/sk_app/VulkanWindowContext.cpp
index b4e6676..65273b0 100644
--- a/tools/viewer/sk_app/VulkanWindowContext.cpp
+++ b/tools/viewer/sk_app/VulkanWindowContext.cpp
@@ -8,6 +8,7 @@
 
 #include "GrContext.h"
 #include "GrRenderTarget.h"
+#include "SkCommonFlagsPathRenderer.h"
 #include "SkAutoMalloc.h"
 #include "SkSurface.h"
 #include "VulkanWindowContext.h"
@@ -61,7 +62,10 @@
     GET_DEV_PROC(AcquireNextImageKHR);
     GET_DEV_PROC(QueuePresentKHR);
 
-    fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext) fBackendContext.get());
+    GrContextOptions ctxOptions;
+    ctxOptions.fGpuPathRenderers = CollectGpuPathRenderersFromFlags();
+    fContext = GrContext::Create(kVulkan_GrBackend, (GrBackendContext) fBackendContext.get(),
+                                 ctxOptions);
 
     fSurface = createVkSurface(instance);
     if (VK_NULL_HANDLE == fSurface) {