blob: edb14080d4165ba1db7bc7c3c82bd7c23a763873 [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
bsalomoneb1cb5c2015-05-22 08:01:09 -070011#include "GrCaps.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:
bungeman06ca8ec2016-06-09 08:01:03 -070061 static sk_sp<GrGeometryProcessor> Make(GrColor color,
62 const SkMatrix& viewMatrix,
63 const GrPrimitiveEdgeType edgeType,
64 const GrCaps& caps,
65 const SkMatrix& localMatrix,
66 bool usesLocalCoords,
67 uint8_t coverage = 0xff) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000068 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -070069 case kFillAA_GrProcessorEdgeType:
jvanverthe9c0fc62015-04-29 11:18:05 -070070 if (!caps.shaderCaps()->shaderDerivativeSupport()) {
halcanary96fcdcc2015-08-27 07:41:13 -070071 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000072 }
bungeman06ca8ec2016-06-09 08:01:03 -070073 return sk_sp<GrGeometryProcessor>(
74 new GrConicEffect(color, viewMatrix, coverage, kFillAA_GrProcessorEdgeType,
75 localMatrix, usesLocalCoords));
joshualittb0a8a372014-09-23 09:50:21 -070076 case kHairlineAA_GrProcessorEdgeType:
jvanverthe9c0fc62015-04-29 11:18:05 -070077 if (!caps.shaderCaps()->shaderDerivativeSupport()) {
halcanary96fcdcc2015-08-27 07:41:13 -070078 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000079 }
bungeman06ca8ec2016-06-09 08:01:03 -070080 return sk_sp<GrGeometryProcessor>(
81 new GrConicEffect(color, viewMatrix, coverage,
82 kHairlineAA_GrProcessorEdgeType, localMatrix,
83 usesLocalCoords));
joshualittb0a8a372014-09-23 09:50:21 -070084 case kFillBW_GrProcessorEdgeType:
bungeman06ca8ec2016-06-09 08:01:03 -070085 return sk_sp<GrGeometryProcessor>(
86 new GrConicEffect(color, viewMatrix, coverage, kFillBW_GrProcessorEdgeType,
87 localMatrix, usesLocalCoords));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +000088 default:
halcanary96fcdcc2015-08-27 07:41:13 -070089 return nullptr;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000090 }
91 }
92
93 virtual ~GrConicEffect();
94
mtklein36352bf2015-03-25 18:17:31 -070095 const char* name() const override { return "Conic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +000096
joshualitt71c92602015-01-14 08:12:47 -080097 inline const Attribute* inPosition() const { return fInPosition; }
98 inline const Attribute* inConicCoeffs() const { return fInConicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -070099 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
100 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
101 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
joshualitt88c23fc2015-05-13 14:18:07 -0700102 GrColor color() const { return fColor; }
joshualittb8c241a2015-05-19 08:23:30 -0700103 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
joshualitte578a952015-05-14 10:09:13 -0700104 const SkMatrix& viewMatrix() const { return fViewMatrix; }
joshualitte3ababe2015-05-15 07:56:07 -0700105 const SkMatrix& localMatrix() const { return fLocalMatrix; }
joshualittb8c241a2015-05-19 08:23:30 -0700106 bool usesLocalCoords() const { return fUsesLocalCoords; }
107 uint8_t coverageScale() const { return fCoverageScale; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000108
Brian Salomon94efbf52016-11-29 13:43:05 -0500109 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000110
Brian Salomon94efbf52016-11-29 13:43:05 -0500111 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000112
113private:
joshualitt8059eb92014-12-29 15:10:07 -0800114 GrConicEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrPrimitiveEdgeType,
joshualittb8c241a2015-05-19 08:23:30 -0700115 const SkMatrix& localMatrix, bool usesLocalCoords);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000116
joshualitt88c23fc2015-05-13 14:18:07 -0700117 GrColor fColor;
joshualitte578a952015-05-14 10:09:13 -0700118 SkMatrix fViewMatrix;
joshualitte3ababe2015-05-15 07:56:07 -0700119 SkMatrix fLocalMatrix;
joshualittb8c241a2015-05-19 08:23:30 -0700120 bool fUsesLocalCoords;
joshualitt88c23fc2015-05-13 14:18:07 -0700121 uint8_t fCoverageScale;
122 GrPrimitiveEdgeType fEdgeType;
joshualitt71c92602015-01-14 08:12:47 -0800123 const Attribute* fInPosition;
124 const Attribute* fInConicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000125
joshualittb0a8a372014-09-23 09:50:21 -0700126 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000127
joshualitt249af152014-09-15 11:41:13 -0700128 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000129};
130
131///////////////////////////////////////////////////////////////////////////////
132/**
133 * The output of this effect is a hairline edge for quadratics.
134 * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
135 * two components of the vertex attribute. At the three control points that define
136 * the Quadratic, u, v have the values {0,0}, {1/2, 0}, and {1, 1} respectively.
137 * Coverage for AA is min(0, 1-distance). 3rd & 4th cimponent unused.
138 * Requires shader derivative instruction support.
139 */
140class GrGLQuadEffect;
141
joshualitt249af152014-09-15 11:41:13 -0700142class GrQuadEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000143public:
bungeman06ca8ec2016-06-09 08:01:03 -0700144 static sk_sp<GrGeometryProcessor> Make(GrColor color,
145 const SkMatrix& viewMatrix,
146 const GrPrimitiveEdgeType edgeType,
147 const GrCaps& caps,
148 const SkMatrix& localMatrix,
149 bool usesLocalCoords,
150 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:
jvanverthe9c0fc62015-04-29 11:18:05 -0700153 if (!caps.shaderCaps()->shaderDerivativeSupport()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700154 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000155 }
bungeman06ca8ec2016-06-09 08:01:03 -0700156 return sk_sp<GrGeometryProcessor>(
157 new GrQuadEffect(color, viewMatrix, coverage, kFillAA_GrProcessorEdgeType,
158 localMatrix, usesLocalCoords));
joshualittb0a8a372014-09-23 09:50:21 -0700159 case kHairlineAA_GrProcessorEdgeType:
jvanverthe9c0fc62015-04-29 11:18:05 -0700160 if (!caps.shaderCaps()->shaderDerivativeSupport()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700161 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000162 }
bungeman06ca8ec2016-06-09 08:01:03 -0700163 return sk_sp<GrGeometryProcessor>(
164 new GrQuadEffect(color, viewMatrix, coverage,
165 kHairlineAA_GrProcessorEdgeType, localMatrix,
166 usesLocalCoords));
joshualittb0a8a372014-09-23 09:50:21 -0700167 case kFillBW_GrProcessorEdgeType:
bungeman06ca8ec2016-06-09 08:01:03 -0700168 return sk_sp<GrGeometryProcessor>(
169 new GrQuadEffect(color, viewMatrix, coverage, kFillBW_GrProcessorEdgeType,
170 localMatrix, usesLocalCoords));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000171 default:
halcanary96fcdcc2015-08-27 07:41:13 -0700172 return nullptr;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000173 }
174 }
175
176 virtual ~GrQuadEffect();
177
mtklein36352bf2015-03-25 18:17:31 -0700178 const char* name() const override { return "Quad"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000179
joshualitt71c92602015-01-14 08:12:47 -0800180 inline const Attribute* inPosition() const { return fInPosition; }
181 inline const Attribute* inHairQuadEdge() const { return fInHairQuadEdge; }
joshualittb0a8a372014-09-23 09:50:21 -0700182 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
183 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
184 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
joshualitt88c23fc2015-05-13 14:18:07 -0700185 GrColor color() const { return fColor; }
joshualittb8c241a2015-05-19 08:23:30 -0700186 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
joshualitte578a952015-05-14 10:09:13 -0700187 const SkMatrix& viewMatrix() const { return fViewMatrix; }
joshualitte3ababe2015-05-15 07:56:07 -0700188 const SkMatrix& localMatrix() const { return fLocalMatrix; }
joshualittb8c241a2015-05-19 08:23:30 -0700189 bool usesLocalCoords() const { return fUsesLocalCoords; }
190 uint8_t coverageScale() const { return fCoverageScale; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000191
Brian Salomon94efbf52016-11-29 13:43:05 -0500192 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000193
Brian Salomon94efbf52016-11-29 13:43:05 -0500194 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000195
196private:
joshualitt8059eb92014-12-29 15:10:07 -0800197 GrQuadEffect(GrColor, const SkMatrix& viewMatrix, uint8_t coverage, GrPrimitiveEdgeType,
joshualittb8c241a2015-05-19 08:23:30 -0700198 const SkMatrix& localMatrix, bool usesLocalCoords);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000199
joshualitt88c23fc2015-05-13 14:18:07 -0700200 GrColor fColor;
joshualitte578a952015-05-14 10:09:13 -0700201 SkMatrix fViewMatrix;
joshualitte3ababe2015-05-15 07:56:07 -0700202 SkMatrix fLocalMatrix;
joshualittb8c241a2015-05-19 08:23:30 -0700203 bool fUsesLocalCoords;
joshualitt88c23fc2015-05-13 14:18:07 -0700204 uint8_t fCoverageScale;
205 GrPrimitiveEdgeType fEdgeType;
joshualitt71c92602015-01-14 08:12:47 -0800206 const Attribute* fInPosition;
207 const Attribute* fInHairQuadEdge;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000208
joshualittb0a8a372014-09-23 09:50:21 -0700209 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000210
joshualitt249af152014-09-15 11:41:13 -0700211 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000212};
213
214//////////////////////////////////////////////////////////////////////////////
215/**
216 * Shader is based off of "Resolution Independent Curve Rendering using
217 * Programmable Graphics Hardware" by Loop and Blinn.
218 * The output of this effect is a hairline edge for non rational cubics.
219 * Cubics are specified by implicit equation K^3 - LM.
220 * K, L, and M, are the first three values of the vertex attribute,
221 * the fourth value is not used. Distance is calculated using a
222 * first order approximation from the taylor series.
223 * Coverage for AA is max(0, 1-distance).
224 */
225class GrGLCubicEffect;
226
joshualitt249af152014-09-15 11:41:13 -0700227class GrCubicEffect : public GrGeometryProcessor {
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000228public:
bungeman06ca8ec2016-06-09 08:01:03 -0700229 static sk_sp<GrGeometryProcessor> Make(GrColor color,
230 const SkMatrix& viewMatrix,
231 const GrPrimitiveEdgeType edgeType,
232 const GrCaps& caps) {
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000233 switch (edgeType) {
joshualittb0a8a372014-09-23 09:50:21 -0700234 case kFillAA_GrProcessorEdgeType:
jvanverthe9c0fc62015-04-29 11:18:05 -0700235 if (!caps.shaderCaps()->shaderDerivativeSupport()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700236 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000237 }
bungeman06ca8ec2016-06-09 08:01:03 -0700238 return sk_sp<GrGeometryProcessor>(
239 new GrCubicEffect(color, viewMatrix, kFillAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700240 case kHairlineAA_GrProcessorEdgeType:
jvanverthe9c0fc62015-04-29 11:18:05 -0700241 if (!caps.shaderCaps()->shaderDerivativeSupport()) {
halcanary96fcdcc2015-08-27 07:41:13 -0700242 return nullptr;
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000243 }
bungeman06ca8ec2016-06-09 08:01:03 -0700244 return sk_sp<GrGeometryProcessor>(
245 new GrCubicEffect(color, viewMatrix, kHairlineAA_GrProcessorEdgeType));
joshualittb0a8a372014-09-23 09:50:21 -0700246 case kFillBW_GrProcessorEdgeType:
bungeman06ca8ec2016-06-09 08:01:03 -0700247 return sk_sp<GrGeometryProcessor>(
248 new GrCubicEffect(color, viewMatrix, kFillBW_GrProcessorEdgeType));
commit-bot@chromium.orgcabf4b22014-03-05 18:27:43 +0000249 default:
halcanary96fcdcc2015-08-27 07:41:13 -0700250 return nullptr;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000251 }
252 }
253
254 virtual ~GrCubicEffect();
255
mtklein36352bf2015-03-25 18:17:31 -0700256 const char* name() const override { return "Cubic"; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000257
joshualitt71c92602015-01-14 08:12:47 -0800258 inline const Attribute* inPosition() const { return fInPosition; }
259 inline const Attribute* inCubicCoeffs() const { return fInCubicCoeffs; }
joshualittb0a8a372014-09-23 09:50:21 -0700260 inline bool isAntiAliased() const { return GrProcessorEdgeTypeIsAA(fEdgeType); }
261 inline bool isFilled() const { return GrProcessorEdgeTypeIsFill(fEdgeType); }
262 inline GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
joshualitt88c23fc2015-05-13 14:18:07 -0700263 GrColor color() const { return fColor; }
joshualittb8c241a2015-05-19 08:23:30 -0700264 bool colorIgnored() const { return GrColor_ILLEGAL == fColor; }
joshualitte578a952015-05-14 10:09:13 -0700265 const SkMatrix& viewMatrix() const { return fViewMatrix; }
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000266
Brian Salomon94efbf52016-11-29 13:43:05 -0500267 void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000268
Brian Salomon94efbf52016-11-29 13:43:05 -0500269 GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000270
271private:
joshualitt8059eb92014-12-29 15:10:07 -0800272 GrCubicEffect(GrColor, const SkMatrix& viewMatrix, GrPrimitiveEdgeType);
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000273
joshualitt88c23fc2015-05-13 14:18:07 -0700274 GrColor fColor;
joshualitte578a952015-05-14 10:09:13 -0700275 SkMatrix fViewMatrix;
joshualitt88c23fc2015-05-13 14:18:07 -0700276 GrPrimitiveEdgeType fEdgeType;
joshualitt71c92602015-01-14 08:12:47 -0800277 const Attribute* fInPosition;
278 const Attribute* fInCubicCoeffs;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000279
joshualittb0a8a372014-09-23 09:50:21 -0700280 GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000281
joshualitt249af152014-09-15 11:41:13 -0700282 typedef GrGeometryProcessor INHERITED;
commit-bot@chromium.org07e1c3f2013-08-22 20:41:15 +0000283};
284
285#endif