Revert "Adds a GrGLPathRendering class that wraps the NV_path_rendering"

This reverts commit 5672da0fa54f31c9727568e9dd5fe82c6e1585bc.

This appears to be blocking the Skia roll by causing failures in the blink layout tests on the canvas-lost-gpu-context.html test.

The bisect for this can be seen at:

https://codereview.chromium.org/449473002/

Original issue's description:
> Adds a GrGLPathRendering class that wraps the NV_path_rendering
> extension and manages its various API versions. It also provides
> backup implementations when certain NVpr methods from later API
> versions are not present on the current system.
>
> Committed: https://skia.googlesource.com/skia/+/5672da0fa54f31c9727568e9dd5fe82c6e1585bc
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 8fd173d..4ae50ba 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -14,6 +14,12 @@
 #define GET_PROC_SUFFIX(F, S) functions->f ## F = (GrGL ## F ## Proc) get(ctx, "gl" #F #S)
 #define GET_PROC_LOCAL(F) GrGL ## F ## Proc F = (GrGL ## F ## Proc) get(ctx, "gl" #F)
 
+// The glStencilThenCover* methods are a new addition to NV_path_rendering. They
+// aren't available on all drivers. In the event that they are not present, this
+// function can be used to add methods to the given GrGLInterface that emulate
+// them using the existing glStencil*/glCover* methods.
+static void emulate_nvpr_stencil_then_cover(GrGLInterface*);
+
 const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
     GET_PROC_LOCAL(GetString);
     GET_PROC_LOCAL(GetStringi);
@@ -239,13 +245,18 @@
         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);
+
+        if (NULL == interface->fFunctions.fStencilThenCoverFillPath ||
+            NULL == interface->fFunctions.fStencilThenCoverStrokePath ||
+            NULL == interface->fFunctions.fStencilThenCoverFillPathInstanced ||
+            NULL == interface->fFunctions.fStencilThenCoverFillPathInstanced) {
+            emulate_nvpr_stencil_then_cover(interface);
+        }
     }
 
     if (extensions.has("GL_EXT_debug_marker")) {
@@ -272,3 +283,101 @@
 
     return interface;
 }
+
+static GrGLStencilFillPathProc gStencilFillPath;
+static GrGLCoverFillPathProc gCoverFillPath;
+static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_fill_path(
+                                        GrGLuint path, GrGLenum fillMode,
+                                        GrGLuint mask, GrGLenum coverMode) {
+    gStencilFillPath(path, fillMode, mask);
+    gCoverFillPath(path, coverMode);
+}
+
+
+static GrGLStencilStrokePathProc gStencilStrokePath;
+static GrGLCoverStrokePathProc gCoverStrokePath;
+static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_stroke_path(
+                                        GrGLuint path, GrGLint reference,
+                                        GrGLuint mask, GrGLenum coverMode) {
+    gStencilStrokePath(path, reference, mask);
+    gCoverStrokePath(path, coverMode);
+}
+
+static GrGLStencilFillPathInstancedProc gStencilFillPathInstanced;
+static GrGLCoverFillPathInstancedProc gCoverFillPathInstanced;
+static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_fill_path_instanced(
+                                        GrGLsizei numPaths, GrGLenum pathNameType,
+                                        const GrGLvoid *paths, GrGLuint pathBase,
+                                        GrGLenum fillMode, GrGLuint mask,
+                                        GrGLenum coverMode, GrGLenum transformType,
+                                        const GrGLfloat *transformValues) {
+    gStencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+                              fillMode, mask, transformType, transformValues);
+    gCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
+                            coverMode, transformType, transformValues);
+}
+
+static GrGLStencilStrokePathInstancedProc gStencilStrokePathInstanced;
+static GrGLCoverStrokePathInstancedProc gCoverStrokePathInstanced;
+static GrGLvoid GR_GL_FUNCTION_TYPE stencil_then_cover_stroke_path_instanced(
+                                        GrGLsizei numPaths, GrGLenum pathNameType,
+                                        const GrGLvoid *paths, GrGLuint pathBase,
+                                        GrGLint reference, GrGLuint mask,
+                                        GrGLenum coverMode, GrGLenum transformType,
+                                        const GrGLfloat *transformValues) {
+    gStencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                                reference, mask, transformType, transformValues);
+    gCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
+                              coverMode, transformType, transformValues);
+}
+
+static void emulate_nvpr_stencil_then_cover(GrGLInterface* interface) {
+    if (NULL == gStencilFillPath) {
+        gStencilFillPath = (GrGLStencilFillPathProc)interface->fFunctions.fStencilFillPath;
+    }
+    if (NULL == gCoverFillPath) {
+        gCoverFillPath = (GrGLCoverFillPathProc)interface->fFunctions.fCoverFillPath;
+    }
+    if (NULL == gStencilStrokePath) {
+        gStencilStrokePath = (GrGLStencilStrokePathProc)interface->fFunctions.fStencilStrokePath;
+    }
+    if (NULL == gCoverStrokePath) {
+        gCoverStrokePath = (GrGLCoverStrokePathProc)interface->fFunctions.fCoverStrokePath;
+    }
+    if (NULL == gStencilFillPathInstanced) {
+        gStencilFillPathInstanced = (GrGLStencilFillPathInstancedProc)
+            interface->fFunctions.fStencilFillPathInstanced;
+    }
+    if (NULL == gCoverFillPathInstanced) {
+        gCoverFillPathInstanced = (GrGLCoverFillPathInstancedProc)
+            interface->fFunctions.fCoverFillPathInstanced;
+    }
+    if (NULL == gStencilStrokePathInstanced) {
+        gStencilStrokePathInstanced = (GrGLStencilStrokePathInstancedProc)
+            interface->fFunctions.fStencilStrokePathInstanced;
+    }
+    if (NULL == gCoverStrokePathInstanced) {
+        gCoverStrokePathInstanced = (GrGLCoverStrokePathInstancedProc)
+            interface->fFunctions.fCoverStrokePathInstanced;
+    }
+
+    if (interface->fFunctions.fStencilFillPath != gStencilFillPath ||
+        interface->fFunctions.fCoverFillPath != gCoverFillPath ||
+        interface->fFunctions.fStencilStrokePath != gStencilStrokePath ||
+        interface->fFunctions.fCoverStrokePath != gCoverStrokePath ||
+        interface->fFunctions.fStencilFillPathInstanced != gStencilFillPathInstanced ||
+        interface->fFunctions.fCoverFillPathInstanced != gCoverFillPathInstanced ||
+        interface->fFunctions.fStencilStrokePathInstanced != gStencilStrokePathInstanced ||
+        interface->fFunctions.fCoverStrokePathInstanced != gCoverStrokePathInstanced) {
+        // While not every windowing system requires GetProcAddress to return
+        // the same addresses in different contexts, it is guaranteed to do so
+        // in any context that supports NV_path_rendering.
+        SkFAIL("GetProcAddress returned different addresses for the same nvpr functions");
+        return;
+    }
+
+    interface->fFunctions.fStencilThenCoverFillPath = &stencil_then_cover_fill_path;
+    interface->fFunctions.fStencilThenCoverStrokePath = &stencil_then_cover_stroke_path;
+    interface->fFunctions.fStencilThenCoverFillPathInstanced = &stencil_then_cover_fill_path_instanced;
+    interface->fFunctions.fStencilThenCoverStrokePathInstanced = &stencil_then_cover_stroke_path_instanced;
+}
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index c192611..e9ba32e 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -56,10 +56,6 @@
     newInterface->fFunctions.fCoverStrokePath = NULL;
     newInterface->fFunctions.fCoverFillPathInstanced = NULL;
     newInterface->fFunctions.fCoverStrokePathInstanced = NULL;
