diff options
author | 2017-07-14 15:17:41 -0600 | |
---|---|---|
committer | 2017-07-14 21:45:35 +0000 | |
commit | 1a325d25b941ef801b3e9b2c0342da43cf35cdba (patch) | |
tree | 3f65d36541399e1ae6a529a534119815a2c5ba36 /src/gpu/ccpr/GrCCPRCubicProcessor.h | |
parent | 588fb040b3ad410cdb10c87f9a7884b6eb825e90 (diff) |
Coverage counting path renderer
Initial implementation of a GPU path renderer that draws antialiased
paths by counting coverage in an offscreen buffer.
Initially disabled until it has had time to soak.
Bug: skia:
Change-Id: I003d8cfdf8dc62641581b5ea2dc4f0aa00108df6
Reviewed-on: https://skia-review.googlesource.com/21541
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
Diffstat (limited to 'src/gpu/ccpr/GrCCPRCubicProcessor.h')
-rw-r--r-- | src/gpu/ccpr/GrCCPRCubicProcessor.h | 147 |
1 files changed, 147 insertions, 0 deletions
diff --git a/src/gpu/ccpr/GrCCPRCubicProcessor.h b/src/gpu/ccpr/GrCCPRCubicProcessor.h new file mode 100644 index 0000000000..f31dad793e --- /dev/null +++ b/src/gpu/ccpr/GrCCPRCubicProcessor.h @@ -0,0 +1,147 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrCCPRCubicProcessor_DEFINED +#define GrCCPRCubicProcessor_DEFINED + +#include "ccpr/GrCCPRCoverageProcessor.h" + +class GrGLSLGeometryBuilder; + +/** + * This class renders the coverage of convex closed cubic segments using the techniques outlined in + * "Resolution Independent Curve Rendering using Programmable Graphics Hardware" by Charles Loop and + * Jim Blinn: + * + * https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf + * + * The caller is expected to chop cubics at the KLM roots (a.k.a. inflection points and loop + * intersection points, resulting in necessarily convex segments) before feeding them into this + * processor. + * + * The curves are rendered in two passes: + * + * Pass 1: Draw the (convex) bezier quadrilateral, inset by 1/2 pixel all around, and use the + * gradient-based AA technique outlined in the Loop/Blinn paper to compute coverage. + * + * Pass 2: Draw a border around the previous inset, up to the bezier quadrilatral's conservative + * raster hull, and compute coverage using pseudo MSAA. This pass is necessary because the + * gradient approach does not work near the L and M lines. + * + * FIXME: The pseudo MSAA border is slow and ugly. We should investigate an alternate solution of + * just approximating the curve with straight lines for short distances across the problem points + * instead. + */ +class GrCCPRCubicProcessor : public GrCCPRCoverageProcessor::PrimitiveProcessor { +public: + enum class Type { + kSerpentine, + kLoop + }; + + GrCCPRCubicProcessor(Type type) + : INHERITED(CoverageType::kShader) + , fType(type) + , fInset(kVec3f_GrSLType) + , fTS(kFloat_GrSLType) + , fKLMMatrix("klm_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray, + kHigh_GrSLPrecision) + , fKLMDerivatives("klm_derivatives", kVec2f_GrSLType, 3, kHigh_GrSLPrecision) {} + + void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { + varyingHandler->addVarying("insets", &fInset, kHigh_GrSLPrecision); + varyingHandler->addVarying("ts", &fTS, kHigh_GrSLPrecision); + } + + void onEmitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*, + const TexelBufferHandle& pointsBuffer, const char* atlasOffset, + const char* rtAdjust, GrGPArgs*) const override; + void emitWind(GrGLSLGeometryBuilder*, const char* rtAdjust, const char* outputWind) const final; + void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* wind, + const char* rtAdjust) const final; + +protected: + virtual void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn, + const char* wind, const char* rtAdjust) const = 0; + + const Type fType; + GrGLSLVertToGeo fInset; + GrGLSLVertToGeo fTS; + GrShaderVar fKLMMatrix; + GrShaderVar fKLMDerivatives; + + typedef GrCCPRCoverageProcessor::PrimitiveProcessor INHERITED; +}; + +class GrCCPRCubicInsetProcessor : public GrCCPRCubicProcessor { +public: + GrCCPRCubicInsetProcessor(Type type) + : INHERITED(type) + , fKLM(kVec3f_GrSLType) + , fGradMatrix(kMat22f_GrSLType) {} + + void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { + this->INHERITED::resetVaryings(varyingHandler); + varyingHandler->addVarying("klm", &fKLM, kHigh_GrSLPrecision); + varyingHandler->addVarying("grad_matrix", &fGradMatrix, kHigh_GrSLPrecision); + } + + void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn, + const char* wind, const char* rtAdjust) const override; + void emitPerVertexGeometryCode(SkString* fnBody, const char* position, const char* coverage, + const char* wind) const override; + void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override; + +protected: + GrGLSLGeoToFrag fKLM; + GrGLSLGeoToFrag fGradMatrix; + + typedef GrCCPRCubicProcessor INHERITED; +}; + +class GrCCPRCubicBorderProcessor : public GrCCPRCubicProcessor { +public: + GrCCPRCubicBorderProcessor(Type type) + : INHERITED(type) + , fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType, + GrShaderVar::kNonArray, kHigh_GrSLPrecision) + , fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType, + GrShaderVar::kNonArray, kHigh_GrSLPrecision) + , fEdgeSpaceTransform("edge_space_transform", kVec4f_GrSLType, GrShaderVar::kNonArray, + kHigh_GrSLPrecision) + , fKLMD(kVec4f_GrSLType) + , fdKLMDdx(kVec4f_GrSLType) + , fdKLMDdy(kVec4f_GrSLType) + , fEdgeSpaceCoord(kVec2f_GrSLType) {} + + void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override { + this->INHERITED::resetVaryings(varyingHandler); + varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision); + varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx, kHigh_GrSLPrecision); + varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy, kHigh_GrSLPrecision); + varyingHandler->addVarying("edge_space_coord", &fEdgeSpaceCoord, kHigh_GrSLPrecision); + } + + void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn, + const char* wind, const char* rtAdjust) const override; + void emitPerVertexGeometryCode(SkString* fnBody, const char* position, const char* coverage, + const char* wind) const override; + void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override; + +protected: + GrShaderVar fEdgeDistanceEquation; + GrShaderVar fEdgeDistanceDerivatives; + GrShaderVar fEdgeSpaceTransform; + GrGLSLGeoToFrag fKLMD; + GrGLSLGeoToFrag fdKLMDdx; + GrGLSLGeoToFrag fdKLMDdy; + GrGLSLGeoToFrag fEdgeSpaceCoord; + + typedef GrCCPRCubicProcessor INHERITED; +}; + +#endif |