blob: a58211b9b63b24ec610ba37836179d1ee5a163cd [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
joshualitt9b989322014-12-15 14:16:27 -0800100 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
101 bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
102
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000103private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800104 GrConicEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000105
bsalomon0e08fc12014-10-15 08:19:04 -0700106 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000107
joshualitt56995b52014-12-11 15:44:02 -0800108 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
109 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700110 }
111
joshualitt9b989322014-12-15 14:16:27 -0800112 uint8_t fCoverageScale;
joshualittb0a8a372014-09-23 09:50:21 -0700113 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800114 const GrAttribute* fInPosition;
115 const GrAttribute* fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000116
joshualittb0a8a372014-09-23 09:50:21 -0700117 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000118
joshualitt249af152014-09-15 11:41:13 -0700119 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000120};
121
122///////////////////////////////////////////////////////////////////////////////
123/**
124 * The output of this effect is a hairline edge for quadratics.
125 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
126 * two components of the vertex attribute. At the three control points that define
127 * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
128 * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
129 * Requires shader derivative instruction support.
130 */
131class GrGLQuadEffect;
132
joshualitt249af152014-09-15 11:41:13 -0700133class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000134public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800135 static GrGeometryProcessor* Create(GrColor color,
136 const GrPrimitiveEdgeType edgeType,
137 const GrDrawTargetCaps& caps,
138 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000139 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700140 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000141 if (!caps.shaderDerivativeSupport()) {
142 return NULL;
143 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800144 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700145 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000146 if (!caps.shaderDerivativeSupport()) {
147 return NULL;
148 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800149 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700150 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -0800151 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000152 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000153 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000154 }
155 }
156
157 virtual ~GrQuadEffect();
158
joshualitteb2a6762014-12-04 11:35:33 -0800159 virtual const char* name() const SK_OVERRIDE { return "Quad"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000160
joshualitt2dd1ae02014-12-03 06:24:10 -0800161 inline const GrAttribute* inPosition() const { return fInPosition; }
162 inline const GrAttribute* inHairQuadEdge() const { return fInHairQuadEdge; }
joshualittb0a8a372014-09-23 09:50:21 -0700163 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
164 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
165 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000166
joshualitteb2a6762014-12-04 11:35:33 -0800167 virtual void getGLProcessorKey(const GrBatchTracker& bt,
168 const GrGLCaps& caps,
169 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000170
joshualitteb2a6762014-12-04 11:35:33 -0800171 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000172
joshualitt9b989322014-12-15 14:16:27 -0800173 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
174 bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
175
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000176private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800177 GrQuadEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000178
bsalomon0e08fc12014-10-15 08:19:04 -0700179 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000180
joshualitt56995b52014-12-11 15:44:02 -0800181 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
182 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700183 }
184
joshualitt9b989322014-12-15 14:16:27 -0800185 uint8_t fCoverageScale;
joshualittb0a8a372014-09-23 09:50:21 -0700186 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800187 const GrAttribute* fInPosition;
188 const GrAttribute* fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000189
joshualittb0a8a372014-09-23 09:50:21 -0700190 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000191
joshualitt249af152014-09-15 11:41:13 -0700192 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000193};
194
195//////////////////////////////////////////////////////////////////////////////
196/**
197 * Shader is based off of "Resolution Independent Curve Rendering using
198 * Programmable Graphics Hardware" by Loop and Blinn.
199 * The output of this effect is a hairline edge for non rational cubics.
200 * Cubics are specified by implicit equation K^3 - LM.
201 * K, L, and M, are the first three values of the vertex attribute,
202 * the fourth value is not used. Distance is calculated using a
203 * first order approximation from the taylor series.
204 * Coverage for AA is max(0, 1-distance).
205 */
206class GrGLCubicEffect;
207
joshualitt249af152014-09-15 11:41:13 -0700208class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000209public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800210 static GrGeometryProcessor* Create(GrColor color,
211 const GrPrimitiveEdgeType edgeType,
joshualittb0a8a372014-09-23 09:50:21 -0700212 const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000213 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700214 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000215 if (!caps.shaderDerivativeSupport()) {
216 return NULL;
217 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800218 return SkNEW_ARGS(GrCubicEffect, (color, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700219 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000220 if (!caps.shaderDerivativeSupport()) {
221 return NULL;
222 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800223 return SkNEW_ARGS(GrCubicEffect, (color, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700224 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -0800225 return SkNEW_ARGS(GrCubicEffect, (color, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000226 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000227 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000228 }
229 }
230
231 virtual ~GrCubicEffect();
232
joshualitteb2a6762014-12-04 11:35:33 -0800233 virtual const char* name() const SK_OVERRIDE { return "Cubic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000234
joshualitt2dd1ae02014-12-03 06:24:10 -0800235 inline const GrAttribute* inPosition() const { return fInPosition; }
236 inline const GrAttribute* inCubicCoeffs() const { return fInCubicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -0700237 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
238 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
239 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000240
joshualitteb2a6762014-12-04 11:35:33 -0800241 virtual void getGLProcessorKey(const GrBatchTracker& bt,
242 const GrGLCaps& caps,
243 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000244
joshualitteb2a6762014-12-04 11:35:33 -0800245 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000246
joshualitt9b989322014-12-15 14:16:27 -0800247 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
248 bool onCanMakeEqual(const GrBatchTracker&, const GrBatchTracker&) const SK_OVERRIDE;
249
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000250private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800251 GrCubicEffect(GrColor, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000252
bsalomon0e08fc12014-10-15 08:19:04 -0700253 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000254
joshualitt56995b52014-12-11 15:44:02 -0800255 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
256 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700257 }
258
joshualittb0a8a372014-09-23 09:50:21 -0700259 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800260 const GrAttribute* fInPosition;
261 const GrAttribute* fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000262
joshualittb0a8a372014-09-23 09:50:21 -0700263 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000264
joshualitt249af152014-09-15 11:41:13 -0700265 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000266};
267
268#endif