-    newInterface->fFunctions.fStencilThenCoverFillPath = NULL;
-    newInterface->fFunctions.fStencilThenCoverStrokePath = NULL;
-    newInterface->fFunctions.fStencilThenCoverFillPathInstanced = NULL;
-    newInterface->fFunctions.fStencilThenCoverStrokePathInstanced = NULL;
     newInterface->fFunctions.fProgramPathFragmentInputGen = NULL;
     return newInterface;
 }
@@ -471,23 +467,18 @@
             NULL == fFunctions.fCoverFillPath ||
             NULL == fFunctions.fCoverStrokePath ||
             NULL == fFunctions.fCoverFillPathInstanced ||
-            NULL == fFunctions.fCoverStrokePathInstanced) {
+            NULL == fFunctions.fCoverStrokePathInstanced ||
+            NULL == fFunctions.fStencilThenCoverFillPath ||
+            NULL == fFunctions.fStencilThenCoverStrokePath ||
+            NULL == fFunctions.fStencilThenCoverFillPathInstanced ||
+            NULL == fFunctions.fStencilThenCoverStrokePathInstanced) {
             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
-            }
+        // Currently ProgramPathFragmentInputGen is not used on
+        // OpenGL, rather PathTexGen is.
+        if ((kGL_GrGLStandard == fStandard && NULL == fFunctions.fPathTexGen) ||
+            (kGLES_GrGLStandard == fStandard && NULL == fFunctions.fProgramPathFragmentInputGen)) {
+            RETURN_FALSE_INTERFACE
         }
     }
 
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
index 6f158cd..1c74580 100644
--- a/src/gpu/gl/GrGLPath.cpp
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -7,9 +7,13 @@
  */
 
 #include "GrGLPath.h"
-#include "GrGLPathRendering.h"
 #include "GrGpuGL.h"
 
+#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
+
+#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X)
+
 namespace {
 inline GrGLubyte verb_to_gl_path_cmd(SkPath::Verb verb) {
     static const GrGLubyte gTable[] = {
@@ -81,11 +85,10 @@
 
 static const bool kIsWrapped = false; // The constructor creates the GL path object.
 
-void GrGLPath::InitPathObject(GrGpuGL* gpu,
+void GrGLPath::InitPathObject(const GrGLInterface* gl,
                               GrGLuint pathID,
                               const SkPath& skPath,
                               const SkStrokeRec& stroke) {
-    GrGLPathRendering* pr = gpu->pathRendering();
     SkSTArray<16, GrGLubyte, true> pathCommands;
     SkSTArray<16, SkPoint, true> pathPoints;
 
@@ -106,25 +109,30 @@
     }
     SkASSERT(pathPoints.count() == numPts);
 
-    pr->pathCommands(pathID, verbCnt, &pathCommands[0], 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]);
+    GR_GL_CALL(gl, PathCommands(pathID,
+                                verbCnt, &pathCommands[0],
+                                2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]));
+
     if (stroke.needToApply()) {
         SkASSERT(!stroke.isHairlineStyle());
-        pr->pathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth()));
-        pr->pathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter()));
+        GR_GL_CALL(gl, PathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth())));
+        GR_GL_CALL(gl, PathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter())));
         GrGLenum join = join_to_gl_join(stroke.getJoin());
