added support for glMinSampleShading
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1812223002

Review URL: https://codereview.chromium.org/1812223002
diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h
index 398517c..9c62adf 100644
--- a/include/gpu/GrCaps.h
+++ b/include/gpu/GrCaps.h
@@ -269,6 +269,8 @@
         is not initialized (even if not read by draw calls). */
     bool mustClearUploadedBufferData() const { return fMustClearUploadedBufferData; }
 
+    bool sampleShadingSupport() const { return fSampleShadingSupport; }
+
 protected:
     /** Subclasses must call this at the end of their constructors in order to apply caps
         overrides requested by the client. Note that overrides will only reduce the caps never
@@ -303,6 +305,8 @@
     // ANGLE workaround
     bool fPreferVRAMUseOverFlushes                   : 1;
 
+    bool fSampleShadingSupport                       : 1;
+
     BlendEquationSupport fBlendEquationSupport;
     uint32_t fAdvBlendEqBlacklist;
     GR_STATIC_ASSERT(kLast_GrBlendEquation < 32);
diff --git a/include/gpu/gl/GrGLFunctions.h b/include/gpu/gl/GrGLFunctions.h
index 5708cce..ea1ed65 100644
--- a/include/gpu/gl/GrGLFunctions.h
+++ b/include/gpu/gl/GrGLFunctions.h
@@ -235,6 +235,9 @@
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLProgramUniformHandleui64Proc)(GrGLuint program, GrGLint location, GrGLuint64 v0);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLProgramUniformHandleui64vProc)(GrGLuint program, GrGLint location, GrGLsizei count, const GrGLuint64 *value);
 
+/* ARB_sample_shading */
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMinSampleShadingProc)(GrGLfloat value);
+
 /* EXT_direct_state_access */
 // (In the future some of these methods may be omitted)
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTextureParameteriProc)(GrGLuint texture, GrGLenum target, GrGLenum pname, GrGLint param);
diff --git a/include/gpu/gl/GrGLInterface.h b/include/gpu/gl/GrGLInterface.h
index 545a66d..1e2ac8f 100644
--- a/include/gpu/gl/GrGLInterface.h
+++ b/include/gpu/gl/GrGLInterface.h
@@ -369,6 +369,9 @@
         GrGLFunction<GrGLProgramUniformHandleui64Proc> fProgramUniformHandleui64;
         GrGLFunction<GrGLProgramUniformHandleui64vProc> fProgramUniformHandleui64v;
 
+        /* ARB_sample_shading */
+        GrGLFunction<GrGLMinSampleShadingProc> fMinSampleShading;
+
         /* EXT_direct_state_access */
         // We use the EXT verson because it is more expansive and interacts with more extensions
         // than the ARB or core (4.5) versions. We may switch and/or omit methods in the future.
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index 784e401..c192c68 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -98,6 +98,7 @@
     fSupportsInstancedDraws = false;
     fFullClearIsFree = false;
     fMustClearUploadedBufferData = false;
+    fSampleShadingSupport = false;
 
     fUseDrawInsteadOfClear = false;
 
diff --git a/src/gpu/GrGeometryProcessor.h b/src/gpu/GrGeometryProcessor.h
index 05afd53..1dbf153 100644
--- a/src/gpu/GrGeometryProcessor.h
+++ b/src/gpu/GrGeometryProcessor.h
@@ -21,7 +21,8 @@
 public:
     GrGeometryProcessor()
         : fWillUseGeoShader(false)
-        , fLocalCoordsType(kUnused_LocalCoordsType) {}
+        , fLocalCoordsType(kUnused_LocalCoordsType)
+        , fSampleShading(0.0) {}
 
     bool willUseGeoShader() const override { return fWillUseGeoShader; }
 
@@ -33,6 +34,15 @@
         return kHasExplicit_LocalCoordsType == fLocalCoordsType;
     }
 
