aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2014-08-04 11:19:11 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-04 11:19:11 -0700
commit5672da0fa54f31c9727568e9dd5fe82c6e1585bc (patch)
tree896528f32f296ed7c21191c470bba5b6a0cae968 /src
parentbce540ca8fb23c1a99f4216cc5ecae46c722dafa (diff)
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. R=bsalomon@google.com, kkinnunen@nvidia.com, markkilgard@gmail.com Author: cdalton@nvidia.com Review URL: https://codereview.chromium.org/437473002
Diffstat (limited to 'src')
-rw-r--r--src/gpu/gl/GrGLAssembleInterface.cpp113
-rw-r--r--src/gpu/gl/GrGLInterface.cpp29
-rw-r--r--src/gpu/gl/GrGLPath.cpp34
-rw-r--r--src/gpu/gl/GrGLPath.h3
-rw-r--r--src/gpu/gl/GrGLPathRange.cpp21
-rw-r--r--src/gpu/gl/GrGLPathRange.h2
-rw-r--r--src/gpu/gl/GrGLPathRendering.cpp281
-rw-r--r--src/gpu/gl/GrGLPathRendering.h108
-rw-r--r--src/gpu/gl/GrGpuGL.cpp108
-rw-r--r--src/gpu/gl/GrGpuGL.h14
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp4
11 files changed, 480 insertions, 237 deletions
diff --git a/src/gpu/gl/GrGLAssembleInterface.cpp b/src/gpu/gl/GrGLAssembleInterface.cpp
index 4ae50ba391..8fd173d9f4 100644
--- a/src/gpu/gl/GrGLAssembleInterface.cpp
+++ b/src/gpu/gl/GrGLAssembleInterface.cpp
@@ -14,12 +14,6 @@
#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);
@@ -245,18 +239,13 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
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")) {
@@ -283,101 +272,3 @@ const GrGLInterface* GrGLAssembleGLInterface(void* ctx, GrGLGetProc get) {
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 e9ba32ed24..c192611f50 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -56,6 +56,10 @@ const GrGLInterface* GrGLInterfaceRemoveNVPR(const GrGLInterface* interface) {
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;
}
@@ -467,18 +471,23 @@ bool GrGLInterface::validate() const {
NULL == fFunctions.fCoverFillPath ||
NULL == fFunctions.fCoverStrokePath ||
NULL == fFunctions.fCoverFillPathInstanced ||
- NULL == fFunctions.fCoverStrokePathInstanced ||
- NULL == fFunctions.fStencilThenCoverFillPath ||
- NULL == fFunctions.fStencilThenCoverStrokePath ||
- NULL == fFunctions.fStencilThenCoverFillPathInstanced ||
- NULL == fFunctions.fStencilThenCoverStrokePathInstanced) {
+ NULL == fFunctions.fCoverStrokePathInstanced) {
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
+ 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
+ }
}
}
diff --git a/src/gpu/gl/GrGLPath.cpp b/src/gpu/gl/GrGLPath.cpp
index 1c745808e9..6f158cdea9 100644
--- a/src/gpu/gl/GrGLPath.cpp
+++ b/src/gpu/gl/GrGLPath.cpp
@@ -7,13 +7,9 @@
*/
#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[] = {
@@ -85,10 +81,11 @@ inline GrGLenum cap_to_gl_cap(SkPaint::Cap cap) {
static const bool kIsWrapped = false; // The constructor creates the GL path object.
-void GrGLPath::InitPathObject(const GrGLInterface* gl,
+void GrGLPath::InitPathObject(GrGpuGL* gpu,
GrGLuint pathID,
const SkPath& skPath,
const SkStrokeRec& stroke) {
+ GrGLPathRendering* pr = gpu->pathRendering();
SkSTArray<16, GrGLubyte, true> pathCommands;
SkSTArray<16, SkPoint, true> pathPoints;
@@ -109,30 +106,25 @@ void GrGLPath::InitPathObject(const GrGLInterface* gl,
}
SkASSERT(pathPoints.count() == numPts);
- GR_GL_CALL(gl, PathCommands(pathID,
- verbCnt, &pathCommands[0],
- 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]));
-
+ pr->pathCommands(pathID, verbCnt, &pathCommands[0], 2 * pointCnt, GR_GL_FLOAT, &pathPoints[0]);
if (stroke.needToApply()) {
SkASSERT(!stroke.isHairlineStyle());
- 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())));
+ pr->pathParameterf(pathID, GR_GL_PATH_STROKE_WIDTH, SkScalarToFloat(stroke.getWidth()));
+ pr->pathParameterf(pathID, GR_GL_PATH_MITER_LIMIT, SkScalarToFloat(stroke.getMiter()));
GrGLenum join = join_to_gl_join(stroke.getJoin());
- GR_GL_CALL(gl, PathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join));
+ pr->pathParameteri(pathID, GR_GL_PATH_JOIN_STYLE, join);
GrGLenum cap = cap_to_gl_cap(stroke.getCap());
- 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));
+ pr->pathParameteri(pathID, GR_GL_PATH_INITIAL_END_CAP, cap);
+ pr->pathParameteri(pathID, GR_GL_PATH_TERMINAL_END_CAP, cap);
}
}
GrGLPath::GrGLPath(GrGpuGL* gpu, const SkPath& path, const SkStrokeRec& stroke)
- : INHERITED(gpu, kIsWrapped, path, stroke) {
+ : INHERITED(gpu, kIsWrapped, path, stroke),
+ fPathID(gpu->pathRendering()->genPaths(1)) {
SkASSERT(!path.isEmpty());
- fPathID = gpu->createGLPathObject();
-
- InitPathObject(static_cast<GrGpuGL*>(this->getGpu())->glInterface(),
- fPathID, fSkPath, stroke);
+ InitPathObject(gpu, fPathID, fSkPath, stroke);
if (stroke.needToApply()) {
// FIXME: try to account for stroking, without rasterizing the stroke.
@@ -146,7 +138,7 @@ GrGLPath::~GrGLPath() {
void GrGLPath::onRelease() {
if (0 != fPathID && !this->isWrapped()) {
- static_cast<GrGpuGL*>(this->getGpu())->deleteGLPathObject(fPathID);
+ static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fPathID, 1);
fPathID = 0;
}
diff --git a/src/gpu/gl/GrGLPath.h b/src/gpu/gl/GrGLPath.h
index 4831b7250f..935a2e24ad 100644
--- a/src/gpu/gl/GrGLPath.h
+++ b/src/gpu/gl/GrGLPath.h
@@ -13,7 +13,6 @@
#include "gl/GrGLFunctions.h"
class GrGpuGL;
-struct GrGLInterface;
/**
* Currently this represents a path built using GL_NV_path_rendering. If we
@@ -23,7 +22,7 @@ struct GrGLInterface;
class GrGLPath : public GrPath {
public:
- static void InitPathObject(const GrGLInterface*,
+ static void InitPathObject(GrGpuGL*,
GrGLuint pathID,
const SkPath&,
const SkStrokeRec&);
diff --git a/src/gpu/gl/GrGLPathRange.cpp b/src/gpu/gl/GrGLPathRange.cpp
index 2df04e3057..5e89cb5d87 100644
--- a/src/gpu/gl/GrGLPathRange.cpp
+++ b/src/gpu/gl/GrGLPathRange.cpp
@@ -8,17 +8,13 @@
#include "GrGLPathRange.h"
#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)
-
-GrGLPathRange::GrGLPathRange(GrGpu* gpu, size_t size, const SkStrokeRec& stroke)
+GrGLPathRange::GrGLPathRange(GrGpuGL* 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() {
@@ -31,15 +27,10 @@ void GrGLPathRange::initAt(size_t index, const SkPath& skPath) {
return;
}
-#ifdef SK_DEBUG
// Make sure the path at this index hasn't been initted already.
- GrGLboolean hasPathAtIndex;
- GL_CALL_RET(hasPathAtIndex, IsPath(fBasePathID + index));
- SkASSERT(GR_GL_FALSE == hasPathAtIndex);
-#endif
-
- GrGLPath::InitPathObject(gpu->glInterface(), fBasePathID + index, skPath, fStroke);
+ SkASSERT(GR_GL_FALSE == gpu->pathRendering()->isPath(fBasePathID + index));
+ GrGLPath::InitPathObject(gpu, fBasePathID + index, skPath, fStroke);
++fNumDefinedPaths;
this->didChangeGpuMemorySize();
}
@@ -48,7 +39,7 @@ void GrGLPathRange::onRelease() {
SkASSERT(NULL != this->getGpu());
if (0 != fBasePathID && !this->isWrapped()) {
- GL_CALL(DeletePaths(fBasePathID, fSize));
+ static_cast<GrGpuGL*>(this->getGpu())->pathRendering()->deletePaths(fBasePathID, fSize);
fBasePathID = 0;
}
diff --git a/src/gpu/gl/GrGLPathRange.h b/src/gpu/gl/GrGLPathRange.h
index 6c6b78e016..927310d651 100644
--- a/src/gpu/gl/GrGLPathRange.h
+++ b/src/gpu/gl/GrGLPathRange.h
@@ -22,7 +22,7 @@ class GrGpuGL;
class GrGLPathRange : public GrPathRange {
public:
- GrGLPathRange(GrGpu*, size_t size, const SkStrokeRec&);
+ GrGLPathRange(GrGpuGL*, 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
new file mode 100644
index 0000000000..249d98139a
--- /dev/null
+++ b/src/gpu/gl/GrGLPathRendering.cpp
@@ -0,0 +1,281 @@
+/*
+ * 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
new file mode 100644
index 0000000000..53b8750356
--- /dev/null
+++ b/src/gpu/gl/GrGLPathRendering.h
@@ -0,0 +1,108 @@
+/*
+ * 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 adcddcc108..52caf9d3ea 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,6 +164,10 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fLastSuccessfulStencilFmtIdx = 0;
fHWProgramID = 0;
+
+ if (this->glCaps().pathRenderingSupport()) {
+ fPathRendering.reset(GrGLPathRendering::Create(glInterface()));
+ }
}
GrGpuGL::~GrGpuGL() {
@@ -329,7 +333,7 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
GL_CALL(MatrixLoadIdentity(GR_GL_MODELVIEW));
for (int i = 0; i < this->glCaps().maxFixedFunctionTextureCoords(); ++i) {
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
fHWPathTexGenSettings[i].fMode = GR_GL_NONE;
fHWPathTexGenSettings[i].fNumComponents = 0;
}
@@ -1881,7 +1885,7 @@ void GrGpuGL::onGpuStencilPath(const GrPath* path, SkPath::FillType fill) {
GrGLenum fillMode =
gr_stencil_op_to_gl_path_rendering_fill_mode(fHWPathStencilSettings.passOp(GrStencilSettings::kFront_Face));
GrGLint writeMask = fHWPathStencilSettings.writeMask(GrStencilSettings::kFront_Face);
- GL_CALL(StencilFillPath(id, fillMode, writeMask));
+ fPathRendering->stencilFillPath(id, fillMode, writeMask);
}
void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
@@ -1904,18 +1908,18 @@ void GrGpuGL::onGpuDrawPath(const GrPath* path, SkPath::FillType fill) {
if (nonInvertedFill == fill) {
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- GL_CALL(StencilFillPath(id, fillMode, writeMask));
+ fPathRendering->stencilFillPath(id, fillMode, writeMask);
}
- GL_CALL(StencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX));
+ fPathRendering->stencilThenCoverStrokePath(id, 0xffff, writeMask, GR_GL_BOUNDING_BOX);
} else {
- GL_CALL(StencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX));
+ fPathRendering->stencilThenCoverFillPath(id, fillMode, writeMask, GR_GL_BOUNDING_BOX);
}
} else {
if (stroke.isFillStyle() || SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- GL_CALL(StencilFillPath(id, fillMode, writeMask));
+ fPathRendering->stencilFillPath(id, fillMode, writeMask);
}
if (stroke.needToApply()) {
- GL_CALL(StencilStrokePath(id, 0xffff, writeMask));
+ fPathRendering->stencilStrokePath(id, 0xffff, writeMask);
}
GrDrawState* drawState = this->drawState();
@@ -1966,33 +1970,33 @@ void GrGpuGL::onGpuDrawPaths(const GrPathRange* pathRange,
if (nonInvertedFill == fill) {
if (stroke.needToApply()) {
if (SkStrokeRec::kStrokeAndFill_Style == stroke.getStyle()) {
- GL_CALL(StencilFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
- writeMask, gXformType2GLType[transformsType],
- transforms));
+ fPathRendering->stencilFillPathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+ writeMask, 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));
+ fPathRendering->stencilThenCoverStrokePathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff, writeMask,
+ GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
+ gXformType2GLType[transformsType], transforms);
} else {
- GL_CALL(StencilThenCoverFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode, writeMask,
- GR_GL_BOUNDING_BOX_OF_BOUNDING_BOXES,
- gXformType2GLType[transformsType], transforms));
+ fPathRendering->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()) {
- GL_CALL(StencilFillPathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
- writeMask, gXformType2GLType[transformsType],
- transforms));
+ fPathRendering->stencilFillPathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, fillMode,
+ writeMask, gXformType2GLType[transformsType],
+ transforms);
}
if (stroke.needToApply()) {
- GL_CALL(StencilStrokePathInstanced(
- count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
- writeMask, gXformType2GLType[transformsType],
- transforms));
+ fPathRendering->stencilStrokePathInstanced(
+ count, GR_GL_UNSIGNED_INT, indices, baseID, 0xffff,
+ writeMask, gXformType2GLType[transformsType],
+ transforms);
}
GrDrawState* drawState = this->drawState();
@@ -2210,9 +2214,9 @@ void GrGpuGL::flushPathStencilSettings(SkPath::FillType fill) {
// that draws the path to the SB (glStencilFillPath)
GrGLenum func =
gr_to_gl_stencil_func(pathStencilSettings.func(GrStencilSettings::kFront_Face));
- GL_CALL(PathStencilFunc(func,
- pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
- pathStencilSettings.funcMask(GrStencilSettings::kFront_Face)));
+ fPathRendering->pathStencilFunc(
+ func, pathStencilSettings.funcRef(GrStencilSettings::kFront_Face),
+ pathStencilSettings.funcMask(GrStencilSettings::kFront_Face));
fHWPathStencilSettings = pathStencilSettings;
}
@@ -2403,10 +2407,10 @@ void GrGpuGL::enablePathTexGen(int unitIdx,
this->setTextureUnit(unitIdx);
fHWPathTexGenSettings[unitIdx].fNumComponents = components;
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
- GR_GL_OBJECT_LINEAR,
- components,
- coefficients));
+ fPathRendering->pathTexGen(GR_GL_TEXTURE0 + unitIdx,
+ GR_GL_OBJECT_LINEAR,
+ components,
+ coefficients);
memcpy(fHWPathTexGenSettings[unitIdx].fCoefficients, coefficients,
3 * components * sizeof(GrGLfloat));
@@ -2455,7 +2459,7 @@ void GrGpuGL::flushPathTexGenSettings(int numUsedTexCoordSets) {
SkASSERT(0 != fHWPathTexGenSettings[i].fNumComponents);
this->setTextureUnit(i);
- GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fPathRendering->pathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL);
fHWPathTexGenSettings[i].fNumComponents = 0;
}
@@ -2511,38 +2515,6 @@ void GrGpuGL::flushMiscFixedFunctionState() {
}
}
-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 e67197219d..b39aedb824 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -24,7 +24,7 @@
#define PROGRAM_CACHE_STATS
#endif
-class GrGLNameAllocator;
+class GrGLPathRendering;
class GrGpuGL : public GrGpu {
public:
@@ -40,6 +40,11 @@ public:
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
@@ -104,11 +109,6 @@ public:
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 @@ private:
// from our loop that tries stencil formats and calls check fb status.
int fLastSuccessfulStencilFmtIdx;
- SkAutoTDelete<GrGLNameAllocator> fPathNameAllocator;
+ SkAutoTDelete<GrGLPathRendering> fPathRendering;
typedef GrGpu INHERITED;
};
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 2afb95fe97..139d5cfa44 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 "GrGLNameAllocator.h"
+#include "GrGLPathRendering.h"
#include "SkTSearch.h"
#ifdef PROGRAM_CACHE_STATS
@@ -203,7 +203,7 @@ void GrGpuGL::abandonResources(){
INHERITED::abandonResources();
fProgramCache->abandon();
fHWProgramID = 0;
- fPathNameAllocator.reset(NULL);
+ fPathRendering->abandonGpuResources();
}
////////////////////////////////////////////////////////////////////////////////