Chromium Code Reviews| 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) { |
|
Mark Kilgard
2014/08/04 17:08:53
good, I like this
|
| + 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)); |
| +} |