-        pr->pathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join);
+        GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join));
         GrGLenum cap = cap_to_gl_cap(stroke.getCap());
-        pr->pathParameteri(pathID, GR_GL_PATH_INITIAL_END_CAP, cap);
-        pr->pathParameteri(pathID, GR_GL_PATH_TERMINAL_END_CAP, cap);
+        GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_INITIAL_END_CAP, cap));
+        GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_TERMINAL_END_CAP, cap));
     }
 }
 
 GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke)
-    : INHERITED(gpu, kIsWrapped, path, stroke),
-      fPathID(gpu->pathRendering()->genPaths(1)) {
+    : INHERITED(gpu, kIsWrapped, path, stroke) {
     SkASSERT(!path.isEmpty());
 
-    InitPathObject(gpu, fPathID, fSkPath, stroke);
+    fPathID = gpu->createGLPathObject();
+
+    InitPathObject(static_cast<GrGpuGL*>(this->getGpu())->glInterface(),
+                   fPathID, fSkPath, stroke);
 
     if (stroke.needToApply()) {
         // FIXME: try to account for stroking, without rasterizing the stroke.
@@ -138,7 +146,7 @@
 
 void GrGLPath::onRelease() {
     if (0 != fPathID && !this->isWrapped()) {
-        static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fPathID, 1);
+        static_cast<GrGpuGL*>(this->getGpu())->deleteGLPathObject(fPathID);
         fPathID = 0;
     }
 
diff --git a/src/gpu/gl/GrGLPath.h b/src/gpu/gl/GrGLPath.h
index 935a2e2..4831b72 100644
--- a/src/gpu/gl/GrGLPath.h
+++ b/src/gpu/gl/GrGLPath.h
@@ -13,6 +13,7 @@
 #include "gl/GrGLFunctions.h"
 
 class GrGpuGL;
+struct GrGLInterface;
 
 /**
  * Currently this represents a path built using GL_NV_path_rendering. If we
@@ -22,7 +23,7 @@
 
 class GrGLPath : public GrPath {
 public:
-    static void InitPathObject(GrGpuGL*,
+    static void InitPathObject(const GrGLInterface*,
                                GrGLuint pathID,
                                const SkPath&,
                                const SkStrokeRec&);
diff --git a/src/gpu/gl/GrGLPathRange.cpp b/src/gpu/gl/GrGLPathRange.cpp
index 5e89cb5..2df04e3 100644
--- a/src/gpu/gl/GrGLPathRange.cpp
+++ b/src/gpu/gl/GrGLPathRange.cpp
@@ -8,13 +8,17 @@
 
 #include "GrGLPathRange.h"
 #include "GrGLPath.h"
-#include "GrGLPathRendering.h"
 #include "GrGpuGL.h"
 
-GrGLPathRange::GrGLPathRange(GrGpuGL* gpu, size_t size, const SkStrokeRec& stroke)
+#define GPUGL static_cast<GrGpuGL*>(this->getGpu())
+
+#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
+#define GL_CALL_RET(R, X) GR_GL_CALL_RET(GPUGL->glInterface(), R, X)
+
+GrGLPathRange::GrGLPathRange(GrGpu* gpu, size_t size, const SkStrokeRec& stroke)
     : INHERITED(gpu, size, stroke),
-      fBasePathID(gpu->pathRendering()->genPaths(fSize)),
       fNumDefinedPaths(0) {
+    GL_CALL_RET(fBasePathID, GenPaths(fSize));
 }
 
 GrGLPathRange::~GrGLPathRange() {
@@ -27,10 +31,15 @@
         return;
     }
 
+#ifdef SK_DEBUG
     // Make sure the path at this index hasn't been initted already.
-    SkASSERT(GR_GL_FALSE == gpu->pathRendering()->isPath(fBasePathID + index));
+    GrGLboolean hasPathAtIndex;
+    GL_CALL_RET(hasPathAtIndex, IsPath(fBasePathID + index));
+    SkASSERT(GR_GL_FALSE == hasPathAtIndex);
+#endif
 
-    GrGLPath::InitPathObject(gpu, fBasePathID + index, skPath, fStroke);
+    GrGLPath::InitPathObject(gpu->glInterface(), fBasePathID + index, skPath, fStroke);
+
     ++fNumDefinedPaths;
     this->didChangeGpuMemorySize();
 }
@@ -39,7 +48,7 @@
     SkASSERT(NULL != this->getGpu());
 
     if (0 != fBasePathID && !this->isWrapped()) {
-        static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fBasePathID, fSize);
+        GL_CALL(DeletePaths(fBasePathID, fSize));
         fBasePathID = 0;
     }
 
diff --git a/src/gpu/gl/GrGLPathRange.h b/src/gpu/gl/GrGLPathRange.h
index 927310d..6c6b78e 100644
--- a/src/gpu/gl/GrGLPathRange.h
+++ b/src/gpu/gl/GrGLPathRange.h
@@ -22,7 +22,7 @@
 
 class GrGLPathRange : public GrPathRange {
 public:
-    GrGLPathRange(GrGpuGL*, size_t size, const SkStrokeRec&);
+    GrGLPathRange(GrGpu*, size_t size, const SkStrokeRec&);
     virtual ~GrGLPathRange();
 
     GrGLuint basePathID() const { return fBasePathID; }
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp
deleted file mode 100644
index 249d981..0000000
--- a/src/gpu/gl/GrGLPathRendering.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "gl/GrGLPathRendering.h"
-#include "gl/GrGLInterface.h"
-#include "gl/GrGLNameAllocator.h"
-#include "gl/GrGLUtil.h"
-
-#define GL_CALL(X) GR_GL_CALL(fGLInterface.get(), X)
-#define GL_CALL_RET(RET, X) GR_GL_CALL_RET(fGLInterface.get(), RET, X)
-
-class GrGLPathRenderingV12 : public GrGLPathRendering {
-public:
-    GrGLPathRenderingV12(const GrGLInterface* glInterface)
-        : GrGLPathRendering(glInterface) {
-    }
-
-    virtual GrGLvoid stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
-                                              GrGLuint mask, GrGLenum coverMode) SK_OVERRIDE;
-    virtual GrGLvoid stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
-                                                GrGLuint mask, GrGLenum coverMode) SK_OVERRIDE;
-    virtual GrGLvoid stencilThenCoverFillPathInstanced(
-                         GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-                         GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
-                         GrGLenum transformType, const GrGLfloat *transformValues) SK_OVERRIDE;
-    virtual GrGLvoid stencilThenCoverStrokePathInstanced(
-                         GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-                         GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
-                         GrGLenum transformType, const GrGLfloat *transformValues) SK_OVERRIDE;
-};
-
-class GrGLPathRenderingV13 : public GrGLPathRenderingV12 {
-public:
-    GrGLPathRenderingV13(const GrGLInterface* glInterface)
-        : GrGLPathRenderingV12(glInterface) {
-        fCaps.fragmentInputGenSupport = true;
-    }
-
-    virtual GrGLvoid programPathFragmentInputGen(GrGLuint program, GrGLint location,
-                                                 GrGLenum genMode, GrGLint components,
-                                                 const GrGLfloat *coeffs) SK_OVERRIDE;
-};
-
-
-GrGLPathRendering* GrGLPathRendering::Create(const GrGLInterface* glInterface) {
-    if (NULL == glInterface->fFunctions.fStencilThenCoverFillPath ||
-        NULL == glInterface->fFunctions.fStencilThenCoverStrokePath ||
-        NULL == glInterface->fFunctions.fStencilThenCoverFillPathInstanced ||
-        NULL == glInterface->fFunctions.fStencilThenCoverStrokePathInstanced) {
-        return new GrGLPathRendering(glInterface);
-    }
-
-    if (NULL == glInterface->fFunctions.fProgramPathFragmentInputGen) {
-        return new GrGLPathRenderingV12(glInterface);
-    }
-
-    return new GrGLPathRenderingV13(glInterface);
-}
-
-GrGLPathRendering::GrGLPathRendering(const GrGLInterface* glInterface)
-    : fGLInterface(SkRef(glInterface)) {
-    memset(&fCaps, 0, sizeof(fCaps));
-}
-
-GrGLPathRendering::~GrGLPathRendering() {
-}
-
-void GrGLPathRendering::abandonGpuResources() {
-    fPathNameAllocator.reset(NULL);
-}
-
-
-// NV_path_rendering
-GrGLuint GrGLPathRendering::genPaths(GrGLsizei range) {
-    if (range > 1) {
-        GrGLuint name;
-        GL_CALL_RET(name, GenPaths(range));
-        return name;
-    }
-
-    if (NULL == fPathNameAllocator.get()) {
-        static const int range = 65536;
-        GrGLuint firstName;
-        GL_CALL_RET(firstName, GenPaths(range));
-        fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
-    }
-
-    // When allocating names one at a time, pull from a client-side pool of
-    // available names in order to save a round trip to the GL server.
-    GrGLuint name = fPathNameAllocator->allocateName();
-
-    if (0 == name) {
-        // Our reserved path names are all in use. Fall back on GenPaths.
-        GL_CALL_RET(name, GenPaths(1));
-    }
-
-    return name;
-}
-
-GrGLvoid GrGLPathRendering::deletePaths(GrGLuint path, GrGLsizei range) {
-    if (range > 1) {
-        // It is not supported to delete names in ranges that were allocated
-        // individually using GrGLPathNameAllocator.
-        SkASSERT(NULL == fPathNameAllocator.get() ||
-                 path + range <= fPathNameAllocator->firstName() ||
-                 path >= fPathNameAllocator->endName());
-        GL_CALL(DeletePaths(path, range));
-        return;
-    }
-
-    if (NULL == fPathNameAllocator.get() ||
-        path < fPathNameAllocator->firstName() ||
-        path >= fPathNameAllocator->endName()) {
-        // If we aren't inside fPathNameAllocator's range then this name was
-        // generated by the GenPaths fallback (or else was never allocated).
-        GL_CALL(DeletePaths(path, 1));
-        return;
-    }
-
-    // Make the path empty to save memory, but don't free the name in the driver.
-    GL_CALL(PathCommands(path, 0, NULL, 0, GR_GL_FLOAT, NULL));
-    fPathNameAllocator->free(path);
-}
-
-GrGLvoid GrGLPathRendering::pathCommands(GrGLuint path, GrGLsizei numCommands,
-                                         const GrGLubyte *commands, GrGLsizei numCoords,
-                                         GrGLenum coordType, const GrGLvoid *coords) {
-    GL_CALL(PathCommands(path, numCommands, commands, numCoords, coordType, coords));
-}
-
-GrGLvoid GrGLPathRendering::pathCoords(GrGLuint path, GrGLsizei numCoords,
-                                       GrGLenum coordType, const GrGLvoid *coords) {
-    GL_CALL(PathCoords(path, numCoords, coordType, coords));
-}
-
-GrGLvoid GrGLPathRendering::pathParameteri(GrGLuint path, GrGLenum pname, GrGLint value) {
-    GL_CALL(PathParameteri(path, pname, value));
-}
-
-GrGLvoid GrGLPathRendering::pathParameterf(GrGLuint path, GrGLenum pname, GrGLfloat value) {
-    GL_CALL(PathParameterf(path, pname, value));
-}
-
-GrGLboolean GrGLPathRendering::isPath(GrGLuint path) {
-    GrGLboolean ret;
-    GL_CALL_RET(ret, IsPath(path));
-    return ret;
-}
-
-GrGLvoid GrGLPathRendering::pathStencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask) {
-    GL_CALL(PathStencilFunc(func, ref, mask));
-}
-
-GrGLvoid GrGLPathRendering::stencilFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask) {
-    GL_CALL(StencilFillPath(path, fillMode, mask));
-}
-
-GrGLvoid GrGLPathRendering::stencilStrokePath(GrGLuint path, GrGLint reference, GrGLuint mask) {
-    GL_CALL(StencilStrokePath(path, reference, mask));
-}
-
-GrGLvoid GrGLPathRendering::stencilFillPathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-             GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask,
-             GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
-                                     fillMode, mask, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRendering::stencilStrokePathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-             GrGLuint pathBase, GrGLint reference, GrGLuint mask,
-             GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
-                                       reference, mask, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRendering::pathTexGen(GrGLenum texCoordSet, GrGLenum genMode,
-                                       GrGLint components, const GrGLfloat *coeffs) {
-    GL_CALL(PathTexGen(texCoordSet, genMode, components, coeffs));
-}
-
-GrGLvoid GrGLPathRendering::coverFillPath(GrGLuint path, GrGLenum coverMode) {
-    GL_CALL(CoverFillPath(path, coverMode));
-}
-
-GrGLvoid GrGLPathRendering::coverStrokePath(GrGLuint name, GrGLenum coverMode) {
-    GL_CALL(CoverStrokePath(name, coverMode));
-}
-
-GrGLvoid GrGLPathRendering::coverFillPathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase,
-             GrGLenum coverMode, GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
-                                   coverMode, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRendering::coverStrokePathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths, GrGLuint pathBase,
-             GrGLenum coverMode, GrGLenum transformType, const GrGLfloat* transformValues) {
-    GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
-                                     coverMode, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRendering::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
-                                                     GrGLuint mask, GrGLenum coverMode) {
-    GL_CALL(StencilFillPath(path, fillMode, mask));
-    GL_CALL(CoverFillPath(path, coverMode));
-}
-
-GrGLvoid GrGLPathRendering::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
-                                                       GrGLuint mask, GrGLenum coverMode) {
-    GL_CALL(StencilStrokePath(path, reference, mask));
-    GL_CALL(CoverStrokePath(path, coverMode));
-}
-
-GrGLvoid GrGLPathRendering::stencilThenCoverFillPathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-             GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
-             GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(StencilFillPathInstanced(numPaths, pathNameType, paths, pathBase,
-                                     fillMode, mask, transformType, transformValues));
-    GL_CALL(CoverFillPathInstanced(numPaths, pathNameType, paths, pathBase,
-                                   coverMode, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRendering::stencilThenCoverStrokePathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-             GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
-             GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(StencilStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
-                                       reference, mask, transformType, transformValues));
-    GL_CALL(CoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase,
-                                     coverMode, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRendering::programPathFragmentInputGen(
-             GrGLuint program, GrGLint location, GrGLenum genMode,
-             GrGLint components, const GrGLfloat *coeffs) {
-    SkFAIL("ProgramPathFragmentInputGen not supported in this GL context.");
-}
-
-
-// NV_path_rendering v1.2
-GrGLvoid GrGLPathRenderingV12::stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
-                                                        GrGLuint mask, GrGLenum coverMode) {
-    GL_CALL(StencilThenCoverFillPath(path, fillMode, mask, coverMode));
-}
-
-GrGLvoid GrGLPathRenderingV12::stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
-                                                          GrGLuint mask, GrGLenum coverMode) {
-    GL_CALL(StencilThenCoverStrokePath(path, reference, mask, coverMode));
-}
-
-GrGLvoid GrGLPathRenderingV12::stencilThenCoverFillPathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-             GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
-             GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(StencilThenCoverFillPathInstanced(numPaths, pathNameType, paths, pathBase, fillMode,
-                                               mask, coverMode, transformType, transformValues));
-}
-
-GrGLvoid GrGLPathRenderingV12::stencilThenCoverStrokePathInstanced(
-             GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-             GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
-             GrGLenum transformType, const GrGLfloat *transformValues) {
-    GL_CALL(StencilThenCoverStrokePathInstanced(numPaths, pathNameType, paths, pathBase, reference,
-                                                mask, coverMode, transformType, transformValues));
-}
-
-
-// NV_path_rendering v1.3
-GrGLvoid GrGLPathRenderingV13::programPathFragmentInputGen(
-             GrGLuint program, GrGLint location, GrGLenum genMode,
-             GrGLint components, const GrGLfloat *coeffs) {
-    GL_CALL(ProgramPathFragmentInputGen(program, location, genMode, components, coeffs));
-}
diff --git a/src/gpu/gl/GrGLPathRendering.h b/src/gpu/gl/GrGLPathRendering.h
deleted file mode 100644
index 53b8750..0000000
--- a/src/gpu/gl/GrGLPathRendering.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2014 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrGLPathRendering_DEFINED
-#define GrGLPathRendering_DEFINED
-
-#include "SkRefCnt.h"
-#include "gl/GrGLFunctions.h"
-
-class GrGLNameAllocator;
-struct GrGLInterface;
-
-/**
- * This class wraps the NV_path_rendering extension and manages its various
- * API versions. If a method is not present in the GrGLInterface (because the
- * driver version is old), it tries to provide a backup implementation. But if
- * a backup implementation is not practical, it marks the method as not
- * supported.
- */
-class GrGLPathRendering {
-public:
-    /**
-     * Create a new GrGLPathRendering object from a given GL interface. Unless
-     * otherwise specified in the caps, every method will work properly, even
-     * if it did not exist in the GL interface.
-     */
-    static GrGLPathRendering* Create(const GrGLInterface*);
-    virtual ~GrGLPathRendering();
-
-    /**
-     * Mark certain functionality as not supported if the driver version is too
-     * old and a backup implementation is not practical.
-     */
-    struct Caps {
-        bool fragmentInputGenSupport : 1;
-    };
-    const Caps& caps() const { return fCaps; }
-
-    /**
-     * Called when the GPU resources have been lost and need to be abandoned
-     * (for example after a context loss).
-     */
-    void abandonGpuResources();
-
-    // NV_path_rendering
-    GrGLuint genPaths(GrGLsizei range);
-    GrGLvoid deletePaths(GrGLuint path, GrGLsizei range);
-    GrGLvoid pathCommands(GrGLuint path, GrGLsizei numCommands, const GrGLubyte *commands,
-                          GrGLsizei numCoords, GrGLenum coordType, const GrGLvoid *coords);
-    GrGLvoid pathCoords(GrGLuint path, GrGLsizei numCoords,
-                        GrGLenum coordType, const GrGLvoid *coords);
-    GrGLvoid pathParameteri(GrGLuint path, GrGLenum pname, GrGLint value);
-    GrGLvoid pathParameterf(GrGLuint path, GrGLenum pname, GrGLfloat value);
-    GrGLboolean isPath(GrGLuint path);
-    GrGLvoid pathStencilFunc(GrGLenum func, GrGLint ref, GrGLuint mask);
-    GrGLvoid stencilFillPath(GrGLuint path, GrGLenum fillMode, GrGLuint mask);
-    GrGLvoid stencilStrokePath(GrGLuint path, GrGLint reference, GrGLuint mask);
-    GrGLvoid stencilFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
-                                      const GrGLvoid *paths, GrGLuint pathBase, GrGLenum fillMode,
-                                      GrGLuint mask, GrGLenum transformType,
-                                      const GrGLfloat *transformValues);
-    GrGLvoid stencilStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
-                                        const GrGLvoid *paths, GrGLuint pathBase,
-                                        GrGLint reference, GrGLuint mask, GrGLenum transformType,
-                                        const GrGLfloat *transformValues);
-    GrGLvoid pathTexGen(GrGLenum texCoordSet, GrGLenum genMode,
-                        GrGLint components, const GrGLfloat *coeffs);
-    GrGLvoid coverFillPath(GrGLuint path, GrGLenum coverMode);
-    GrGLvoid coverStrokePath(GrGLuint name, GrGLenum coverMode);
-    GrGLvoid coverFillPathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
-                                    const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode,
-                                    GrGLenum transformType, const GrGLfloat *transformValues);
-    GrGLvoid coverStrokePathInstanced(GrGLsizei numPaths, GrGLenum pathNameType,
-                                      const GrGLvoid *paths, GrGLuint pathBase, GrGLenum coverMode,
-                                      GrGLenum transformType, const GrGLfloat* transformValues);
-
-    // NV_path_rendering v1.2
-    virtual GrGLvoid stencilThenCoverFillPath(GrGLuint path, GrGLenum fillMode,
-                                              GrGLuint mask, GrGLenum coverMode);
-    virtual GrGLvoid stencilThenCoverStrokePath(GrGLuint path, GrGLint reference,
-                                                GrGLuint mask, GrGLenum coverMode);
-    virtual GrGLvoid stencilThenCoverFillPathInstanced(
-                         GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-                         GrGLuint pathBase, GrGLenum fillMode, GrGLuint mask, GrGLenum coverMode,
-                         GrGLenum transformType, const GrGLfloat *transformValues);
-    virtual GrGLvoid stencilThenCoverStrokePathInstanced(
-                         GrGLsizei numPaths, GrGLenum pathNameType, const GrGLvoid *paths,
-                         GrGLuint pathBase, GrGLint reference, GrGLuint mask, GrGLenum coverMode,
-                         GrGLenum transformType, const GrGLfloat *transformValues);
-
-    // NV_path_rendering v1.3
-    virtual GrGLvoid programPathFragmentInputGen(GrGLuint program, GrGLint location,
-                                                 GrGLenum genMode, GrGLint components,
-                                                 const GrGLfloat *coeffs);
-
-protected:
-    GrGLPathRendering(const GrGLInterface*);
-
-    SkAutoTUnref<const GrGLInterface> fGLInterface;
-    SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
-    Caps fCaps;
-};
-
-#endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 52caf9d..adcddcc 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -7,10 +7,10 @@
 
 
 #include "GrGpuGL.h"
