Revert of Cleanup legacy NVPR-related definitions (patchset #4 id:60001 of https...
authorjvanverth <jvanverth@google.com>
Tue, 30 Jun 2015 16:40:38 +0000 (09:40 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 30 Jun 2015 16:40:38 +0000 (09:40 -0700)
Reason for revert:
Breaks the Ubuntu *SAN bots.

Original issue's description:
> Cleanup legacy NVPR-related definitions
>
> Fixed-function NVPR codepaths were removed a while ago. Only NVPR API
> version 1.3 (PathFragmentInputGen) was left working. Remove
> backwards-compatibility code that was left behind.
>
> Remove some NVPR API function typedefs that were left from initial
> commits.
>
> Remove PathCoords function pointer from GrGLInterface, it has
> never been called and causes problems in the future, since it will
> not be implemented in the Chromium pseudo extension.
>
> Committed: https://skia.googlesource.com/skia/+/fb8d6884e0e01d0c2f8596adf5af1efb0d08de7e
>
> Committed: https://skia.googlesource.com/skia/+/e35b5d99d8dfcc6b2be844df28cba47436380809

TBR=joshualitt@google.com,cdalton@nvidia.com,bsalomon@google.com,kkinnunen@nvidia.com
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Review URL: https://codereview.chromium.org/1219663005

include/gpu/gl/GrGLFunctions.h
include/gpu/gl/GrGLInterface.h
src/gpu/GrContextFactory.cpp
src/gpu/gl/GrGLAssembleInterface.cpp
src/gpu/gl/GrGLCaps.cpp
src/gpu/gl/GrGLCaps.h
src/gpu/gl/GrGLGpu.h
src/gpu/gl/GrGLInterface.cpp
src/gpu/gl/GrGLPathRendering.cpp
src/gpu/gl/GrGLPathRendering.h

index f5240c5..a3b9cca 100644 (file)
@@ -236,6 +236,15 @@ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLViewportProc)(GrGLint x, GrGLint y, G
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMatrixLoadfProc)(GrGLenum matrixMode, const GrGLfloat* m);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLMatrixLoadIdentityProc)(GrGLenum);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathCommandsProc)(GrGLuint path, GrGLsizei numCommands, const GrGLubyte *commands, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathCoordsProc)(GrGLuint path, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathSubCoordsProc)(GrGLuint path, GrGLsizei coordStart, GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathStringProc)(GrGLuint path, GrGLenum format, GrGLsizei length, const GrGLvoid *pathString);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathGlyphsProc)(GrGLuint firstPathName, GrGLenum fontTarget, const GrGLvoid *fontName, GrGLbitfield fontStyle, GrGLsizei numGlyphs, GrGLenum type, const GrGLvoid *charcodes, GrGLenum handleMissingGlyphs, GrGLuint pathParameterTemplate, GrGLfloat emScale);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathGlyphRangeProc)(GrGLuint firstPathName, GrGLenum fontTarget, const GrGLvoid *fontName, GrGLbitfield fontStyle, GrGLuint firstGlyph, GrGLsizei numGlyphs, GrGLenum handleMissingGlyphs, GrGLuint pathParameterTemplate, GrGLfloat emScale);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLWeightPathsProc)(GrGLuint resultPath, GrGLsizei numPaths, const GrGLuint paths[], const GrGLfloat weights[]);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCopyPathProc)(GrGLuint resultPath, GrGLuint srcPath);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLInterpolatePathsProc)(GrGLuint resultPath, GrGLuint pathA, GrGLuint pathB, GrGLfloat weight);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLTransformPathProc)(GrGLuint resultPath, GrGLuint srcPath, GrGLenum transformType, const GrGLfloat *transformValues);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathParameteriProc)(GrGLuint path, GrGLenum pname, GrGLint value);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathParameterfProc)(GrGLuint path, GrGLenum pname, GrGLfloat value);
 typedef GrGLuint (GR_GL_FUNCTION_TYPE* GrGLGenPathsProc)(GrGLsizei range);
