Index: src/gpu/gl/GrGLPathRendering.cpp |
diff --git a/src/gpu/gl/GrGLPathRendering.cpp b/src/gpu/gl/GrGLPathRendering.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..249d98139ad65b9d888e161ba32c7f6281a52046 |
--- /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)); |
+} |