• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2017 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrCCPRCubicProcessor_DEFINED
9 #define GrCCPRCubicProcessor_DEFINED
10 
11 #include "ccpr/GrCCPRCoverageProcessor.h"
12 
13 class GrGLSLGeometryBuilder;
14 
15 /**
16  * This class renders the coverage of convex closed cubic segments using the techniques outlined in
17  * "Resolution Independent Curve Rendering using Programmable Graphics Hardware" by Charles Loop and
18  * Jim Blinn:
19  *
20  * https://www.microsoft.com/en-us/research/wp-content/uploads/2005/01/p1000-loop.pdf
21  *
22  * The caller is expected to chop cubics at the KLM roots (a.k.a. inflection points and loop
23  * intersection points, resulting in necessarily convex segments) before feeding them into this
24  * processor.
25  *
26  * The curves are rendered in two passes:
27  *
28  * Pass 1: Draw the (convex) bezier quadrilateral, inset by 1/2 pixel all around, and use the
29  *         gradient-based AA technique outlined in the Loop/Blinn paper to compute coverage.
30  *
31  * Pass 2: Draw a border around the previous inset, up to the bezier quadrilatral's conservative
32  *         raster hull, and compute coverage using pseudo MSAA. This pass is necessary because the
33  *         gradient approach does not work near the L and M lines.
34  *
35  * FIXME: The pseudo MSAA border is slow and ugly. We should investigate an alternate solution of
36  * just approximating the curve with straight lines for short distances across the problem points
37  * instead.
38  */
39 class GrCCPRCubicProcessor : public GrCCPRCoverageProcessor::PrimitiveProcessor {
40 public:
41     enum class Type {
42         kSerpentine,
43         kLoop
44     };
45 
GrCCPRCubicProcessor(Type type)46     GrCCPRCubicProcessor(Type type)
47             : INHERITED(CoverageType::kShader)
48             , fType(type)
49             , fInset(kVec3f_GrSLType)
50             , fTS(kFloat_GrSLType)
51             , fKLMMatrix("klm_matrix", kMat33f_GrSLType, GrShaderVar::kNonArray,
52                          kHigh_GrSLPrecision)
53             , fKLMDerivatives("klm_derivatives", kVec2f_GrSLType, 3, kHigh_GrSLPrecision) {}
54 
resetVaryings(GrGLSLVaryingHandler * varyingHandler)55     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
56         varyingHandler->addVarying("insets", &fInset, kHigh_GrSLPrecision);
57         varyingHandler->addVarying("ts", &fTS, kHigh_GrSLPrecision);
58     }
59 
60     void onEmitVertexShader(const GrCCPRCoverageProcessor&, GrGLSLVertexBuilder*,
61                             const TexelBufferHandle& pointsBuffer, const char* atlasOffset,
62                             const char* rtAdjust, GrGPArgs*) const override;
63     void emitWind(GrGLSLGeometryBuilder*, const char* rtAdjust, const char* outputWind) const final;
64     void onEmitGeometryShader(GrGLSLGeometryBuilder*, const char* emitVertexFn, const char* wind,
65                               const char* rtAdjust) const final;
66 
67 protected:
68     virtual void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
69                                    const char* wind, const char* rtAdjust) const = 0;
70 
71     const Type        fType;
72     GrGLSLVertToGeo   fInset;
73     GrGLSLVertToGeo   fTS;
74     GrShaderVar       fKLMMatrix;
75     GrShaderVar       fKLMDerivatives;
76 
77     typedef GrCCPRCoverageProcessor::PrimitiveProcessor INHERITED;
78 };
79 
80 class GrCCPRCubicInsetProcessor : public GrCCPRCubicProcessor {
81 public:
GrCCPRCubicInsetProcessor(Type type)82     GrCCPRCubicInsetProcessor(Type type)
83             : INHERITED(type)
84             , fKLM(kVec3f_GrSLType)
85             , fGradMatrix(kMat22f_GrSLType) {}
86 
resetVaryings(GrGLSLVaryingHandler * varyingHandler)87     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
88         this->INHERITED::resetVaryings(varyingHandler);
89         varyingHandler->addVarying("klm", &fKLM, kHigh_GrSLPrecision);
90         varyingHandler->addVarying("grad_matrix", &fGradMatrix, kHigh_GrSLPrecision);
91     }
92 
93     void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
94                            const char* wind, const char* rtAdjust) const override;
95     void emitPerVertexGeometryCode(SkString* fnBody, const char* position, const char* coverage,
96                                    const char* wind) const override;
97     void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
98 
99 protected:
100     GrGLSLGeoToFrag   fKLM;
101     GrGLSLGeoToFrag   fGradMatrix;
102 
103     typedef GrCCPRCubicProcessor INHERITED;
104 };
105 
106 class GrCCPRCubicBorderProcessor : public GrCCPRCubicProcessor {
107 public:
GrCCPRCubicBorderProcessor(Type type)108     GrCCPRCubicBorderProcessor(Type type)
109             : INHERITED(type)
110             , fEdgeDistanceEquation("edge_distance_equation", kVec3f_GrSLType,
111                                     GrShaderVar::kNonArray, kHigh_GrSLPrecision)
112             , fEdgeDistanceDerivatives("edge_distance_derivatives", kVec2f_GrSLType,
113                                         GrShaderVar::kNonArray, kHigh_GrSLPrecision)
114             , fEdgeSpaceTransform("edge_space_transform", kVec4f_GrSLType, GrShaderVar::kNonArray,
115                                   kHigh_GrSLPrecision)
116             , fKLMD(kVec4f_GrSLType)
117             , fdKLMDdx(kVec4f_GrSLType)
118             , fdKLMDdy(kVec4f_GrSLType)
119             , fEdgeSpaceCoord(kVec2f_GrSLType) {}
120 
resetVaryings(GrGLSLVaryingHandler * varyingHandler)121     void resetVaryings(GrGLSLVaryingHandler* varyingHandler) override {
122         this->INHERITED::resetVaryings(varyingHandler);
123         varyingHandler->addVarying("klmd", &fKLMD, kHigh_GrSLPrecision);
124         varyingHandler->addFlatVarying("dklmddx", &fdKLMDdx, kHigh_GrSLPrecision);
125         varyingHandler->addFlatVarying("dklmddy", &fdKLMDdy, kHigh_GrSLPrecision);
126         varyingHandler->addVarying("edge_space_coord", &fEdgeSpaceCoord, kHigh_GrSLPrecision);
127     }
128 
129     void emitCubicGeometry(GrGLSLGeometryBuilder*, const char* emitVertexFn,
130                            const char* wind, const char* rtAdjust) const override;
131     void emitPerVertexGeometryCode(SkString* fnBody, const char* position, const char* coverage,
132                                    const char* wind) const override;
133     void emitShaderCoverage(GrGLSLFragmentBuilder*, const char* outputCoverage) const override;
134 
135 protected:
136     GrShaderVar        fEdgeDistanceEquation;
137     GrShaderVar        fEdgeDistanceDerivatives;
138     GrShaderVar        fEdgeSpaceTransform;
139     GrGLSLGeoToFrag    fKLMD;
140     GrGLSLGeoToFrag    fdKLMDdx;
141     GrGLSLGeoToFrag    fdKLMDdy;
142     GrGLSLGeoToFrag    fEdgeSpaceCoord;
143 
144     typedef GrCCPRCubicProcessor INHERITED;
145 };
146 
147 #endif
148