Add a kWireframe flag to GrPipeline

Adds the flag to GrPipeline, as well as a 'w' keystroke in viewer for
toggling the alternate global wireframe mode.

Change-Id: I385c31320a5fa2cec79b527a91fa876b19cdff89
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/260747
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 173c242..a33912d 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -27,6 +27,7 @@
     fInstanceAttribSupport = false;
     fMixedSamplesSupport = false;
     fConservativeRasterSupport = false;
+    fWireframeSupport = false;
     fMSAAResolvesAutomatically = false;
     fUsePrimitiveRestart = false;
     fPreferClientSideDynamicBuffers = false;
@@ -191,6 +192,7 @@
     writer->appendBool("Instance Attrib Support", fInstanceAttribSupport);
     writer->appendBool("Mixed Samples Support", fMixedSamplesSupport);
     writer->appendBool("Conservative Raster Support", fConservativeRasterSupport);
+    writer->appendBool("Wireframe Support", fWireframeSupport);
     writer->appendBool("MSAA Resolves Automatically", fMSAAResolvesAutomatically);
     writer->appendBool("Use primitive restart", fUsePrimitiveRestart);
     writer->appendBool("Prefer client-side dynamic buffers", fPreferClientSideDynamicBuffers);
diff --git a/src/gpu/GrCaps.h b/src/gpu/GrCaps.h
index d869a56..b81e3c0 100644
--- a/src/gpu/GrCaps.h
+++ b/src/gpu/GrCaps.h
@@ -54,6 +54,7 @@
     bool instanceAttribSupport() const { return fInstanceAttribSupport; }
     bool mixedSamplesSupport() const { return fMixedSamplesSupport; }
     bool conservativeRasterSupport() const { return fConservativeRasterSupport; }
+    bool wireframeSupport() const { return fWireframeSupport; }
     // This flag indicates that we never have to resolve MSAA. In practice, it means that we have
     // an MSAA-render-to-texture extension: Any render target we create internally will use the
     // extension, and any wrapped render target is the client's responsibility.
@@ -490,6 +491,7 @@
     bool fInstanceAttribSupport                      : 1;
     bool fMixedSamplesSupport                        : 1;
     bool fConservativeRasterSupport                  : 1;
+    bool fWireframeSupport                           : 1;
     bool fMSAAResolvesAutomatically                  : 1;
     bool fUsePrimitiveRestart                        : 1;
     bool fPreferClientSideDynamicBuffers             : 1;
diff --git a/src/gpu/GrOpsRenderPass.cpp b/src/gpu/GrOpsRenderPass.cpp
index 85ae57d..c506110 100644
--- a/src/gpu/GrOpsRenderPass.cpp
+++ b/src/gpu/GrOpsRenderPass.cpp
@@ -46,6 +46,8 @@
              this->gpu()->caps()->instanceAttribSupport());
     SkASSERT(!programInfo.pipeline().usesConservativeRaster() ||
              this->gpu()->caps()->conservativeRasterSupport());
+    SkASSERT(!programInfo.pipeline().isWireframe() ||
+             this->gpu()->caps()->wireframeSupport());
 
     programInfo.compatibleWithMeshes(meshes, meshCount);
     programInfo.checkAllInstantiated();
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index 76adc9e..6598cf3 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -56,9 +56,13 @@
          */
         kConservativeRaster = (1 << 1),
         /**
+         * Draws triangles as outlines.
+         */
+        kWireframe = (1 << 2),
+        /**
          * Modifies the vertex shader so that vertices will be positioned at pixel centers.
          */
-        kSnapVerticesToPixelCenters = (1 << 2),  // This value must be last. (See kLastInputFlag.)
+        kSnapVerticesToPixelCenters = (1 << 3),  // This value must be last. (See kLastInputFlag.)
     };
 
     struct InitArgs {
@@ -190,6 +194,7 @@
 
     bool isHWAntialiasState() const { return fFlags & InputFlags::kHWAntialias; }
     bool usesConservativeRaster() const { return fFlags & InputFlags::kConservativeRaster; }
+    bool isWireframe() const { return fFlags & InputFlags::kWireframe; }
     bool snapVerticesToPixelCenters() const {
         return fFlags & InputFlags::kSnapVerticesToPixelCenters;
     }
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index aafa033..b7fac56 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -406,6 +406,10 @@
         fConservativeRasterSupport = true;
     }
 