+#include "GrGLNameAllocator.h"
 #include "GrGLStencilBuffer.h"
 #include "GrGLPath.h"
 #include "GrGLPathRange.h"
-#include "GrGLPathRendering.h"
 #include "GrGLShaderBuilder.h"
 #include "GrTemplates.h"
 #include "GrTypes.h"
@@ -164,10 +164,6 @@
 
     fLastSuccessfulStencilFmtIdx = 0;
     fHWProgramID = 0;
-
-    if (this->glCaps().pathRenderingSupport()) {
-        fPathRendering.reset(GrGLPathRendering::Create(glInterface()));
-    }
 }
 
 GrGpuGL::~GrGpuGL() {
@@ -333,7 +329,7 @@
             GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
 
             for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
-                fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
+                GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
                 fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
                 fHWPathTexGenSettings[i].fNumComponents = 0;
             }
@@ -1885,7 +1881,7 @@
     GrGLenum fillMode =
         gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
     GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
-    fPathRendering->stencilFillPath(id, fillMode, writeMask);
+    GL_CALL(StencilFillPath(id, fillMode, writeMask));
 }
 
 void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
@@ -1908,18 +1904,18 @@
     if (nonInvertedFill == fill) {
         if (stroke.needToApply()) {
             if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
-                fPathRendering->stencilFillPath(id, fillMode, writeMask);
+                GL_CALL(StencilFillPath(id, fillMode, writeMask));
             }
-            fPathRendering->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
+            GL_CALL(StencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX));
         } else {
-            fPathRendering->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
+            GL_CALL(StencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX));
         }
     } else {
         if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
-            fPathRendering->stencilFillPath(id, fillMode, writeMask);
+            GL_CALL(StencilFillPath(id, fillMode, writeMask));
         }
         if (stroke.needToApply()) {
-            fPathRendering->stencilStrokePath(id, 0xffff, writeMask);
+            GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
         }
 
         GrDrawState* drawState = this->drawState();