@@ -246,6 +255,7 @@ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilFillPathProc)(GrGLuint path, G
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilStrokePathProc)(GrGLuint path, GrGLint reference, GrGLuint mask);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLStencilStrokePathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum transformType, const GrGLfloat *transformValues);
+typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLPathTexGenProc)(GrGLenum texCoordSet, GrGLenum genMode, GrGLint components, const GrGLfloat *coeffs);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverFillPathProc)(GrGLuint path, GrGLenum coverMode);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverStrokePathProc)(GrGLuint name, GrGLenum coverMode);
 typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GrGLCoverFillPathInstancedProc)(GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues);
index 9a71758..8626dc3 100644 (file)
@@ -329,6 +329,7 @@ public:
         GLPtr<GrGLMatrixLoadIdentityProc> fMatrixLoadIdentity;
         GLPtr<GrGLGetProgramResourceLocationProc> fGetProgramResourceLocation;
         GLPtr<GrGLPathCommandsProc> fPathCommands;
+        GLPtr<GrGLPathCoordsProc> fPathCoords;
         GLPtr<GrGLPathParameteriProc> fPathParameteri;
         GLPtr<GrGLPathParameterfProc> fPathParameterf;
         GLPtr<GrGLGenPathsProc> fGenPaths;
@@ -339,6 +340,7 @@ public:
         GLPtr<GrGLStencilStrokePathProc> fStencilStrokePath;
         GLPtr<GrGLStencilFillPathInstancedProc> fStencilFillPathInstanced;
         GLPtr<GrGLStencilStrokePathInstancedProc> fStencilStrokePathInstanced;
+        GLPtr<GrGLPathTexGenProc> fPathTexGen;
         GLPtr<GrGLCoverFillPathProc> fCoverFillPath;
         GLPtr<GrGLCoverStrokePathProc> fCoverStrokePath;
         GLPtr<GrGLCoverFillPathInstancedProc> fCoverFillPathInstanced;
index f62c6fe..7df1917 100755 (executable)
@@ -17,7 +17,7 @@
 #endif
 #include "gl/SkGLContext.h"
 #include "gl/SkNullGLContext.h"
