blob: 53b1053b0c8ebddbbcc7fe45263b328b0add130e [file] [log] [blame]
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +00001/*
2 * Copyright 2013 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 GrBezierEffect_DEFINED
skia.committer@gmail.com44a77c82013-08-23 07:01:29 +00009#define GrBezierEffect_DEFINED
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000010
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000011#include "GrDrawTargetCaps.h"
joshualittb0a8a372014-09-23 09:50:21 -070012#include "GrProcessor.h"
joshualitt249af152014-09-15 11:41:13 -070013#include "GrGeometryProcessor.h"
egdaniel605dd0f2014-11-12 08:35:25 -080014#include "GrInvariantOutput.h"
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000015#include "GrTypesPriv.h"
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000016
17/**
18 * Shader is based off of Loop-Blinn Quadratic GPU Rendering
19 * The output of this effect is a hairline edge for conics.
20 * Conics specified by implicit equation K^2 - LM.
21 * K, L, and M, are the first three values of the vertex attribute,
22 * the fourth value is not used. Distance is calculated using a
23 * first order approximation from the taylor series.
24 * Coverage for AA is max(0, 1-distance).
25 *
26 * Test were also run using a second order distance approximation.
27 * There were two versions of the second order approx. The first version
28 * is of roughly the form:
29 * f(q) = |f(p)| - ||f'(p)||*||q-p|| - ||f''(p)||*||q-p||^2.
30 * The second is similar:
31 * f(q) = |f(p)| + ||f'(p)||*||q-p|| + ||f''(p)||*||q-p||^2.
32 * The exact version of the equations can be found in the paper
33 * "Distance Approximations for Rasterizing Implicit Curves" by Gabriel Taubin
34 *
35 * In both versions we solve the quadratic for ||q-p||.
36 * Version 1:
37 * gFM is magnitude of first partials and gFM2 is magnitude of 2nd partials (as derived from paper)
38 * builder->fsCodeAppend("\t\tedgeAlpha = (sqrt(gFM*gFM+4.0*func*gF2M) - gFM)/(2.0*gF2M);\n");
39 * Version 2:
40 * builder->fsCodeAppend("\t\tedgeAlpha = (gFM - sqrt(gFM*gFM-4.0*func*gF2M))/(2.0*gF2M);\n");
41 *
42 * Also note that 2nd partials of k,l,m are zero
43 *
44 * When comparing the two second order approximations to the first order approximations,
45 * the following results were found. Version 1 tends to underestimate the distances, thus it
46 * basically increases all the error that we were already seeing in the first order
47 * approx. So this version is not the one to use. Version 2 has the opposite effect
48 * and tends to overestimate the distances. This is much closer to what we are
49 * looking for. It is able to render ellipses (even thin ones) without the need to chop.
50 * However, it can not handle thin hyperbolas well and thus would still rely on
51 * chopping to tighten the clipping. Another side effect of the overestimating is
52 * that the curves become much thinner and "ropey". If all that was ever rendered
53 * were "not too thin" curves and ellipses then 2nd order may have an advantage since
54 * only one geometry would need to be rendered. However no benches were run comparing
55 * chopped first order and non chopped 2nd order.
56 */
57class GrGLConicEffect;
58
joshualitt249af152014-09-15 11:41:13 -070059class GrConicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000060public:
joshualitt2e3b3e32014-12-09 13:31:14 -080061 static GrGeometryProcessor* Create(GrColor color,
62 const GrPrimitiveEdgeType edgeType,
63 const GrDrawTargetCaps& caps,
64 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000065 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -070066 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000067 if (!caps.shaderDerivativeSupport()) {
68 return NULL;
69 }
joshualitt2e3b3e32014-12-09 13:31:14 -080070 return SkNEW_ARGS(GrConicEffect, (color, coverage, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -070071 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000072 if (!caps.shaderDerivativeSupport()) {
73 return NULL;
74 }
joshualitt2e3b3e32014-12-09 13:31:14 -080075 return SkNEW_ARGS(GrConicEffect, (color, coverage,
76 kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -070077 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -080078 return SkNEW_ARGS(GrConicEffect, (color, coverage, kFillBW_GrProcessorEdgeType));;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000079 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000080 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000081 }
82 }
83
84 virtual ~GrConicEffect();
85
joshualitteb2a6762014-12-04 11:35:33 -080086 virtual const char* name() const SK_OVERRIDE { return "Conic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000087
joshualitt2dd1ae02014-12-03 06:24:10 -080088 inline const GrAttribute* inPosition() const { return fInPosition; }
89 inline const GrAttribute* inConicCoeffs() const { return fInConicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -070090 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
91 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
92 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000093
joshualitteb2a6762014-12-04 11:35:33 -080094 virtual void getGLProcessorKey(const GrBatchTracker& bt,
95 const GrGLCaps& caps,
96 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000097
joshualitteb2a6762014-12-04 11:35:33 -080098 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000099
100private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800101 GrConicEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000102
bsalomon0e08fc12014-10-15 08:19:04 -0700103 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000104
joshualitt56995b52014-12-11 15:44:02 -0800105 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
106 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700107 }
108
joshualittb0a8a372014-09-23 09:50:21 -0700109 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800110 const GrAttribute* fInPosition;
111 const GrAttribute* fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000112
joshualittb0a8a372014-09-23 09:50:21 -0700113 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000114
joshualitt249af152014-09-15 11:41:13 -0700115 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000116};
117
118///////////////////////////////////////////////////////////////////////////////
119/**
120 * The output of this effect is a hairline edge for quadratics.
121 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
122 * two components of the vertex attribute. At the three control points that define
123 * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
124 * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
125 * Requires shader derivative instruction support.
126 */
127class GrGLQuadEffect;
128
joshualitt249af152014-09-15 11:41:13 -0700129class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000130public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800131 static GrGeometryProcessor* Create(GrColor color,
132 const GrPrimitiveEdgeType edgeType,
133 const GrDrawTargetCaps& caps,
134 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000135 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700136 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000137 if (!caps.shaderDerivativeSupport()) {
138 return NULL;
139 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800140 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700141 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000142 if (!caps.shaderDerivativeSupport()) {
143 return NULL;
144 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800145 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700146 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -0800147 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000148 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000149 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000150 }
151 }
152
153 virtual ~GrQuadEffect();
154
joshualitteb2a6762014-12-04 11:35:33 -0800155 virtual const char* name() const SK_OVERRIDE { return "Quad"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000156
joshualitt2dd1ae02014-12-03 06:24:10 -0800157 inline const GrAttribute* inPosition() const { return fInPosition; }
158 inline const GrAttribute* inHairQuadEdge() const { return fInHairQuadEdge; }
joshualittb0a8a372014-09-23 09:50:21 -0700159 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
160 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
161 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000162
joshualitteb2a6762014-12-04 11:35:33 -0800163 virtual void getGLProcessorKey(const GrBatchTracker& bt,
164 const GrGLCaps& caps,
165 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000166
joshualitteb2a6762014-12-04 11:35:33 -0800167 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000168
169private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800170 GrQuadEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000171
bsalomon0e08fc12014-10-15 08:19:04 -0700172 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000173
joshualitt56995b52014-12-11 15:44:02 -0800174 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
175 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700176 }
177
joshualittb0a8a372014-09-23 09:50:21 -0700178 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800179 const GrAttribute* fInPosition;
180 const GrAttribute* fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000181
joshualittb0a8a372014-09-23 09:50:21 -0700182 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000183
joshualitt249af152014-09-15 11:41:13 -0700184 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000185};
186
187//////////////////////////////////////////////////////////////////////////////
188/**
189 * Shader is based off of "Resolution Independent Curve Rendering using
190 * Programmable Graphics Hardware" by Loop and Blinn.
191 * The output of this effect is a hairline edge for non rational cubics.
192 * Cubics are specified by implicit equation K^3 - LM.
193 * K, L, and M, are the first three values of the vertex attribute,
194 * the fourth value is not used. Distance is calculated using a
195 * first order approximation from the taylor series.
196 * Coverage for AA is max(0, 1-distance).
197 */
198class GrGLCubicEffect;
199
joshualitt249af152014-09-15 11:41:13 -0700200class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000201public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800202 static GrGeometryProcessor* Create(GrColor color,
203 const GrPrimitiveEdgeType edgeType,
joshualittb0a8a372014-09-23 09:50:21 -0700204 const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000205 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700206 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000207 if (!caps.shaderDerivativeSupport()) {
208 return NULL;
209 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800210 return SkNEW_ARGS(GrCubicEffect, (color, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700211 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000212 if (!caps.shaderDerivativeSupport()) {
213 return NULL;
214 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800215 return SkNEW_ARGS(GrCubicEffect, (color, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700216 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -0800217 return SkNEW_ARGS(GrCubicEffect, (color, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000218 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000219 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000220 }
221 }
222
223 virtual ~GrCubicEffect();
224
joshualitteb2a6762014-12-04 11:35:33 -0800225 virtual const char* name() const SK_OVERRIDE { return "Cubic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000226
joshualitt2dd1ae02014-12-03 06:24:10 -0800227 inline const GrAttribute* inPosition() const { return fInPosition; }
228 inline const GrAttribute* inCubicCoeffs() const { return fInCubicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -0700229 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
230 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
231 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000232
joshualitteb2a6762014-12-04 11:35:33 -0800233 virtual void getGLProcessorKey(const GrBatchTracker& bt,
234 const GrGLCaps& caps,
235 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000236
joshualitteb2a6762014-12-04 11:35:33 -0800237 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000238
239private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800240 GrCubicEffect(GrColor, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000241
bsalomon0e08fc12014-10-15 08:19:04 -0700242 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000243
joshualitt56995b52014-12-11 15:44:02 -0800244 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
245 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700246 }
247
joshualittb0a8a372014-09-23 09:50:21 -0700248 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800249 const GrAttribute* fInPosition;
250 const GrAttribute* fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000251
joshualittb0a8a372014-09-23 09:50:21 -0700252 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000253
joshualitt249af152014-09-15 11:41:13 -0700254 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000255};
256
257#endif