@@ -1970,33 +1966,33 @@
     if (nonInvertedFill == fill) {
         if (stroke.needToApply()) {
             if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
-                fPathRendering->stencilFillPathInstanced(
-                                    count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
-                                    writeMask, gXformType2GLType[transformsType],
-                                    transforms);
+                GL_CALL(StencilFillPathInstanced(
+                            count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+                            writeMask, gXformType2GLType[transformsType],
+                            transforms));
             }
-            fPathRendering->stencilThenCoverStrokePathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
-                                GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
-                                gXformType2GLType[transformsType], transforms);
+            GL_CALL(StencilThenCoverStrokePathInstanced(
+                        count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
+                        GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+                        gXformType2GLType[transformsType], transforms));
         } else {
-            fPathRendering->stencilThenCoverFillPathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
-                                GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
-                                gXformType2GLType[transformsType], transforms);
+            GL_CALL(StencilThenCoverFillPathInstanced(
+                        count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
+                        GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+                        gXformType2GLType[transformsType], transforms));
         }
     } else {
         if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
-            fPathRendering->stencilFillPathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
-                                writeMask, gXformType2GLType[transformsType],
-                                transforms);
+            GL_CALL(StencilFillPathInstanced(
+                        count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+                        writeMask, gXformType2GLType[transformsType],
+                        transforms));
         }
         if (stroke.needToApply()) {
-            fPathRendering->stencilStrokePathInstanced(
-                                count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
-                                writeMask, gXformType2GLType[transformsType],
-                                transforms);
+            GL_CALL(StencilStrokePathInstanced(
+                        count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
+                        writeMask, gXformType2GLType[transformsType],
+                        transforms));
         }
 
         GrDrawState* drawState = this->drawState();