+    if (GR_IS_GR_GL(standard)) {
+        fWireframeSupport = true;
+    }
+
     // Protect ourselves against tracking huge amounts of texture state.
     static const uint8_t kMaxSaneSamplers = 32;
     GrGLint maxSamplers;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index b3e7735..e3bd51d 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -551,11 +551,7 @@
             }
             GL_CALL(Disable(GR_GL_POLYGON_OFFSET_FILL));
 
-            if (this->caps()->wireframeMode()) {
-                GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_LINE));
-            } else {
-                GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_FILL));
-            }
+            fHWWireframeEnabled = kUnknown_TriState;
 #endif
             // Since ES doesn't support glPointSize at all we always use the VS to
             // set the point size
@@ -1721,6 +1717,7 @@
                                 glRT, programInfo.origin());
     this->flushHWAAState(glRT, programInfo.pipeline().isHWAntialiasState());
     this->flushConservativeRasterState(programInfo.pipeline().usesConservativeRaster());
+    this->flushWireframeState(programInfo.pipeline().isWireframe());
 
     // This must come after textures are flushed because a texture may need
     // to be msaa-resolved (which will modify bound FBO state).
@@ -2534,6 +2531,22 @@
     }
 }
 
+void GrGLGpu::flushWireframeState(bool enabled) {
+    if (this->caps()->wireframeSupport()) {
+        if (this->caps()->wireframeMode() || enabled) {
+            if (kYes_TriState != fHWWireframeEnabled) {
+                GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_LINE));
+                fHWWireframeEnabled = kYes_TriState;
+            }
+        } else {
+            if (kNo_TriState != fHWWireframeEnabled) {
+                GL_CALL(PolygonMode(GR_GL_FRONT_AND_BACK, GR_GL_FILL));
+                fHWWireframeEnabled = kNo_TriState;
+            }
+        }
+    }
+}
+
 void GrGLGpu::flushBlendAndColorWrite(
         const GrXferProcessor::BlendInfo& blendInfo, const GrSwizzle& swizzle) {
     if (this->glCaps().neverDisableColorWrites() && !blendInfo.fWriteColor) {
@@ -3366,6 +3379,7 @@
     this->flushBlendAndColorWrite(GrXferProcessor::BlendInfo(), GrSwizzle::RGBA());
     this->flushHWAAState(nullptr, false);
     this->flushConservativeRasterState(false);
+    this->flushWireframeState(false);
     this->disableScissor();
     this->disableWindowRectangles();
     this->disableStencil();
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 58cec1a..9cc12a4 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -376,6 +376,8 @@
 
     void flushConservativeRasterState(bool enable);
 
+    void flushWireframeState(bool enable);
+
     void flushFramebufferSRGB(bool enable);
 
     bool uploadTexData(GrGLFormat textureFormat, GrColorType textureColorType, int texWidth,
@@ -589,11 +591,12 @@
     TriState                                fMSAAEnabled;
     TriState                                fHWConservativeRasterEnabled;
 
+    TriState                                fHWWireframeEnabled;
+
     GrStencilSettings                       fHWStencilSettings;
     GrSurfaceOrigin                         fHWStencilOrigin;
     TriState                                fHWStencilTestEnabled;
 
-
     TriState                                fHWWriteToColor;
     GrGpuResource::UniqueID                 fHWBoundRenderTargetUniqueID;
     TriState                                fHWSRGBFramebuffer;
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 40441ab..119425a 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -514,6 +514,8 @@
         fConservativeRasterSupport = true;
     }
 
+    fWireframeSupport = true;
+
     // We could actually query and get a max size for each config, however maxImageDimension2D will
     // give the minimum max size across all configs. So for simplicity we will use that for now.
     fMaxRenderTargetSize = SkTMin(properties.limits.maxImageDimension2D, (uint32_t)INT_MAX);
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index afb4d61..83db392 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -510,8 +510,8 @@
     rasterInfo->flags = 0;
     rasterInfo->depthClampEnable = VK_FALSE;
     rasterInfo->rasterizerDiscardEnable = VK_FALSE;
-    rasterInfo->polygonMode = caps->wireframeMode() ? VK_POLYGON_MODE_LINE
-                                                    : VK_POLYGON_MODE_FILL;
+    rasterInfo->polygonMode = (caps->wireframeMode() || pipeline.isWireframe()) ?
+            VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL;
     rasterInfo->cullMode = VK_CULL_MODE_NONE;
     rasterInfo->frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
     rasterInfo->depthBiasEnable = VK_FALSE;