blob: 5954ee36df610263ab630ad99cd74b75ff5927ce [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;
joshualitt290c09b2014-12-19 13:45:20 -0800101 bool onCanMakeEqual(const GrBatchTracker&,
102 const GrGeometryProcessor&,
103 const GrBatchTracker&) const SK_OVERRIDE;
joshualitt9b989322014-12-15 14:16:27 -0800104
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000105private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800106 GrConicEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000107
bsalomon0e08fc12014-10-15 08:19:04 -0700108 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000109
joshualitt56995b52014-12-11 15:44:02 -0800110 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
111 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700112 }
113
joshualitt9b989322014-12-15 14:16:27 -0800114 uint8_t fCoverageScale;
joshualittb0a8a372014-09-23 09:50:21 -0700115 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800116 const GrAttribute* fInPosition;
117 const GrAttribute* fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000118
joshualittb0a8a372014-09-23 09:50:21 -0700119 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000120
joshualitt249af152014-09-15 11:41:13 -0700121 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000122};
123
124///////////////////////////////////////////////////////////////////////////////
125/**
126 * The output of this effect is a hairline edge for quadratics.
127 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
128 * two components of the vertex attribute. At the three control points that define
129 * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
130 * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
131 * Requires shader derivative instruction support.
132 */
133class GrGLQuadEffect;
134
joshualitt249af152014-09-15 11:41:13 -0700135class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000136public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800137 static GrGeometryProcessor* Create(GrColor color,
138 const GrPrimitiveEdgeType edgeType,
139 const GrDrawTargetCaps& caps,
140 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000141 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700142 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000143 if (!caps.shaderDerivativeSupport()) {
144 return NULL;
145 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800146 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700147 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000148 if (!caps.shaderDerivativeSupport()) {
149 return NULL;
150 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800151 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700152 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -0800153 return SkNEW_ARGS(GrQuadEffect, (color, coverage, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000154 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000155 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000156 }
157 }
158
159 virtual ~GrQuadEffect();
160
joshualitteb2a6762014-12-04 11:35:33 -0800161 virtual const char* name() const SK_OVERRIDE { return "Quad"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000162
joshualitt2dd1ae02014-12-03 06:24:10 -0800163 inline const GrAttribute* inPosition() const { return fInPosition; }
164 inline const GrAttribute* inHairQuadEdge() const { return fInHairQuadEdge; }
joshualittb0a8a372014-09-23 09:50:21 -0700165 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
166 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
167 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000168
joshualitteb2a6762014-12-04 11:35:33 -0800169 virtual void getGLProcessorKey(const GrBatchTracker& bt,
170 const GrGLCaps& caps,
171 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000172
joshualitteb2a6762014-12-04 11:35:33 -0800173 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000174
joshualitt9b989322014-12-15 14:16:27 -0800175 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
joshualitt290c09b2014-12-19 13:45:20 -0800176 bool onCanMakeEqual(const GrBatchTracker&,
177 const GrGeometryProcessor&,
178 const GrBatchTracker&) const SK_OVERRIDE;
joshualitt9b989322014-12-15 14:16:27 -0800179
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000180private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800181 GrQuadEffect(GrColor, uint8_t coverage, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000182
bsalomon0e08fc12014-10-15 08:19:04 -0700183 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000184
joshualitt56995b52014-12-11 15:44:02 -0800185 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
186 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700187 }
188
joshualitt9b989322014-12-15 14:16:27 -0800189 uint8_t fCoverageScale;
joshualittb0a8a372014-09-23 09:50:21 -0700190 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800191 const GrAttribute* fInPosition;
192 const GrAttribute* fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000193
joshualittb0a8a372014-09-23 09:50:21 -0700194 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000195
joshualitt249af152014-09-15 11:41:13 -0700196 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000197};
198
199//////////////////////////////////////////////////////////////////////////////
200/**
201 * Shader is based off of "Resolution Independent Curve Rendering using
202 * Programmable Graphics Hardware" by Loop and Blinn.
203 * The output of this effect is a hairline edge for non rational cubics.
204 * Cubics are specified by implicit equation K^3 - LM.
205 * K, L, and M, are the first three values of the vertex attribute,
206 * the fourth value is not used. Distance is calculated using a
207 * first order approximation from the taylor series.
208 * Coverage for AA is max(0, 1-distance).
209 */
210class GrGLCubicEffect;
211
joshualitt249af152014-09-15 11:41:13 -0700212class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000213public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800214 static GrGeometryProcessor* Create(GrColor color,
215 const GrPrimitiveEdgeType edgeType,
joshualittb0a8a372014-09-23 09:50:21 -0700216 const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000217 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700218 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000219 if (!caps.shaderDerivativeSupport()) {
220 return NULL;
221 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800222 return SkNEW_ARGS(GrCubicEffect, (color, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700223 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000224 if (!caps.shaderDerivativeSupport()) {
225 return NULL;
226 }
joshualitt2e3b3e32014-12-09 13:31:14 -0800227 return SkNEW_ARGS(GrCubicEffect, (color, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700228 case kFillBW_GrProcessorEdgeType:
joshualitt2e3b3e32014-12-09 13:31:14 -0800229 return SkNEW_ARGS(GrCubicEffect, (color, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000230 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000231 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000232 }
233 }
234
235 virtual ~GrCubicEffect();
236
joshualitteb2a6762014-12-04 11:35:33 -0800237 virtual const char* name() const SK_OVERRIDE { return "Cubic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000238
joshualitt2dd1ae02014-12-03 06:24:10 -0800239 inline const GrAttribute* inPosition() const { return fInPosition; }
240 inline const GrAttribute* inCubicCoeffs() const { return fInCubicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -0700241 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
242 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
243 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000244
joshualitteb2a6762014-12-04 11:35:33 -0800245 virtual void getGLProcessorKey(const GrBatchTracker& bt,
246 const GrGLCaps& caps,
247 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000248
joshualitteb2a6762014-12-04 11:35:33 -0800249 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000250
joshualitt9b989322014-12-15 14:16:27 -0800251 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
joshualitt290c09b2014-12-19 13:45:20 -0800252 bool onCanMakeEqual(const GrBatchTracker&,
253 const GrGeometryProcessor&,
254 const GrBatchTracker&) const SK_OVERRIDE;
joshualitt9b989322014-12-15 14:16:27 -0800255
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000256private:
joshualitt2e3b3e32014-12-09 13:31:14 -0800257 GrCubicEffect(GrColor, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000258
bsalomon0e08fc12014-10-15 08:19:04 -0700259 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000260
joshualitt56995b52014-12-11 15:44:02 -0800261 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
262 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700263 }
264
joshualittb0a8a372014-09-23 09:50:21 -0700265 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800266 const GrAttribute* fInPosition;
267 const GrAttribute* fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000268
joshualittb0a8a372014-09-23 09:50:21 -0700269 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000270
joshualitt249af152014-09-15 11:41:13 -0700271 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000272};
273
274#endif