@@ -2214,9 +2210,9 @@
         // that draws the path to the SB (glStencilFillPath)
         GrGLenum func =
             gr_to_gl_stencil_func(pathStencilSettings.func(GrStencilSettings::kFront_Face));
-        fPathRendering->pathStencilFunc(
-                            func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
-                            pathStencilSettings.funcMask(GrStencilSettings::kFront_Face));
+        GL_CALL(PathStencilFunc(func,
+                                pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
+                                pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
 
         fHWPathStencilSettings = pathStencilSettings;
     }
@@ -2407,10 +2403,10 @@
     this->setTextureUnit(unitIdx);
 
     fHWPathTexGenSettings[unitIdx].fNumComponents = components;
-    fPathRendering->pathTexGen(GR_GL_TEXTURE0 + unitIdx,
-                               GR_GL_OBJECT_LINEAR,
-                               components,
-                               coefficients);
+    GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
+                       GR_GL_OBJECT_LINEAR,
+                       components,
+                       coefficients));
 
     memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
            3 * components * sizeof(GrGLfloat));
@@ -2459,7 +2455,7 @@
         SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
 
         this->setTextureUnit(i);
-        fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
+        GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
         fHWPathTexGenSettings[i].fNumComponents = 0;
     }
 
@@ -2515,6 +2511,38 @@
     }
 }
 
