Conditionally insert gl_PointSize into shaders.

BUG=chromium:648816
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2358843002

Review-Url: https://codereview.chromium.org/2358843002
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index c452d34..cfcdbb5 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -106,6 +106,7 @@
 
 bool GrProgramDesc::Build(GrProgramDesc* desc,
                           const GrPrimitiveProcessor& primProc,
+                          bool hasPointSize,
                           const GrPipeline& pipeline,
                           const GrGLSLCaps& glslCaps) {
     // The descriptor is used as a cache key. Thus when a field of the
@@ -171,14 +172,16 @@
 
     header->fOutputSwizzle = glslCaps.configOutputSwizzle(rt->config()).asKey();
 
-    if (pipeline.ignoresCoverage()) {
-        header->fIgnoresCoverage = 1;
-    } else {
-        header->fIgnoresCoverage = 0;
-    }
+    header->fIgnoresCoverage = pipeline.ignoresCoverage() ? 1 : 0;
 
     header->fSnapVerticesToPixelCenters = pipeline.snapVerticesToPixelCenters();
-    header->fColorEffectCnt = pipeline.numColorFragmentProcessors();
-    header->fCoverageEffectCnt = pipeline.numCoverageFragmentProcessors();
+    header->fColorFragmentProcessorCnt = pipeline.numColorFragmentProcessors();
+    header->fCoverageFragmentProcessorCnt = pipeline.numCoverageFragmentProcessors();
+    // Fail if the client requested more processors than the key can fit.
+    if (header->fColorFragmentProcessorCnt != pipeline.numColorFragmentProcessors() ||
+        header->fCoverageFragmentProcessorCnt != pipeline.numCoverageFragmentProcessors()) {
+        return false;
+    }
+    header->fHasPointSize = hasPointSize ? 1 : 0;
     return true;
 }
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index 1f5a581..f304ec5 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -28,6 +28,7 @@
     * on the returned GrProgramDesc.
     *
     * @param GrPrimitiveProcessor The geometry
+    * @param hasPointSize Controls whether the shader will output a point size.
     * @param GrPipeline  The optimized drawstate.  The descriptor will represent a program
     *                        which this optstate can use to draw with.  The optstate contains
     *                        general draw information, as well as the specific color, geometry,
@@ -38,6 +39,7 @@
     **/
     static bool Build(GrProgramDesc*,
                       const GrPrimitiveProcessor&,
+                      bool hasPointSize,
                       const GrPipeline&,
                       const GrGLSLCaps&);
 
@@ -92,28 +94,21 @@
     }
 
     struct KeyHeader {
-        // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
-        uint8_t                     fSurfaceOriginKey;
         // Set to uniquely identify the sample pattern, or 0 if the shader doesn't use sample
         // locations.
         uint8_t                     fSamplePatternKey;
         // Set to uniquely idenitify any swizzling of the shader's output color(s).
         uint8_t                     fOutputSwizzle;
-        uint8_t                     fSnapVerticesToPixelCenters;
-        int8_t                      fColorEffectCnt;
-        int8_t                      fCoverageEffectCnt;
-        uint8_t                     fIgnoresCoverage;
+        uint8_t                     fColorFragmentProcessorCnt : 4;
+        uint8_t                     fCoverageFragmentProcessorCnt : 4;
+        // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
+        uint8_t                     fSurfaceOriginKey : 2;
+        uint8_t                     fIgnoresCoverage : 1;
+        uint8_t                     fSnapVerticesToPixelCenters : 1;
+        uint8_t                     fHasPointSize : 1;
+        uint8_t                     fPad : 3;
     };
-
-    int numColorEffects() const {
-        return this->header().fColorEffectCnt;
-    }
-
-    int numCoverageEffects() const {
-        return this->header().fCoverageEffectCnt;
-    }
-
-    int numTotalEffects() const { return this->numColorEffects() + this->numCoverageEffects(); }
+    GR_STATIC_ASSERT(sizeof(KeyHeader) == 4);
 
     // This should really only be used internally, base classes should return their own headers
     const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 52c7d94..fcd3270 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -2054,8 +2054,10 @@
     }
 }
 
-bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc) {
-    SkAutoTUnref<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc));
+bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc,
+                           bool willDrawPoints) {
+    SkAutoTUnref<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc,
+                                                                willDrawPoints));
     if (!program) {
         GrCapsDebugf(this->caps(), "Failed to create program!\n");
         return false;
@@ -2743,11 +2745,18 @@
 
 void GrGLGpu::draw(const GrPipeline& pipeline,
                    const GrPrimitiveProcessor& primProc,
-                   const GrMesh* meshes,
+                   const GrMesh meshes[],
                    int meshCount) {
     this->handleDirtyContext();
 
-    if (!this->flushGLState(pipeline, primProc)) {
+    bool hasPoints = false;
+    for (int i = 0; i < meshCount; ++i) {
+        if (meshes[i].primitiveType() == kPoints_GrPrimitiveType) {
+            hasPoints = true;
+            break;
+        }
+    }
+    if (!this->flushGLState(pipeline, primProc, hasPoints)) {
         return;
     }
     GrPixelLocalStorageState plsState = primProc.getPixelLocalStorageState();
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 62803ee..b23be3d 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -230,7 +230,8 @@
     void setTextureSwizzle(int unitIdx, GrGLenum target, const GrGLenum swizzle[]);
 
     // Flushes state from GrPipeline to GL. Returns false if the state couldn't be set.
-    bool flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc);
+    // willDrawPoints must be true if point primitives will be rendered after setting the GL state.
+    bool flushGLState(const GrPipeline&, const GrPrimitiveProcessor&, bool willDrawPoints);
 
     // Sets up vertex attribute pointers and strides. On return indexOffsetInBytes gives the offset
     // an into the index buffer. It does not account for vertices.startIndex() but rather the start
@@ -269,7 +270,8 @@
         ~ProgramCache();
 
         void abandon();
-        GrGLProgram* refProgram(const GrGLGpu* gpu, const GrPipeline&, const GrPrimitiveProcessor&);
+        GrGLProgram* refProgram(const GrGLGpu*, const GrPipeline&, const GrPrimitiveProcessor&,
+                                bool hasPointSize);
 
     private:
         enum {
diff --git a/src/gpu/gl/GrGLGpuProgramCache.cpp b/src/gpu/gl/GrGLGpuProgramCache.cpp
index 8dd5d0c..260e256 100644
--- a/src/gpu/gl/GrGLGpuProgramCache.cpp
+++ b/src/gpu/gl/GrGLGpuProgramCache.cpp
@@ -106,14 +106,15 @@
 
 GrGLProgram* GrGLGpu::ProgramCache::refProgram(const GrGLGpu* gpu,
                                                const GrPipeline& pipeline,
-                                               const GrPrimitiveProcessor& primProc) {
+                                               const GrPrimitiveProcessor& primProc,
+                                               bool isPoints) {
 #ifdef PROGRAM_CACHE_STATS
     ++fTotalRequests;
 #endif
 
     // Get GrGLProgramDesc
     GrProgramDesc desc;
-    if (!GrProgramDesc::Build(&desc, primProc, pipeline, *gpu->glCaps().glslCaps())) {
+    if (!GrProgramDesc::Build(&desc, primProc, isPoints, pipeline, *gpu->glCaps().glslCaps())) {
         GrCapsDebugf(gpu->caps(), "Failed to gl program descriptor!\n");
         return nullptr;
     }
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
index 8508cfb..cbf2041 100644
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -149,7 +149,7 @@
                                    const GrPrimitiveProcessor& primProc,
                                    const GrStencilSettings& stencilPassSettings,
                                    const GrPath* path) {
-    if (!this->gpu()->flushGLState(pipeline, primProc)) {
+    if (!this->gpu()->flushGLState(pipeline, primProc, false)) {
         return;
     }
     const GrGLPath* glPath = static_cast<const GrGLPath*>(path);
@@ -181,7 +181,7 @@
                                     PathTransformType transformType, int count) {
     SkDEBUGCODE(verify_floats(transformValues, gXformType2ComponentCount[transformType] * count));
 
-    if (!this->gpu()->flushGLState(pipeline, primProc)) {
+    if (!this->gpu()->flushGLState(pipeline, primProc, false)) {
         return;
     }
     this->flushPathStencilSettings(stencilPassSettings);
diff --git a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
index 4931e0f..f8302b3 100644
--- a/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLVertexShaderBuilder.cpp
@@ -46,8 +46,10 @@
                           posVar.c_str(), fRtAdjustName, fRtAdjustName);
     }
     // We could have the GrGeometryProcessor do this, but its just easier to have it performed
-    // here. If we ever need to set variable pointsize, then we can reinvestigate
-    this->codeAppend("gl_PointSize = 1.0;");
+    // here. If we ever need to set variable pointsize, then we can reinvestigate.
+    if (this->getProgramBuilder()->desc().header().fHasPointSize) {
+        this->codeAppend("gl_PointSize = 1.0;");
+    }
 }
 
 void GrGLSLVertexBuilder::onFinalize() {
diff --git a/src/gpu/instanced/GLInstancedRendering.cpp b/src/gpu/instanced/GLInstancedRendering.cpp
index bd014ec..dabfe4e 100644
--- a/src/gpu/instanced/GLInstancedRendering.cpp
+++ b/src/gpu/instanced/GLInstancedRendering.cpp
@@ -204,7 +204,7 @@
     if (!fDrawIndirectBuffer && !fGLDrawCmdsInfo) {
         return; // beginFlush was not successful.
     }
-    if (!this->glGpu()->flushGLState(pipeline, instProc)) {
+    if (!this->glGpu()->flushGLState(pipeline, instProc, false)) {
         return;
     }
 
diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp
index 50250a5..73ff62e 100644
--- a/src/gpu/vk/GrVkPipelineState.cpp
+++ b/src/gpu/vk/GrVkPipelineState.cpp
@@ -487,7 +487,8 @@
                                     const GrPipeline& pipeline,
                                     GrPrimitiveType primitiveType,
                                     const GrGLSLCaps& caps) {
-    if (!INHERITED::Build(desc, primProc, pipeline, caps)) {
+    if (!INHERITED::Build(desc, primProc, primitiveType == kPoints_GrPrimitiveType, pipeline,
+                          caps)) {
         return false;
     }