+    /**
+     * Returns the minimum fraction of samples for which the fragment shader will be run. For
+     * instance, if sampleShading is 0.5 in MSAA16 mode, the fragment shader will run a minimum of
+     * 8 times per pixel. The default value is zero.
+     */
+    float getSampleShading() const override {
+        return fSampleShading;
+    }
+
 protected:
     /**
      * Subclasses call this from their constructor to register vertex attributes.  Attributes
@@ -74,9 +84,14 @@
         fLocalCoordsType = kHasTransformed_LocalCoordsType;
     }
 
+    void setSampleShading(float sampleShading) {
+        fSampleShading = sampleShading;
+    }
+
 private:
     bool fWillUseGeoShader;
     LocalCoordsType fLocalCoordsType;
+    float fSampleShading;
 
     typedef GrPrimitiveProcessor INHERITED;
 };
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index e8bb449..3300ec7 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -217,6 +217,10 @@
      */
     virtual const char* getDestColorOverride() const { return nullptr; }
     
+    virtual float getSampleShading() const {
+        return 0.0;
+    }
+
 protected:
     GrPrimitiveProcessor() : fVertexStride(0) {}
 
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 6672d22..d1b2fb6 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -515,6 +515,10 @@
         GET_EGL_PROC_SUFFIX(DestroyImage, KHR);
     }
 
+    if (glVer >= GR_GL_VER(4,0) || extensions.has("GL_ARB_sample_shading")) {
+        GET_PROC(MinSampleShading);
+    }
+
     interface->fStandard = kGL_GrGLStandard;
     interface->fExtensions.swap(&extensions);
 
@@ -893,6 +897,10 @@
         GET_EGL_PROC_SUFFIX(DestroyImage, KHR);
     }
 
+    if (extensions.has("GL_OES_sample_shading")) {
+        GET_PROC_SUFFIX(MinSampleShading, OES);
+    }
+
     interface->fStandard = kGLES_GrGLStandard;
     interface->fExtensions.swap(&extensions);
 
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index faccbd1..599a0e0 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -533,6 +533,14 @@
         fTextureSwizzleSupport = false;
     }
 
+    if (kGL_GrGLStandard == standard) {
+        if (version >= GR_GL_VER(4, 0) || ctxInfo.hasExtension("GL_ARB_sample_shading")) {
+            fSampleShadingSupport = true;
+        }
+    } else if (ctxInfo.hasExtension("GL_OES_sample_shading")) {
+        fSampleShadingSupport = true;
+    }
+
     // Requires fTextureRedSupport, fTextureSwizzleSupport, msaa support, ES compatibility have
     // already been detected.
     this->initConfigTable(ctxInfo, gli, glslCaps);
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index ff4c457..98b328b 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -165,7 +165,8 @@
 #define GR_GL_LINE_STIPPLE                   0x0B24
 #define GR_GL_FRAMEBUFFER_SRGB               0x8DB9
 #define GR_GL_SHADER_PIXEL_LOCAL_STORAGE     0x8F64
-
+#define GR_GL_SAMPLE_SHADING                 0x8C36
+ 
 /* ErrorCode */
 #define GR_GL_NO_ERROR                       0
 #define GR_GL_INVALID_ENUM                   0x0500
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index 3bbc77a..349ef9a 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -233,6 +233,7 @@
     }
     fHWPLSEnabled = false;
     fPLSHasBeenUsed = false;
+    fHWMinSampleShading = 0.0;
 }
 
 GrGLGpu::~GrGLGpu() {
@@ -2070,12 +2071,26 @@
     this->disableScissor();
 }
 