+GrGLuint GrGpuGL::createGLPathObject() {
+    if (NULL == fPathNameAllocator.get()) {
+        static const int range = 65536;
+        GrGLuint firstName;
+        GL_CALL_RET(firstName, GenPaths(range));
+        fPathNameAllocator.reset(SkNEW_ARGS(GrGLNameAllocator, (firstName, firstName + range)));
+    }
+
+    GrGLuint name = fPathNameAllocator->allocateName();
+    if (0 == name) {
+        // Our reserved path names are all in use. Fall back on GenPaths.
+        GL_CALL_RET(name, GenPaths(1));
+    }
+
+    return name;
+}
+
+void GrGpuGL::deleteGLPathObject(GrGLuint name) {
+    if (NULL == fPathNameAllocator.get() ||
+        name < fPathNameAllocator->firstName() ||
+        name >= fPathNameAllocator->endName()) {
+        // If we aren't inside fPathNameAllocator's range then this name was
+        // generated by the GenPaths fallback (or else the name is unallocated).
+        GL_CALL(DeletePaths(name, 1));
+        return;
+    }
+
+    // Make the path empty to save memory, but don't free the name in the driver.
+    GL_CALL(PathCommands(name, 0, NULL, 0, GR_GL_FLOAT, NULL));
+    fPathNameAllocator->free(name);
+}
+
 bool GrGpuGL::configToGLFormats(GrPixelConfig config,
                                 bool getSizedInternalFormat,
                                 GrGLenum* internalFormat,
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index b39aedb..e671972 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -24,7 +24,7 @@
 #define PROGRAM_CACHE_STATS
 #endif
 
-class GrGLPathRendering;
+class GrGLNameAllocator;
 
 class GrGpuGL : public GrGpu {
 public:
@@ -40,11 +40,6 @@
     GrGLSLGeneration glslGeneration() const { return fGLContext.glslGeneration(); }
     const GrGLCaps& glCaps() const { return *fGLContext.caps(); }
 
-    GrGLPathRendering* pathRendering() const {
-        SkASSERT(glCaps().pathRenderingSupport());
-        return fPathRendering.get();
-    }
-
     virtual void discard(GrRenderTarget*) SK_OVERRIDE;
 
     // Used by GrGLProgram and GrGLPathTexGenProgramEffects to configure OpenGL
@@ -109,6 +104,11 @@
         fHWGeometryState.notifyIndexBufferDelete(id);
     }
 
+    // These functions should be used to generate and delete GL path names. They have their own
+    // allocator that runs on the client side, so they are much faster than going through GenPaths.
+    GrGLuint createGLPathObject();
+    void deleteGLPathObject(GrGLuint);
+
 protected:
     virtual bool onCopySurface(GrSurface* dst,
                                GrSurface* src,
@@ -470,7 +470,7 @@
     // from our loop that tries stencil formats and calls check fb status.
     int fLastSuccessfulStencilFmtIdx;
 
-    SkAutoTDelete<GrGLPathRendering> fPathRendering;
+    SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
 
     typedef GrGpu INHERITED;
 };
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 139d5cf..2afb95f 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -10,7 +10,7 @@
 #include "GrEffect.h"
 #include "GrGLEffect.h"
 #include "SkRTConf.h"
-#include "GrGLPathRendering.h"
+#include "GrGLNameAllocator.h"
 #include "SkTSearch.h"
 
 #ifdef PROGRAM_CACHE_STATS
@@ -203,7 +203,7 @@
     INHERITED::abandonResources();
     fProgramCache->abandon();
     fHWProgramID = 0;
-    fPathRendering->abandonGpuResources();
+    fPathNameAllocator.reset(NULL);
 }
 
 ////////////////////////////////////////////////////////////////////////////////