blob: 1bd93b64c99c38598e0df691965d051421bc1aee [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,
joshualitt8059eb92014-12-29 15:10:07 -080062 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -080063 const GrPrimitiveEdgeType edgeType,
64 const GrDrawTargetCaps& caps,
joshualittd27f73e2014-12-29 07:43:36 -080065 const SkMatrix& localMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -080066 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000067 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -070068 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000069 if (!caps.shaderDerivativeSupport()) {
70 return NULL;
71 }
joshualitt8059eb92014-12-29 15:10:07 -080072 return SkNEW_ARGS(GrConicEffect, (color, viewMatrix, coverage,
73 kFillAA_GrProcessorEdgeType,
joshualittd27f73e2014-12-29 07:43:36 -080074 localMatrix));
joshualittb0a8a372014-09-23 09:50:21 -070075 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000076 if (!caps.shaderDerivativeSupport()) {
77 return NULL;
78 }
joshualitt8059eb92014-12-29 15:10:07 -080079 return SkNEW_ARGS(GrConicEffect, (color, viewMatrix, coverage,
joshualittd27f73e2014-12-29 07:43:36 -080080 kHairlineAA_GrProcessorEdgeType,
81 localMatrix));
joshualittb0a8a372014-09-23 09:50:21 -070082 case kFillBW_GrProcessorEdgeType:
joshualitt8059eb92014-12-29 15:10:07 -080083 return SkNEW_ARGS(GrConicEffect, (color, viewMatrix, coverage,
84 kFillBW_GrProcessorEdgeType,
joshualittd27f73e2014-12-29 07:43:36 -080085 localMatrix));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000086 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000087 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000088 }
89 }
90
91 virtual ~GrConicEffect();
92
joshualitteb2a6762014-12-04 11:35:33 -080093 virtual const char* name() const SK_OVERRIDE { return "Conic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000094
joshualitt2dd1ae02014-12-03 06:24:10 -080095 inline const GrAttribute* inPosition() const { return fInPosition; }
96 inline const GrAttribute* inConicCoeffs() const { return fInConicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -070097 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
98 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
99 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000100
joshualitteb2a6762014-12-04 11:35:33 -0800101 virtual void getGLProcessorKey(const GrBatchTracker& bt,
102 const GrGLCaps& caps,
103 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000104
joshualitteb2a6762014-12-04 11:35:33 -0800105 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000106
joshualitt9b989322014-12-15 14:16:27 -0800107 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
joshualitt290c09b2014-12-19 13:45:20 -0800108 bool onCanMakeEqual(const GrBatchTracker&,
109 const GrGeometryProcessor&,
110 const GrBatchTracker&) const SK_OVERRIDE;
joshualitt9b989322014-12-15 14:16:27 -0800111
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000112private:
joshualitt8059eb92014-12-29 15:10:07 -0800113 GrConicEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrPrimitiveEdgeType,
114 const SkMatrix& localMatrix);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000115
bsalomon0e08fc12014-10-15 08:19:04 -0700116 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000117
joshualitt56995b52014-12-11 15:44:02 -0800118 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
119 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700120 }
121
joshualitt9b989322014-12-15 14:16:27 -0800122 uint8_t fCoverageScale;
joshualittb0a8a372014-09-23 09:50:21 -0700123 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800124 const GrAttribute* fInPosition;
125 const GrAttribute* fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000126
joshualittb0a8a372014-09-23 09:50:21 -0700127 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000128
joshualitt249af152014-09-15 11:41:13 -0700129 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000130};
131
132///////////////////////////////////////////////////////////////////////////////
133/**
134 * The output of this effect is a hairline edge for quadratics.
135 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
136 * two components of the vertex attribute. At the three control points that define
137 * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
138 * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
139 * Requires shader derivative instruction support.
140 */
141class GrGLQuadEffect;
142
joshualitt249af152014-09-15 11:41:13 -0700143class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000144public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800145 static GrGeometryProcessor* Create(GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800146 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800147 const GrPrimitiveEdgeType edgeType,
148 const GrDrawTargetCaps& caps,
joshualittd27f73e2014-12-29 07:43:36 -0800149 const SkMatrix& localMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800150 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000151 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700152 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000153 if (!caps.shaderDerivativeSupport()) {
154 return NULL;
155 }
joshualitt8059eb92014-12-29 15:10:07 -0800156 return SkNEW_ARGS(GrQuadEffect, (color, viewMatrix, coverage,
157 kFillAA_GrProcessorEdgeType,
joshualittd27f73e2014-12-29 07:43:36 -0800158 localMatrix));
joshualittb0a8a372014-09-23 09:50:21 -0700159 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000160 if (!caps.shaderDerivativeSupport()) {
161 return NULL;
162 }
joshualitt8059eb92014-12-29 15:10:07 -0800163 return SkNEW_ARGS(GrQuadEffect, (color, viewMatrix, coverage,
164 kHairlineAA_GrProcessorEdgeType,
joshualittd27f73e2014-12-29 07:43:36 -0800165 localMatrix));
joshualittb0a8a372014-09-23 09:50:21 -0700166 case kFillBW_GrProcessorEdgeType:
joshualitt8059eb92014-12-29 15:10:07 -0800167 return SkNEW_ARGS(GrQuadEffect, (color, viewMatrix, coverage,
168 kFillBW_GrProcessorEdgeType,
joshualittd27f73e2014-12-29 07:43:36 -0800169 localMatrix));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000170 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000171 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000172 }
173 }
174
175 virtual ~GrQuadEffect();
176
joshualitteb2a6762014-12-04 11:35:33 -0800177 virtual const char* name() const SK_OVERRIDE { return "Quad"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000178
joshualitt2dd1ae02014-12-03 06:24:10 -0800179 inline const GrAttribute* inPosition() const { return fInPosition; }
180 inline const GrAttribute* inHairQuadEdge() const { return fInHairQuadEdge; }
joshualittb0a8a372014-09-23 09:50:21 -0700181 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
182 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
183 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000184
joshualitteb2a6762014-12-04 11:35:33 -0800185 virtual void getGLProcessorKey(const GrBatchTracker& bt,
186 const GrGLCaps& caps,
187 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000188
joshualitteb2a6762014-12-04 11:35:33 -0800189 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000190
joshualitt9b989322014-12-15 14:16:27 -0800191 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
joshualitt290c09b2014-12-19 13:45:20 -0800192 bool onCanMakeEqual(const GrBatchTracker&,
193 const GrGeometryProcessor&,
194 const GrBatchTracker&) const SK_OVERRIDE;
joshualitt9b989322014-12-15 14:16:27 -0800195
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000196private:
joshualitt8059eb92014-12-29 15:10:07 -0800197 GrQuadEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrPrimitiveEdgeType,
198 const SkMatrix& localMatrix);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000199
bsalomon0e08fc12014-10-15 08:19:04 -0700200 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000201
joshualitt56995b52014-12-11 15:44:02 -0800202 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
203 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700204 }
205
joshualitt9b989322014-12-15 14:16:27 -0800206 uint8_t fCoverageScale;
joshualittb0a8a372014-09-23 09:50:21 -0700207 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800208 const GrAttribute* fInPosition;
209 const GrAttribute* fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000210
joshualittb0a8a372014-09-23 09:50:21 -0700211 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000212
joshualitt249af152014-09-15 11:41:13 -0700213 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000214};
215
216//////////////////////////////////////////////////////////////////////////////
217/**
218 * Shader is based off of "Resolution Independent Curve Rendering using
219 * Programmable Graphics Hardware" by Loop and Blinn.
220 * The output of this effect is a hairline edge for non rational cubics.
221 * Cubics are specified by implicit equation K^3 - LM.
222 * K, L, and M, are the first three values of the vertex attribute,
223 * the fourth value is not used. Distance is calculated using a
224 * first order approximation from the taylor series.
225 * Coverage for AA is max(0, 1-distance).
226 */
227class GrGLCubicEffect;
228
joshualitt249af152014-09-15 11:41:13 -0700229class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000230public:
joshualitt2e3b3e32014-12-09 13:31:14 -0800231 static GrGeometryProcessor* Create(GrColor color,
joshualitt8059eb92014-12-29 15:10:07 -0800232 const SkMatrix& viewMatrix,
joshualitt2e3b3e32014-12-09 13:31:14 -0800233 const GrPrimitiveEdgeType edgeType,
joshualittb0a8a372014-09-23 09:50:21 -0700234 const GrDrawTargetCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000235 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700236 case kFillAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000237 if (!caps.shaderDerivativeSupport()) {
238 return NULL;
239 }
joshualitt8059eb92014-12-29 15:10:07 -0800240 return SkNEW_ARGS(GrCubicEffect, (color, viewMatrix, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700241 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000242 if (!caps.shaderDerivativeSupport()) {
243 return NULL;
244 }
joshualitt8059eb92014-12-29 15:10:07 -0800245 return SkNEW_ARGS(GrCubicEffect, (color, viewMatrix,
246 kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700247 case kFillBW_GrProcessorEdgeType:
joshualitt8059eb92014-12-29 15:10:07 -0800248 return SkNEW_ARGS(GrCubicEffect, (color, viewMatrix,
249 kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000250 default:
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000251 return NULL;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000252 }
253 }
254
255 virtual ~GrCubicEffect();
256
joshualitteb2a6762014-12-04 11:35:33 -0800257 virtual const char* name() const SK_OVERRIDE { return "Cubic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000258
joshualitt2dd1ae02014-12-03 06:24:10 -0800259 inline const GrAttribute* inPosition() const { return fInPosition; }
260 inline const GrAttribute* inCubicCoeffs() const { return fInCubicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -0700261 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
262 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
263 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000264
joshualitteb2a6762014-12-04 11:35:33 -0800265 virtual void getGLProcessorKey(const GrBatchTracker& bt,
266 const GrGLCaps& caps,
267 GrProcessorKeyBuilder* b) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000268
joshualitteb2a6762014-12-04 11:35:33 -0800269 virtual GrGLGeometryProcessor* createGLInstance(const GrBatchTracker& bt) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000270
joshualitt9b989322014-12-15 14:16:27 -0800271 void initBatchTracker(GrBatchTracker*, const InitBT&) const SK_OVERRIDE;
joshualitt290c09b2014-12-19 13:45:20 -0800272 bool onCanMakeEqual(const GrBatchTracker&,
273 const GrGeometryProcessor&,
274 const GrBatchTracker&) const SK_OVERRIDE;
joshualitt9b989322014-12-15 14:16:27 -0800275
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000276private:
joshualitt8059eb92014-12-29 15:10:07 -0800277 GrCubicEffect(GrColor, const SkMatrix& viewMatrix, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000278
bsalomon0e08fc12014-10-15 08:19:04 -0700279 virtual bool onIsEqual(const GrGeometryProcessor& other) const SK_OVERRIDE;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000280
joshualitt56995b52014-12-11 15:44:02 -0800281 virtual void onGetInvariantOutputCoverage(GrInitInvariantOutput* out) const SK_OVERRIDE {
282 out->setUnknownSingleComponent();
egdaniel1a8ecdf2014-10-03 06:24:12 -0700283 }
284
joshualittb0a8a372014-09-23 09:50:21 -0700285 GrPrimitiveEdgeType fEdgeType;
joshualitt2dd1ae02014-12-03 06:24:10 -0800286 const GrAttribute* fInPosition;
287 const GrAttribute* fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000288
joshualittb0a8a372014-09-23 09:50:21 -0700289 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000290
joshualitt249af152014-09-15 11:41:13 -0700291 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000292};
293
294#endif