+void GrGLGpu::flushMinSampleShading(float minSampleShading) {
+    if (fHWMinSampleShading != minSampleShading) {
+        if (minSampleShading > 0.0) {
+            GL_CALL(Enable(GR_GL_SAMPLE_SHADING));
+            GL_CALL(MinSampleShading(minSampleShading));
+        }
+        else {
+            GL_CALL(Disable(GR_GL_SAMPLE_SHADING));
+        }
+        fHWMinSampleShading = minSampleShading;
+    }
+}
+
 bool GrGLGpu::flushGLState(const GrPipeline& pipeline, const GrPrimitiveProcessor& primProc) {
     GrXferProcessor::BlendInfo blendInfo;
     pipeline.getXferProcessor().getBlendInfo(&blendInfo);
 
     this->flushColorWrite(blendInfo.fWriteColor);
     this->flushDrawFace(pipeline.getDrawFace());
+    this->flushMinSampleShading(primProc.getSampleShading());
 
     SkAutoTUnref<GrGLProgram> program(fProgramCache->refProgram(this, pipeline, primProc));
     if (!program) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 61fdb8f..c527b53 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -340,6 +340,8 @@
     // rt is used only if useHWAA is true.
     void flushHWAAState(GrRenderTarget* rt, bool useHWAA, bool stencilEnabled);
 
+    void flushMinSampleShading(float minSampleShading);
+
     // helper for onCreateTexture and writeTexturePixels
     enum UploadType {
         kNewTexture_UploadType,    // we are creating a new texture
@@ -619,6 +621,8 @@
     bool fHWPLSEnabled;
     bool fPLSHasBeenUsed;
 
+    float fHWMinSampleShading;
+
     typedef GrGpu INHERITED;
     friend class GrGLPathRendering; // For accessing setTextureUnit.
 };
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index 728fb3f..32d85b6 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -781,6 +781,17 @@
         }
     }
 
