blob: 62b1c529c991171890ae6e219181101b6c47c197 [file] [log] [blame]
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +00001/*
2 * Copyright 2014 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#include "GrOvalEffect.h"
joshualitteb2a6762014-12-04 11:35:33 -08009
10#include "GrFragmentProcessor.h"
joshualitteb2a6762014-12-04 11:35:33 -080011#include "SkRect.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050012#include "GrShaderCaps.h"
egdaniel64c47282015-11-13 06:54:19 -080013#include "glsl/GrGLSLFragmentProcessor.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070015#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080016#include "glsl/GrGLSLUniformHandler.h"
Brian Salomon94efbf52016-11-29 13:43:05 -050017#include "../private/GrGLSL.h"
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000018
19//////////////////////////////////////////////////////////////////////////////
20
joshualittb0a8a372014-09-23 09:50:21 -070021class CircleEffect : public GrFragmentProcessor {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000022public:
bungeman06ca8ec2016-06-09 08:01:03 -070023 static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center,
24 SkScalar radius);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000025
Mike Kleinfc6c37b2016-09-27 09:34:10 -040026 virtual ~CircleEffect() {}
joshualitteb2a6762014-12-04 11:35:33 -080027
mtklein36352bf2015-03-25 18:17:31 -070028 const char* name() const override { return "Circle"; }
joshualitteb2a6762014-12-04 11:35:33 -080029
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000030 const SkPoint& getCenter() const { return fCenter; }
31 SkScalar getRadius() const { return fRadius; }
32
joshualittb0a8a372014-09-23 09:50:21 -070033 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000034
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000035private:
joshualittb0a8a372014-09-23 09:50:21 -070036 CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000037
egdaniel57d3b032015-11-13 11:57:27 -080038 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070039
Brian Salomon94efbf52016-11-29 13:43:05 -050040 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070041
mtklein36352bf2015-03-25 18:17:31 -070042 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000043
44 SkPoint fCenter;
45 SkScalar fRadius;
joshualittb0a8a372014-09-23 09:50:21 -070046 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000047
joshualittb0a8a372014-09-23 09:50:21 -070048 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000049
joshualittb0a8a372014-09-23 09:50:21 -070050 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000051};
52
bungeman06ca8ec2016-06-09 08:01:03 -070053sk_sp<GrFragmentProcessor> CircleEffect::Make(GrPrimitiveEdgeType edgeType, const SkPoint& center,
54 SkScalar radius) {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000055 SkASSERT(radius >= 0);
bungeman06ca8ec2016-06-09 08:01:03 -070056 return sk_sp<GrFragmentProcessor>(new CircleEffect(edgeType, center, radius));
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000057}
58
joshualittb0a8a372014-09-23 09:50:21 -070059CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
Brian Salomonf3b995b2017-02-15 10:22:23 -050060 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
61 , fCenter(c)
62 , fRadius(r)
63 , fEdgeType(edgeType) {
joshualitteb2a6762014-12-04 11:35:33 -080064 this->initClassID<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000065}
66
bsalomon0e08fc12014-10-15 08:19:04 -070067bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -070068 const CircleEffect& ce = other.cast<CircleEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +000069 return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000070}
71
72//////////////////////////////////////////////////////////////////////////////
73
joshualittb0a8a372014-09-23 09:50:21 -070074GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleEffect);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000075
Hal Canary6f6961e2017-01-31 13:50:44 -050076#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -070077sk_sp<GrFragmentProcessor> CircleEffect::TestCreate(GrProcessorTestData* d) {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000078 SkPoint center;
joshualitt0067ff52015-07-08 14:26:19 -070079 center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
80 center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
81 SkScalar radius = d->fRandom->nextRangeF(0.f, 1000.f);
joshualittb0a8a372014-09-23 09:50:21 -070082 GrPrimitiveEdgeType et;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000083 do {
joshualitt0067ff52015-07-08 14:26:19 -070084 et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
joshualittb0a8a372014-09-23 09:50:21 -070085 } while (kHairlineAA_GrProcessorEdgeType == et);
bungeman06ca8ec2016-06-09 08:01:03 -070086 return CircleEffect::Make(et, center, radius);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000087}
Hal Canary6f6961e2017-01-31 13:50:44 -050088#endif
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000089
90//////////////////////////////////////////////////////////////////////////////
91
egdaniel64c47282015-11-13 06:54:19 -080092class GLCircleEffect : public GrGLSLFragmentProcessor {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000093public:
robertphillips9cdb9922016-02-03 12:25:40 -080094 GLCircleEffect() : fPrevRadius(-1.0f) { }
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000095
wangyix7c157a92015-07-22 15:08:53 -070096 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000097
Brian Salomon94efbf52016-11-29 13:43:05 -050098 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000099
wangyixb1daa862015-08-18 11:29:31 -0700100protected:
egdaniel018fb622015-10-28 07:26:40 -0700101 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000102
103private:
egdaniel018fb622015-10-28 07:26:40 -0700104 GrGLSLProgramDataManager::UniformHandle fCircleUniform;
105 SkPoint fPrevCenter;
106 SkScalar fPrevRadius;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000107
egdaniel64c47282015-11-13 06:54:19 -0800108 typedef GrGLSLFragmentProcessor INHERITED;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000109};
110
wangyix7c157a92015-07-22 15:08:53 -0700111void GLCircleEffect::emitCode(EmitArgs& args) {
112 const CircleEffect& ce = args.fFp.cast<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000113 const char *circleName;
bsalomonfcabe422015-04-28 12:43:01 -0700114 // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular
115 // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
cdalton5e58cee2016-02-11 12:49:47 -0800116 fCircleUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800117 kVec4f_GrSLType, kDefault_GrSLPrecision,
118 "circle",
119 &circleName);
joshualitt30ba4362014-08-21 20:18:45 -0700120
cdalton85285412016-02-18 12:37:07 -0800121 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000122
joshualittb0a8a372014-09-23 09:50:21 -0700123 SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
bsalomonfcabe422015-04-28 12:43:01 -0700124 // TODO: Right now the distance to circle caclulation is performed in a space normalized to the
125 // radius and then denormalized. This is to prevent overflow on devices that have a "real"
126 // mediump. It'd be nice to only to this on mediump devices but we currently don't have the
127 // caps here.
joshualittb0a8a372014-09-23 09:50:21 -0700128 if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
Ethan Nicholas38657112017-02-09 17:01:22 -0500129 fragBuilder->codeAppendf("float d = (length((%s.xy - sk_FragCoord.xy) * %s.w) - 1.0) * "
130 "%s.z;",
131 circleName, circleName, circleName);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000132 } else {
Ethan Nicholas38657112017-02-09 17:01:22 -0500133 fragBuilder->codeAppendf("float d = (1.0 - length((%s.xy - sk_FragCoord.xy) * %s.w)) * "
134 "%s.z;",
135 circleName, circleName, circleName);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000136 }
joshualittb0a8a372014-09-23 09:50:21 -0700137 if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
bsalomone87256c42015-12-09 17:14:40 -0800138 fragBuilder->codeAppend("d = clamp(d, 0.0, 1.0);");
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000139 } else {
bsalomone87256c42015-12-09 17:14:40 -0800140 fragBuilder->codeAppend("d = d > 0.5 ? 1.0 : 0.0;");
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000141 }
142
bsalomone87256c42015-12-09 17:14:40 -0800143 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
egdaniel4ca2e602015-11-18 08:01:26 -0800144 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("d")).c_str());
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000145}
146
Brian Salomon94efbf52016-11-29 13:43:05 -0500147void GLCircleEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700148 GrProcessorKeyBuilder* b) {
149 const CircleEffect& ce = processor.cast<CircleEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700150 b->add32(ce.getEdgeType());
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000151}
152
egdaniel018fb622015-10-28 07:26:40 -0700153void GLCircleEffect::onSetData(const GrGLSLProgramDataManager& pdman,
154 const GrProcessor& processor) {
joshualittb0a8a372014-09-23 09:50:21 -0700155 const CircleEffect& ce = processor.cast<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000156 if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000157 SkScalar radius = ce.getRadius();
joshualittb0a8a372014-09-23 09:50:21 -0700158 if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000159 radius -= 0.5f;
160 } else {
161 radius += 0.5f;
162 }
bsalomonfcabe422015-04-28 12:43:01 -0700163 pdman.set4f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius,
164 SkScalarInvert(radius));
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000165 fPrevCenter = ce.getCenter();
166 fPrevRadius = ce.getRadius();
167 }
168}
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000169
joshualitteb2a6762014-12-04 11:35:33 -0800170///////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000171
Brian Salomon94efbf52016-11-29 13:43:05 -0500172void CircleEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800173 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800174 GLCircleEffect::GenKey(*this, caps, b);
175}
176
egdaniel57d3b032015-11-13 11:57:27 -0800177GrGLSLFragmentProcessor* CircleEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800178 return new GLCircleEffect;
joshualitteb2a6762014-12-04 11:35:33 -0800179}
180
181//////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000182
joshualittb0a8a372014-09-23 09:50:21 -0700183class EllipseEffect : public GrFragmentProcessor {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000184public:
bungeman06ca8ec2016-06-09 08:01:03 -0700185 static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center,
186 SkScalar rx, SkScalar ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000187
Mike Kleinfc6c37b2016-09-27 09:34:10 -0400188 virtual ~EllipseEffect() {}
joshualitteb2a6762014-12-04 11:35:33 -0800189
mtklein36352bf2015-03-25 18:17:31 -0700190 const char* name() const override { return "Ellipse"; }
joshualitteb2a6762014-12-04 11:35:33 -0800191
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000192 const SkPoint& getCenter() const { return fCenter; }
193 SkVector getRadii() const { return fRadii; }
194
joshualittb0a8a372014-09-23 09:50:21 -0700195 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000196
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000197private:
joshualittb0a8a372014-09-23 09:50:21 -0700198 EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000199
egdaniel57d3b032015-11-13 11:57:27 -0800200 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700201
Brian Salomon94efbf52016-11-29 13:43:05 -0500202 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700203
mtklein36352bf2015-03-25 18:17:31 -0700204 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000205
206 SkPoint fCenter;
207 SkVector fRadii;
joshualittb0a8a372014-09-23 09:50:21 -0700208 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000209
joshualittb0a8a372014-09-23 09:50:21 -0700210 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000211
joshualittb0a8a372014-09-23 09:50:21 -0700212 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000213};
214
bungeman06ca8ec2016-06-09 08:01:03 -0700215sk_sp<GrFragmentProcessor> EllipseEffect::Make(GrPrimitiveEdgeType edgeType,
216 const SkPoint& center,
217 SkScalar rx,
218 SkScalar ry) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000219 SkASSERT(rx >= 0 && ry >= 0);
bungeman06ca8ec2016-06-09 08:01:03 -0700220 return sk_sp<GrFragmentProcessor>(new EllipseEffect(edgeType, center, rx, ry));
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000221}
222
Brian Salomon587e08f2017-01-27 10:59:27 -0500223EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx,
224 SkScalar ry)
Brian Salomonf3b995b2017-02-15 10:22:23 -0500225 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon587e08f2017-01-27 10:59:27 -0500226 , fCenter(c)
227 , fRadii(SkVector::Make(rx, ry))
228 , fEdgeType(edgeType) {
joshualitteb2a6762014-12-04 11:35:33 -0800229 this->initClassID<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000230}
231
bsalomon0e08fc12014-10-15 08:19:04 -0700232bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700233 const EllipseEffect& ee = other.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000234 return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
235}
236
237//////////////////////////////////////////////////////////////////////////////
238
joshualittb0a8a372014-09-23 09:50:21 -0700239GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000240
Hal Canary6f6961e2017-01-31 13:50:44 -0500241#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700242sk_sp<GrFragmentProcessor> EllipseEffect::TestCreate(GrProcessorTestData* d) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000243 SkPoint center;
joshualitt0067ff52015-07-08 14:26:19 -0700244 center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
245 center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
246 SkScalar rx = d->fRandom->nextRangeF(0.f, 1000.f);
247 SkScalar ry = d->fRandom->nextRangeF(0.f, 1000.f);
joshualittb0a8a372014-09-23 09:50:21 -0700248 GrPrimitiveEdgeType et;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000249 do {
joshualitt0067ff52015-07-08 14:26:19 -0700250 et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
joshualittb0a8a372014-09-23 09:50:21 -0700251 } while (kHairlineAA_GrProcessorEdgeType == et);
bungeman06ca8ec2016-06-09 08:01:03 -0700252 return EllipseEffect::Make(et, center, rx, ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000253}
Hal Canary6f6961e2017-01-31 13:50:44 -0500254#endif
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000255
256//////////////////////////////////////////////////////////////////////////////
257
egdaniel64c47282015-11-13 06:54:19 -0800258class GLEllipseEffect : public GrGLSLFragmentProcessor {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000259public:
robertphillips9cdb9922016-02-03 12:25:40 -0800260 GLEllipseEffect() {
261 fPrevRadii.fX = -1.0f;
262 }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000263
robertphillips9cdb9922016-02-03 12:25:40 -0800264 void emitCode(EmitArgs&) override;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000265
Brian Salomon94efbf52016-11-29 13:43:05 -0500266 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000267
wangyixb1daa862015-08-18 11:29:31 -0700268protected:
egdaniel018fb622015-10-28 07:26:40 -0700269 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000270
271private:
egdaniel018fb622015-10-28 07:26:40 -0700272 GrGLSLProgramDataManager::UniformHandle fEllipseUniform;
bsalomone87256c42015-12-09 17:14:40 -0800273 GrGLSLProgramDataManager::UniformHandle fScaleUniform;
egdaniel018fb622015-10-28 07:26:40 -0700274 SkPoint fPrevCenter;
275 SkVector fPrevRadii;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000276
egdaniel64c47282015-11-13 06:54:19 -0800277 typedef GrGLSLFragmentProcessor INHERITED;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000278};
279
wangyix7c157a92015-07-22 15:08:53 -0700280void GLEllipseEffect::emitCode(EmitArgs& args) {
281 const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000282 const char *ellipseName;
283 // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
bsalomonc41f4d62015-08-03 14:23:03 -0700284 // The last two terms can underflow on mediump, so we use highp.
cdalton5e58cee2016-02-11 12:49:47 -0800285 fEllipseUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800286 kVec4f_GrSLType, kHigh_GrSLPrecision,
287 "ellipse",
288 &ellipseName);
bsalomone87256c42015-12-09 17:14:40 -0800289 // If we're on a device with a "real" mediump then we'll do the distance computation in a space
290 // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
291 // inverse squared radii uniform values are already in this normalized space. The center is
292 // not.
293 const char* scaleName = nullptr;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500294 if (args.fShaderCaps->floatPrecisionVaries()) {
bsalomone87256c42015-12-09 17:14:40 -0800295 fScaleUniform = args.fUniformHandler->addUniform(
cdalton5e58cee2016-02-11 12:49:47 -0800296 kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision,
bsalomone87256c42015-12-09 17:14:40 -0800297 "scale", &scaleName);
298 }
joshualitt30ba4362014-08-21 20:18:45 -0700299
cdalton85285412016-02-18 12:37:07 -0800300 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000301
302 // d is the offset to the ellipse center
Ethan Nicholas38657112017-02-09 17:01:22 -0500303 fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName);
bsalomone87256c42015-12-09 17:14:40 -0800304 if (scaleName) {
305 fragBuilder->codeAppendf("d *= %s.y;", scaleName);
306 }
307 fragBuilder->codeAppendf("vec2 Z = d * %s.zw;", ellipseName);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000308 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
bsalomone87256c42015-12-09 17:14:40 -0800309 fragBuilder->codeAppend("float implicit = dot(Z, d) - 1.0;");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000310 // grad_dot is the squared length of the gradient of the implicit.
bsalomone87256c42015-12-09 17:14:40 -0800311 fragBuilder->codeAppendf("float grad_dot = 4.0 * dot(Z, Z);");
312 // Avoid calling inversesqrt on zero.
313 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
314 fragBuilder->codeAppendf("float approx_dist = implicit * inversesqrt(grad_dot);");
315 if (scaleName) {
316 fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
317 }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000318
319 switch (ee.getEdgeType()) {
joshualittb0a8a372014-09-23 09:50:21 -0700320 case kFillAA_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800321 fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000322 break;
joshualittb0a8a372014-09-23 09:50:21 -0700323 case kInverseFillAA_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800324 fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000325 break;
joshualittb0a8a372014-09-23 09:50:21 -0700326 case kFillBW_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800327 fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 0.0 : 1.0;");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000328 break;
joshualittb0a8a372014-09-23 09:50:21 -0700329 case kInverseFillBW_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800330 fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 1.0 : 0.0;");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000331 break;
joshualittb0a8a372014-09-23 09:50:21 -0700332 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000333 SkFAIL("Hairline not expected here.");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000334 }
335
bsalomone87256c42015-12-09 17:14:40 -0800336 fragBuilder->codeAppendf("%s = %s;", args.fOutputColor,
egdaniel4ca2e602015-11-18 08:01:26 -0800337 (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000338}
339
Brian Salomon94efbf52016-11-29 13:43:05 -0500340void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700341 GrProcessorKeyBuilder* b) {
joshualitt49586be2014-09-16 08:21:41 -0700342 const EllipseEffect& ee = effect.cast<EllipseEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700343 b->add32(ee.getEdgeType());
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000344}
345
egdaniel018fb622015-10-28 07:26:40 -0700346void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman,
347 const GrProcessor& effect) {
joshualitt49586be2014-09-16 08:21:41 -0700348 const EllipseEffect& ee = effect.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000349 if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
bsalomone87256c42015-12-09 17:14:40 -0800350 float invRXSqd;
351 float invRYSqd;
352 // If we're using a scale factor to work around precision issues, choose the larger radius
353 // as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
354 if (fScaleUniform.isValid()) {
355 if (ee.getRadii().fX > ee.getRadii().fY) {
356 invRXSqd = 1.f;
357 invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) /
358 (ee.getRadii().fY * ee.getRadii().fY);
359 pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX);
360 } else {
361 invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) /
362 (ee.getRadii().fX * ee.getRadii().fX);
363 invRYSqd = 1.f;
364 pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY);
365 }
366 } else {
367 invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
368 invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
369 }
kkinnunen7510b222014-07-30 00:04:16 -0700370 pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000371 fPrevCenter = ee.getCenter();
372 fPrevRadii = ee.getRadii();
373 }
374}
375
joshualitteb2a6762014-12-04 11:35:33 -0800376///////////////////////////////////////////////////////////////////////////////////////////////////
377
Brian Salomon94efbf52016-11-29 13:43:05 -0500378void EllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800379 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800380 GLEllipseEffect::GenKey(*this, caps, b);
381}
382
egdaniel57d3b032015-11-13 11:57:27 -0800383GrGLSLFragmentProcessor* EllipseEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800384 return new GLEllipseEffect;
joshualitteb2a6762014-12-04 11:35:33 -0800385}
386
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000387//////////////////////////////////////////////////////////////////////////////
388
bungeman06ca8ec2016-06-09 08:01:03 -0700389sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
joshualittb0a8a372014-09-23 09:50:21 -0700390 if (kHairlineAA_GrProcessorEdgeType == edgeType) {
halcanary96fcdcc2015-08-27 07:41:13 -0700391 return nullptr;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000392 }
393 SkScalar w = oval.width();
394 SkScalar h = oval.height();
395 if (SkScalarNearlyEqual(w, h)) {
396 w /= 2;
bungeman06ca8ec2016-06-09 08:01:03 -0700397 return CircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000398 } else {
399 w /= 2;
400 h /= 2;
bungeman06ca8ec2016-06-09 08:01:03 -0700401 return EllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000402 }
403
halcanary96fcdcc2015-08-27 07:41:13 -0700404 return nullptr;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000405}