-#include "GrCaps.h"
+
 
 GrContext* GrContextFactory::get(GLContextType type, GrGLStandard forcedGpuAPI) {
     for (int i = 0; i < fContexts.count(); ++i) {
@@ -60,9 +60,13 @@ GrContext* GrContextFactory::get(GLContextType type, GrGLStandard forcedGpuAPI)
 
     SkASSERT(glCtx->isValid());
 
-    // Block NVPR from non-NVPR types.
+    // Ensure NVPR is available for the NVPR type and block it from other types.
     SkAutoTUnref<const GrGLInterface> glInterface(SkRef(glCtx->gl()));
-    if (kNVPR_GLContextType != type) {
+    if (kNVPR_GLContextType == type) {
+        if (!glInterface->hasExtension("GL_NV_path_rendering")) {
+            return NULL;
+        }
+    } else {
         glInterface.reset(GrGLInterfaceRemoveNVPR(glInterface));
         if (!glInterface) {
             return NULL;
@@ -75,13 +79,6 @@ GrContext* GrContextFactory::get(GLContextType type, GrGLStandard forcedGpuAPI)
     if (!grCtx.get()) {
         return NULL;
     }
-    // Ensure path rendering support is available for the NVPR type
-    if (kNVPR_GLContextType == type) {
-        if (!grCtx->caps()->shaderCaps()->pathRenderingSupport()) {
-            return NULL;
-        }
-    }
-
     GPUContext& ctx = fContexts.push_back();
     ctx.fGLContext = glCtx.get();
     ctx.fGLContext->ref();
index 3f66c03..1fe53eb 100644 (file)
@@ -273,6 +273,7 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
         GET_PROC_SUFFIX(MatrixLoadf, EXT);
         GET_PROC_SUFFIX(MatrixLoadIdentity, EXT);
         GET_PROC_SUFFIX(PathCommands, NV);
+        GET_PROC_SUFFIX(PathCoords, NV);
         GET_PROC_SUFFIX(PathParameteri, NV);
         GET_PROC_SUFFIX(PathParameterf, NV);
         GET_PROC_SUFFIX(GenPaths, NV);
@@ -283,14 +284,17 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
         GET_PROC_SUFFIX(StencilStrokePath, NV);
         GET_PROC_SUFFIX(StencilFillPathInstanced, NV);
         GET_PROC_SUFFIX(StencilStrokePathInstanced, NV);
+        GET_PROC_SUFFIX(PathTexGen, NV);
         GET_PROC_SUFFIX(CoverFillPath, NV);
         GET_PROC_SUFFIX(CoverStrokePath, NV);
         GET_PROC_SUFFIX(CoverFillPathInstanced, NV);
         GET_PROC_SUFFIX(CoverStrokePathInstanced, NV);
+        // NV_path_rendering v1.2 (These methods may not be present)
         GET_PROC_SUFFIX(StencilThenCoverFillPath, NV);
         GET_PROC_SUFFIX(StencilThenCoverStrokePath, NV);
         GET_PROC_SUFFIX(StencilThenCoverFillPathInstanced, NV);
         GET_PROC_SUFFIX(StencilThenCoverStrokePathInstanced, NV);
+        // NV_path_rendering v1.3 (These methods may not be present)
         GET_PROC_SUFFIX(ProgramPathFragmentInputGen, NV);
     }
 
@@ -678,6 +682,7 @@ const GrGLInterface* GrGLAssembleGLESInterface(void* ctx, GrGLGetProc get) {
         GET_PROC_SUFFIX(MatrixLoadf, EXT);
         GET_PROC_SUFFIX(MatrixLoadIdentity, EXT);
         GET_PROC_SUFFIX(PathCommands, NV);
+        GET_PROC_SUFFIX(PathCoords, NV);
         GET_PROC_SUFFIX(PathParameteri, NV);
         GET_PROC_SUFFIX(PathParameterf, NV);
         GET_PROC_SUFFIX(GenPaths, NV);
index 539212c..feb45ea 100644 (file)
@@ -279,7 +279,21 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
     * GrShaderCaps fields
     **************************************************************************/
 
-    glslCaps->fPathRenderingSupport = this->hasPathRenderingSupport(ctxInfo, gli);
+    glslCaps->fPathRenderingSupport = ctxInfo.hasExtension("GL_NV_path_rendering");
+
+    if (glslCaps->fPathRenderingSupport) {
+        if (kGL_GrGLStandard == standard) {
+            // We only support v1.3+ of GL_NV_path_rendering which allows us to
+            // set individual fragment inputs with ProgramPathFragmentInputGen. The API
+            // additions are detected by checking the existence of the function.
+            glslCaps->fPathRenderingSupport = ((ctxInfo.version() >= GR_GL_VER(4, 3) ||
+                ctxInfo.hasExtension("GL_ARB_program_interface_query")) &&
+                gli->fFunctions.fProgramPathFragmentInputGen);
+        }
+        else {
+            glslCaps->fPathRenderingSupport = ctxInfo.version() >= GR_GL_VER(3, 1);
+        }
+    }
 
     // For now these two are equivalent but we could have dst read in shader via some other method
     glslCaps->fDstReadInShaderSupport = glslCaps->fFBFetchSupport;
@@ -463,35 +477,6 @@ void GrGLCaps::init(const GrContextOptions& contextOptions,
     glslCaps->applyOptionsOverrides(contextOptions);
 }
 
-bool GrGLCaps::hasPathRenderingSupport(const GrGLContextInfo& ctxInfo, const GrGLInterface* gli) {
-    if (!ctxInfo.hasExtension("GL_NV_path_rendering")) {
-        return false;
-    }
-    if (kGL_GrGLStandard == ctxInfo.standard()) {
-        if (ctxInfo.version() < GR_GL_VER(4, 3) &&
-            !ctxInfo.hasExtension("GL_ARB_program_interface_query")) {
-            return false;
-        }
-    } else {
-        if (ctxInfo.version() < GR_GL_VER(3, 1)) {
-            return false;
-        }
-    }
-    // We only support v1.3+ of GL_NV_path_rendering which allows us to
-    // set individual fragment inputs with ProgramPathFragmentInputGen. The API
-    // additions are detected by checking the existence of the function.
-    // We also use *Then* functions that not all drivers might have. Check
-    // them for consistency.
-    if (NULL == gli->fFunctions.fStencilThenCoverFillPath ||
-        NULL == gli->fFunctions.fStencilThenCoverStrokePath ||
-        NULL == gli->fFunctions.fStencilThenCoverFillPathInstanced ||
-        NULL == gli->fFunctions.fStencilThenCoverStrokePathInstanced ||
-        NULL == gli->fFunctions.fProgramPathFragmentInputGen) {
-        return false;
-    }
-    return true;
-}
-
 void GrGLCaps::initConfigRenderableTable(const GrGLContextInfo& ctxInfo) {
     // OpenGL < 3.0
     //  no support for render targets unless the GL_ARB_framebuffer_object
index ac90aa1..1e07a76 100644 (file)
@@ -281,7 +281,6 @@ public:
 
 private:
     void init(const GrContextOptions&, const GrGLContextInfo&, const GrGLInterface*);
-    bool hasPathRenderingSupport(const GrGLContextInfo&, const GrGLInterface*);
 
     /**
      * Maintains a bit per GrPixelConfig. It is used to avoid redundantly
index e5cd7a9..4872db7 100644 (file)
@@ -54,7 +54,8 @@ public:
 
     void discard(GrRenderTarget*) override;
 
-    // Used by GrGLProgram to configure OpenGL state.
+    // Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL
+    // state.
     void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
 
     // GrGpu overrides
index 56f1e59..3d44f6d 100644 (file)
@@ -40,6 +40,7 @@ const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
 
     newInterface->fExtensions.remove("GL_NV_path_rendering");
     newInterface->fFunctions.fPathCommands = NULL;
+    newInterface->fFunctions.fPathCoords = NULL;
     newInterface->fFunctions.fPathParameteri = NULL;
     newInterface->fFunctions.fPathParameterf = NULL;
     newInterface->fFunctions.fGenPaths = NULL;
@@ -50,6 +51,7 @@ const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
     newInterface->fFunctions.fStencilStrokePath = NULL;
     newInterface->fFunctions.fStencilFillPathInstanced = NULL;
     newInterface->fFunctions.fStencilStrokePathInstanced = NULL;
+    newInterface->fFunctions.fPathTexGen = NULL;
     newInterface->fFunctions.fCoverFillPath = NULL;
     newInterface->fFunctions.fCoverStrokePath = NULL;
     newInterface->fFunctions.fCoverFillPathInstanced = NULL;
@@ -487,6 +489,7 @@ bool GrGLInterface::validate() const {
         if (NULL == fFunctions.fMatrixLoadf ||
             NULL == fFunctions.fMatrixLoadIdentity ||
             NULL == fFunctions.fPathCommands ||
+            NULL == fFunctions.fPathCoords ||
             NULL == fFunctions.fPathParameteri ||
             NULL == fFunctions.fPathParameterf ||
             NULL == fFunctions.fGenPaths ||
@@ -500,21 +503,24 @@ bool GrGLInterface::validate() const {
             NULL == fFunctions.fCoverFillPath ||
             NULL == fFunctions.fCoverStrokePath ||
             NULL == fFunctions.fCoverFillPathInstanced ||
-            NULL == fFunctions.fCoverStrokePathInstanced
-#if 0
-            // List of functions that Skia uses, but which have been added since the initial release
-            // of NV_path_rendering driver. We do not want to fail interface validation due to
-            // missing features, we will just not use the extension.
-            // Update this list -> update GrGLCaps::hasPathRenderingSupport too.
-            || NULL == fFunctions.fStencilThenCoverFillPath ||
-            NULL == fFunctions.fStencilThenCoverStrokePath ||
-            NULL == fFunctions.fStencilThenCoverFillPathInstanced ||
-            NULL == fFunctions.fStencilThenCoverStrokePathInstanced ||
-            NULL == fFunctions.fProgramPathFragmentInputGen
-#endif
-            ) {
+            NULL == fFunctions.fCoverStrokePathInstanced) {
             RETURN_FALSE_INTERFACE
         }
+        if (kGL_GrGLStandard == fStandard) {
+            // Some methods only exist on desktop
+            if (NULL == fFunctions.fPathTexGen) {
+                RETURN_FALSE_INTERFACE
+            }
+        } else {
+            // All additions through v1.3 exist on GLES
+            if (NULL == fFunctions.fStencilThenCoverFillPath ||
+                NULL == fFunctions.fStencilThenCoverStrokePath ||
+                NULL == fFunctions.fStencilThenCoverFillPathInstanced ||
+                NULL == fFunctions.fStencilThenCoverStrokePathInstanced ||
+                NULL == fFunctions.fProgramPathFragmentInputGen) {
+                RETURN_FALSE_INTERFACE
+            }
+        }
     }
 
     if (fExtensions.has("GL_EXT_raster_multisample")) {
index ffdbbda..eb9f5a8 100644 (file)
@@ -61,6 +61,16 @@ static GrGLenum gr_stencil_op_to_gl_path_rendering_fill_mode(GrStencilOp op) {
 
 GrGLPathRendering::GrGLPathRendering(GrGLGpu* gpu)
     : GrPathRendering(gpu) {
+    const GrGLInterface* glInterface = gpu->glInterface();
+    fCaps.stencilThenCoverSupport =
+        NULL != glInterface->fFunctions.fStencilThenCoverFillPath &&
+        NULL != glInterface->fFunctions.fStencilThenCoverStrokePath &&
+        NULL != glInterface->fFunctions.fStencilThenCoverFillPathInstanced &&
+        NULL != glInterface->fFunctions.fStencilThenCoverStrokePathInstanced;
+    fCaps.fragmentInputGenSupport =
+        NULL != glInterface->fFunctions.fProgramPathFragmentInputGen;
+
+    SkASSERT(fCaps.fragmentInputGenSupport);
 }
 
 GrGLPathRendering::~GrGLPathRendering() {
@@ -75,6 +85,7 @@ void GrGLPathRendering::resetContext() {
     // we don't use the model view matrix.
     GL_CALL(MatrixLoadIdentity(GR_GL_PATH_MODELVIEW));
 
+    SkASSERT(fCaps.fragmentInputGenSupport);
     fHWPathStencilSettings.invalidate();
 }
 
@@ -134,11 +145,9 @@ void GrGLPathRendering::onDrawPath(const DrawPathArgs& args, const GrPath* path)
         if (glPath->shouldFill()) {
             GL_CALL(StencilFillPath(glPath->pathID(), fillMode, writeMask));
         }
-        GL_CALL(StencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask,
-                                           GR_GL_BOUNDING_BOX));
+        this->stencilThenCoverStrokePath(glPath->pathID(), 0xffff, writeMask, GR_GL_BOUNDING_BOX);
     } else {
-        GL_CALL(StencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask,
-                                         GR_GL_BOUNDING_BOX));
+        this->stencilThenCoverFillPath(glPath->pathID(), fillMode, writeMask, GR_GL_BOUNDING_BOX);
     }
 }
 
@@ -168,21 +177,22 @@ void GrGLPathRendering::onDrawPaths(const DrawPathArgs& args, const GrPathRange*
                             fillMode, writeMask, gXformType2GLType[transformType],
                             transformValues));
         }
-        GL_CALL(StencilThenCoverStrokePathInstanced(
+        this->stencilThenCoverStrokePathInstanced(
                             count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(),
                             0xffff, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
-                            gXformType2GLType[transformType], transformValues));
+                            gXformType2GLType[transformType], transformValues);
     } else {
-        GL_CALL(StencilThenCoverFillPathInstanced(
+        this->stencilThenCoverFillPathInstanced(
                             count, gIndexType2GLType[indexType], indices, glPathRange->basePathID(),
                             fillMode, writeMask, GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
-                            gXformType2GLType[transformType], transformValues));
+                            gXformType2GLType[transformType], transformValues);
     }
 }
 
 void GrGLPathRendering::setProgramPathFragmentInputTransform(GrGLuint program, GrGLint location,
                                                              GrGLenum genMode, GrGLint components,
                                                              const SkMatrix& matrix) {
+    SkASSERT(caps().fragmentInputGenSupport);
     GrGLfloat coefficients[3 * 3];
     SkASSERT(components >= 1 && components <= 3);
 
@@ -290,6 +300,58 @@ void GrGLPathRendering::flushPathStencilSettings(const GrStencilSettings& stenci
     }
 }
 
+inline void GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
+                                                     GrGLuint mask, GrGLenum coverMode) {
+    if (caps().stencilThenCoverSupport) {
+        GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
+        return;
+    }
+    GL_CALL(StencilFillPath(path, fillMode, mask));
+    GL_CALL(CoverFillPath(path, coverMode));
+}
+
+inline void GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
+                                                       GrGLuint mask, GrGLenum coverMode) {
+    if (caps().stencilThenCoverSupport) {
+        GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
+        return;
+    }
+    GL_CALL(StencilStrokePath(path, reference, mask));
+    GL_CALL(CoverStrokePath(path, coverMode));
+}
+
+inline void GrGLPathRendering::stencilThenCoverFillPathInstanced(
+             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
+             GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
+             GrGLenum transformType, const GrGLfloat *transformValues) {
+    if (caps().stencilThenCoverSupport) {
+        GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
+                                                  mask, coverMode, transformType, transformValues));
+        return;
+    }
+    GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+                                     fillMode, mask, transformType, transformValues));
+    GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+                                   coverMode, transformType, transformValues));
+}
+
+inline void GrGLPathRendering::stencilThenCoverStrokePathInstanced(
+        GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
+        GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
+        GrGLenum transformType, const GrGLfloat *transformValues) {
+    if (caps().stencilThenCoverSupport) {
+        GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                                                    reference, mask, coverMode, transformType,
+                                                    transformValues));
+        return;
+    }
+
+    GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                                       reference, mask, transformType, transformValues));
+    GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                                     coverMode, transformType, transformValues));
+}
+
 inline GrGLGpu* GrGLPathRendering::gpu() {
     return static_cast<GrGLGpu*>(fGpu);
 }
index 86cf1b1..20fd496 100644 (file)
@@ -65,8 +65,35 @@ protected:
     void onDrawPaths(const DrawPathArgs&, const GrPathRange*, const void* indices, PathIndexType,
                      const float transformValues[], PathTransformType, int count) override;
 private:
+    /**
+     * Mark certain functionality as not supported if the driver version is too
+     * old and a backup implementation is not practical.
+     */
+    struct Caps {
+        bool stencilThenCoverSupport : 1;
+        bool fragmentInputGenSupport : 1;
+    };
+    const Caps& caps() const { return fCaps; }
+
     void flushPathStencilSettings(const GrStencilSettings&);
 
+    // NV_path_rendering v1.2
+    void stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
+                                  GrGLuint mask, GrGLenum coverMode);
+
+    void stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
+                                    GrGLuint mask, GrGLenum coverMode);
+
+    void stencilThenCoverFillPathInstanced(
+        GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
+                         GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
+                         GrGLenum transformType, const GrGLfloat *transformValues);
+
+    void stencilThenCoverStrokePathInstanced(
+                         GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
+                         GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
+                         GrGLenum transformType, const GrGLfloat *transformValues);
+
     struct MatrixState {
         SkMatrix        fViewMatrix;
         SkISize         fRenderTargetSize;
@@ -101,8 +128,14 @@ private:
     GrGLGpu* gpu();
 
     SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
+    Caps fCaps;
     MatrixState fHWProjectionMatrixState;
     GrStencilSettings fHWPathStencilSettings;
+    struct PathTexGenData {
+        GrGLenum  fMode;
+        GrGLint   fNumComponents;
+        GrGLfloat fCoefficients[3 * 3];
+    };
 };
 
 #endif