+    if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,0)) ||
+        fExtensions.has("GL_ARB_sample_shading")) {
+        if (nullptr == fFunctions.fMinSampleShading) {
+            RETURN_FALSE_INTERFACE
+        }
+    } else if (kGL_GrGLStandard == fStandard && fExtensions.has("GL_OES_sample_shading")) {
+        if (nullptr == fFunctions.fMinSampleShading) {
+            RETURN_FALSE_INTERFACE
+        }
+    }
+
     if (fExtensions.has("EGL_KHR_image") || fExtensions.has("EGL_KHR_image_base")) {
         if (nullptr == fFunctions.fEGLCreateImage ||
             nullptr == fFunctions.fEGLDestroyImage) {
diff --git a/src/gpu/gl/GrGLTestInterface.cpp b/src/gpu/gl/GrGLTestInterface.cpp
index 7200981..c992587 100644
--- a/src/gpu/gl/GrGLTestInterface.cpp
+++ b/src/gpu/gl/GrGLTestInterface.cpp
@@ -116,6 +116,7 @@
     fFunctions.fMapBufferRange = bind_to_member(this, &GrGLTestInterface::mapBufferRange);
     fFunctions.fMapBufferSubData = bind_to_member(this, &GrGLTestInterface::mapBufferSubData);
     fFunctions.fMapTexSubImage2D = bind_to_member(this, &GrGLTestInterface::mapTexSubImage2D);
+    fFunctions.fMinSampleShading = bind_to_member(this, &GrGLTestInterface::minSampleShading);
     fFunctions.fPixelStorei = bind_to_member(this, &GrGLTestInterface::pixelStorei);
     fFunctions.fPopGroupMarker = bind_to_member(this, &GrGLTestInterface::popGroupMarker);
     fFunctions.fPushGroupMarker = bind_to_member(this, &GrGLTestInterface::pushGroupMarker);
diff --git a/src/gpu/gl/GrGLTestInterface.h b/src/gpu/gl/GrGLTestInterface.h
index f8c5801..6af71fe 100644
--- a/src/gpu/gl/GrGLTestInterface.h
+++ b/src/gpu/gl/GrGLTestInterface.h
@@ -113,6 +113,7 @@
     virtual GrGLvoid* mapBufferRange(GrGLenum target, GrGLintptr offset, GrGLsizeiptr length, GrGLbitfield access) { return nullptr; }
     virtual GrGLvoid* mapBufferSubData(GrGLuint target, GrGLintptr offset, GrGLsizeiptr size, GrGLenum access) { return nullptr; }
     virtual GrGLvoid* mapTexSubImage2D(GrGLenum target, GrGLint level, GrGLint xoffset, GrGLint yoffset, GrGLsizei width, GrGLsizei height, GrGLenum format, GrGLenum type, GrGLenum access) { return nullptr; }
+    virtual GrGLvoid minSampleShading(GrGLfloat value) {}    
     virtual GrGLvoid pixelStorei(GrGLenum pname, GrGLint param) {}
     virtual GrGLvoid popGroupMarker() {}
     virtual GrGLvoid pushGroupMarker(GrGLsizei length, const char* marker) {}
diff --git a/src/gpu/vk/GrVkCaps.cpp b/src/gpu/vk/GrVkCaps.cpp
index 89a5a73..3126ca0 100644
--- a/src/gpu/vk/GrVkCaps.cpp
+++ b/src/gpu/vk/GrVkCaps.cpp
@@ -116,6 +116,7 @@
 
     fStencilWrapOpsSupport = true;
     fOversizedStencilSupport = true;
+    fSampleShadingSupport = SkToBool(featureFlags & kSampleRateShading_GrVkFeatureFlag);
 }
 
 void GrVkCaps::initGLSLCaps(const VkPhysicalDeviceProperties& properties,
diff --git a/src/gpu/vk/GrVkPipeline.cpp b/src/gpu/vk/GrVkPipeline.cpp
index 9c0fd28..794acb0 100644
--- a/src/gpu/vk/GrVkPipeline.cpp
+++ b/src/gpu/vk/GrVkPipeline.cpp
@@ -203,7 +203,9 @@
     SkASSERT(viewportInfo->viewportCount == viewportInfo->scissorCount);
 }
 
-void setup_multisample_state(const GrPipeline& pipeline,
+void setup_multisample_state(const GrPipeline& pipeline, 
+                             const GrPrimitiveProcessor& primProc,
+                             const GrCaps* caps,
                              VkPipelineMultisampleStateCreateInfo* multisampleInfo) {
     memset(multisampleInfo, 0, sizeof(VkPipelineMultisampleStateCreateInfo));
     multisampleInfo->sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
@@ -212,8 +214,10 @@
     int numSamples = pipeline.getRenderTarget()->numColorSamples();
     SkAssertResult(GrSampleCountToVkSampleCount(numSamples,
                    &multisampleInfo->rasterizationSamples));
-    multisampleInfo->sampleShadingEnable = VK_FALSE;
-    multisampleInfo->minSampleShading = 0;
+    float sampleShading = primProc.getSampleShading();
+    SkASSERT(sampleShading == 0.0f || caps->sampleShadingSupport());
+    multisampleInfo->sampleShadingEnable = sampleShading > 0.0f;
+    multisampleInfo->minSampleShading = sampleShading;
     multisampleInfo->pSampleMask = nullptr;
     multisampleInfo->alphaToCoverageEnable = VK_FALSE;
     multisampleInfo->alphaToOneEnable = VK_FALSE;
@@ -427,7 +431,7 @@
     setup_viewport_scissor_state(gpu, pipeline, vkRT, &viewportInfo);
 
     VkPipelineMultisampleStateCreateInfo multisampleInfo;
-    setup_multisample_state(pipeline, &multisampleInfo);
+    setup_multisample_state(pipeline, primProc, gpu->caps(), &multisampleInfo);
 
     // We will only have one color attachment per pipeline.
     VkPipelineColorBlendAttachmentState attachmentStates[1];
diff --git a/src/views/mac/SkNSView.mm b/src/views/mac/SkNSView.mm
index ada79f8..3a096f6 100644
--- a/src/views/mac/SkNSView.mm
+++ b/src/views/mac/SkNSView.mm
@@ -337,6 +337,7 @@
         kCGLPFAStencilSize, (CGLPixelFormatAttribute) 8,
         kCGLPFAAccelerated,
         kCGLPFADoubleBuffer,
+        kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
         (CGLPixelFormatAttribute)0
     };