blob: 20e476d25580eedbb2fb1eaa3f67e6d663577298 [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
Brian Salomond3b65972017-03-22 12:05:03 -040026 ~CircleEffect() override {}
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
Brian Salomon0c26a9d2017-07-06 10:09:38 -040048 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:
Brian Salomonab015ef2017-04-04 10:15:51 -0400101 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) 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
Ethan Nicholas2983f402017-05-08 09:36:08 -0400143 fragBuilder->codeAppendf("%s = %s * d;", args.fOutputColor, args.fInputColor);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000144}
145
Brian Salomon94efbf52016-11-29 13:43:05 -0500146void GLCircleEffect::GenKey(const GrProcessor& processor, const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700147 GrProcessorKeyBuilder* b) {
148 const CircleEffect& ce = processor.cast<CircleEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700149 b->add32(ce.getEdgeType());
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000150}
151
egdaniel018fb622015-10-28 07:26:40 -0700152void GLCircleEffect::onSetData(const GrGLSLProgramDataManager& pdman,
Brian Salomonab015ef2017-04-04 10:15:51 -0400153 const GrFragmentProcessor& processor) {
joshualittb0a8a372014-09-23 09:50:21 -0700154 const CircleEffect& ce = processor.cast<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000155 if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000156 SkScalar radius = ce.getRadius();
joshualittb0a8a372014-09-23 09:50:21 -0700157 if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000158 radius -= 0.5f;
159 } else {
160 radius += 0.5f;
161 }
bsalomonfcabe422015-04-28 12:43:01 -0700162 pdman.set4f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius,
163 SkScalarInvert(radius));
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000164 fPrevCenter = ce.getCenter();
165 fPrevRadius = ce.getRadius();
166 }
167}
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000168
joshualitteb2a6762014-12-04 11:35:33 -0800169///////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000170
Brian Salomon94efbf52016-11-29 13:43:05 -0500171void CircleEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800172 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800173 GLCircleEffect::GenKey(*this, caps, b);
174}
175
egdaniel57d3b032015-11-13 11:57:27 -0800176GrGLSLFragmentProcessor* CircleEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800177 return new GLCircleEffect;
joshualitteb2a6762014-12-04 11:35:33 -0800178}
179
180//////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000181
joshualittb0a8a372014-09-23 09:50:21 -0700182class EllipseEffect : public GrFragmentProcessor {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000183public:
bungeman06ca8ec2016-06-09 08:01:03 -0700184 static sk_sp<GrFragmentProcessor> Make(GrPrimitiveEdgeType, const SkPoint& center,
185 SkScalar rx, SkScalar ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000186
Brian Salomond3b65972017-03-22 12:05:03 -0400187 ~EllipseEffect() override {}
joshualitteb2a6762014-12-04 11:35:33 -0800188
mtklein36352bf2015-03-25 18:17:31 -0700189 const char* name() const override { return "Ellipse"; }
joshualitteb2a6762014-12-04 11:35:33 -0800190
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000191 const SkPoint& getCenter() const { return fCenter; }
192 SkVector getRadii() const { return fRadii; }
193
joshualittb0a8a372014-09-23 09:50:21 -0700194 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000195
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000196private:
joshualittb0a8a372014-09-23 09:50:21 -0700197 EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000198
egdaniel57d3b032015-11-13 11:57:27 -0800199 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700200
Brian Salomon94efbf52016-11-29 13:43:05 -0500201 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700202
mtklein36352bf2015-03-25 18:17:31 -0700203 bool onIsEqual(const GrFragmentProcessor&) const override;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000204
205 SkPoint fCenter;
206 SkVector fRadii;
joshualittb0a8a372014-09-23 09:50:21 -0700207 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000208
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400209 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000210
joshualittb0a8a372014-09-23 09:50:21 -0700211 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000212};
213
bungeman06ca8ec2016-06-09 08:01:03 -0700214sk_sp<GrFragmentProcessor> EllipseEffect::Make(GrPrimitiveEdgeType edgeType,
215 const SkPoint& center,
216 SkScalar rx,
217 SkScalar ry) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000218 SkASSERT(rx >= 0 && ry >= 0);
bungeman06ca8ec2016-06-09 08:01:03 -0700219 return sk_sp<GrFragmentProcessor>(new EllipseEffect(edgeType, center, rx, ry));
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000220}
221
Brian Salomon587e08f2017-01-27 10:59:27 -0500222EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx,
223 SkScalar ry)
Brian Salomonf3b995b2017-02-15 10:22:23 -0500224 : INHERITED(kCompatibleWithCoverageAsAlpha_OptimizationFlag)
Brian Salomon587e08f2017-01-27 10:59:27 -0500225 , fCenter(c)
226 , fRadii(SkVector::Make(rx, ry))
227 , fEdgeType(edgeType) {
joshualitteb2a6762014-12-04 11:35:33 -0800228 this->initClassID<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000229}
230
bsalomon0e08fc12014-10-15 08:19:04 -0700231bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700232 const EllipseEffect& ee = other.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000233 return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
234}
235
236//////////////////////////////////////////////////////////////////////////////
237
joshualittb0a8a372014-09-23 09:50:21 -0700238GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000239
Hal Canary6f6961e2017-01-31 13:50:44 -0500240#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700241sk_sp<GrFragmentProcessor> EllipseEffect::TestCreate(GrProcessorTestData* d) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000242 SkPoint center;
joshualitt0067ff52015-07-08 14:26:19 -0700243 center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
244 center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
245 SkScalar rx = d->fRandom->nextRangeF(0.f, 1000.f);
246 SkScalar ry = d->fRandom->nextRangeF(0.f, 1000.f);
joshualittb0a8a372014-09-23 09:50:21 -0700247 GrPrimitiveEdgeType et;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000248 do {
joshualitt0067ff52015-07-08 14:26:19 -0700249 et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
joshualittb0a8a372014-09-23 09:50:21 -0700250 } while (kHairlineAA_GrProcessorEdgeType == et);
bungeman06ca8ec2016-06-09 08:01:03 -0700251 return EllipseEffect::Make(et, center, rx, ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000252}
Hal Canary6f6961e2017-01-31 13:50:44 -0500253#endif
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000254
255//////////////////////////////////////////////////////////////////////////////
256
egdaniel64c47282015-11-13 06:54:19 -0800257class GLEllipseEffect : public GrGLSLFragmentProcessor {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000258public:
robertphillips9cdb9922016-02-03 12:25:40 -0800259 GLEllipseEffect() {
260 fPrevRadii.fX = -1.0f;
261 }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000262
robertphillips9cdb9922016-02-03 12:25:40 -0800263 void emitCode(EmitArgs&) override;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000264
Brian Salomon94efbf52016-11-29 13:43:05 -0500265 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000266
wangyixb1daa862015-08-18 11:29:31 -0700267protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400268 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000269
270private:
egdaniel018fb622015-10-28 07:26:40 -0700271 GrGLSLProgramDataManager::UniformHandle fEllipseUniform;
bsalomone87256c42015-12-09 17:14:40 -0800272 GrGLSLProgramDataManager::UniformHandle fScaleUniform;
egdaniel018fb622015-10-28 07:26:40 -0700273 SkPoint fPrevCenter;
274 SkVector fPrevRadii;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000275
egdaniel64c47282015-11-13 06:54:19 -0800276 typedef GrGLSLFragmentProcessor INHERITED;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000277};
278
wangyix7c157a92015-07-22 15:08:53 -0700279void GLEllipseEffect::emitCode(EmitArgs& args) {
280 const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000281 const char *ellipseName;
282 // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
bsalomonc41f4d62015-08-03 14:23:03 -0700283 // The last two terms can underflow on mediump, so we use highp.
cdalton5e58cee2016-02-11 12:49:47 -0800284 fEllipseUniform = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800285 kVec4f_GrSLType, kHigh_GrSLPrecision,
286 "ellipse",
287 &ellipseName);
bsalomone87256c42015-12-09 17:14:40 -0800288 // If we're on a device with a "real" mediump then we'll do the distance computation in a space
289 // that is normalized by the larger radius. The scale uniform will be scale, 1/scale. The
290 // inverse squared radii uniform values are already in this normalized space. The center is
291 // not.
292 const char* scaleName = nullptr;
Brian Salomon1edc5b92016-11-29 13:43:46 -0500293 if (args.fShaderCaps->floatPrecisionVaries()) {
bsalomone87256c42015-12-09 17:14:40 -0800294 fScaleUniform = args.fUniformHandler->addUniform(
cdalton5e58cee2016-02-11 12:49:47 -0800295 kFragment_GrShaderFlag, kVec2f_GrSLType, kDefault_GrSLPrecision,
bsalomone87256c42015-12-09 17:14:40 -0800296 "scale", &scaleName);
297 }
joshualitt30ba4362014-08-21 20:18:45 -0700298
cdalton85285412016-02-18 12:37:07 -0800299 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000300
301 // d is the offset to the ellipse center
Ethan Nicholas38657112017-02-09 17:01:22 -0500302 fragBuilder->codeAppendf("vec2 d = sk_FragCoord.xy - %s.xy;", ellipseName);
bsalomone87256c42015-12-09 17:14:40 -0800303 if (scaleName) {
304 fragBuilder->codeAppendf("d *= %s.y;", scaleName);
305 }
306 fragBuilder->codeAppendf("vec2 Z = d * %s.zw;", ellipseName);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000307 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
bsalomone87256c42015-12-09 17:14:40 -0800308 fragBuilder->codeAppend("float implicit = dot(Z, d) - 1.0;");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000309 // grad_dot is the squared length of the gradient of the implicit.
bsalomone87256c42015-12-09 17:14:40 -0800310 fragBuilder->codeAppendf("float grad_dot = 4.0 * dot(Z, Z);");
311 // Avoid calling inversesqrt on zero.
312 fragBuilder->codeAppend("grad_dot = max(grad_dot, 1.0e-4);");
313 fragBuilder->codeAppendf("float approx_dist = implicit * inversesqrt(grad_dot);");
314 if (scaleName) {
315 fragBuilder->codeAppendf("approx_dist *= %s.x;", scaleName);
316 }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000317
318 switch (ee.getEdgeType()) {
joshualittb0a8a372014-09-23 09:50:21 -0700319 case kFillAA_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800320 fragBuilder->codeAppend("float alpha = clamp(0.5 - approx_dist, 0.0, 1.0);");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000321 break;
joshualittb0a8a372014-09-23 09:50:21 -0700322 case kInverseFillAA_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800323 fragBuilder->codeAppend("float alpha = clamp(0.5 + approx_dist, 0.0, 1.0);");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000324 break;
joshualittb0a8a372014-09-23 09:50:21 -0700325 case kFillBW_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800326 fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 0.0 : 1.0;");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000327 break;
joshualittb0a8a372014-09-23 09:50:21 -0700328 case kInverseFillBW_GrProcessorEdgeType:
bsalomone87256c42015-12-09 17:14:40 -0800329 fragBuilder->codeAppend("float alpha = approx_dist > 0.0 ? 1.0 : 0.0;");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000330 break;
joshualittb0a8a372014-09-23 09:50:21 -0700331 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000332 SkFAIL("Hairline not expected here.");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000333 }
334
Ethan Nicholas2983f402017-05-08 09:36:08 -0400335 fragBuilder->codeAppendf("%s = %s * alpha;", args.fOutputColor, args.fInputColor);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000336}
337
Brian Salomon94efbf52016-11-29 13:43:05 -0500338void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrShaderCaps&,
joshualittb0a8a372014-09-23 09:50:21 -0700339 GrProcessorKeyBuilder* b) {
joshualitt49586be2014-09-16 08:21:41 -0700340 const EllipseEffect& ee = effect.cast<EllipseEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700341 b->add32(ee.getEdgeType());
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000342}
343
egdaniel018fb622015-10-28 07:26:40 -0700344void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman,
Brian Salomonab015ef2017-04-04 10:15:51 -0400345 const GrFragmentProcessor& effect) {
joshualitt49586be2014-09-16 08:21:41 -0700346 const EllipseEffect& ee = effect.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000347 if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
bsalomone87256c42015-12-09 17:14:40 -0800348 float invRXSqd;
349 float invRYSqd;
350 // If we're using a scale factor to work around precision issues, choose the larger radius
351 // as the scale factor. The inv radii need to be pre-adjusted by the scale factor.
352 if (fScaleUniform.isValid()) {
353 if (ee.getRadii().fX > ee.getRadii().fY) {
354 invRXSqd = 1.f;
355 invRYSqd = (ee.getRadii().fX * ee.getRadii().fX) /
356 (ee.getRadii().fY * ee.getRadii().fY);
357 pdman.set2f(fScaleUniform, ee.getRadii().fX, 1.f / ee.getRadii().fX);
358 } else {
359 invRXSqd = (ee.getRadii().fY * ee.getRadii().fY) /
360 (ee.getRadii().fX * ee.getRadii().fX);
361 invRYSqd = 1.f;
362 pdman.set2f(fScaleUniform, ee.getRadii().fY, 1.f / ee.getRadii().fY);
363 }
364 } else {
365 invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
366 invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
367 }
kkinnunen7510b222014-07-30 00:04:16 -0700368 pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000369 fPrevCenter = ee.getCenter();
370 fPrevRadii = ee.getRadii();
371 }
372}
373
joshualitteb2a6762014-12-04 11:35:33 -0800374///////////////////////////////////////////////////////////////////////////////////////////////////
375
Brian Salomon94efbf52016-11-29 13:43:05 -0500376void EllipseEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800377 GrProcessorKeyBuilder* b) const {
joshualitteb2a6762014-12-04 11:35:33 -0800378 GLEllipseEffect::GenKey(*this, caps, b);
379}
380
egdaniel57d3b032015-11-13 11:57:27 -0800381GrGLSLFragmentProcessor* EllipseEffect::onCreateGLSLInstance() const {
robertphillips9cdb9922016-02-03 12:25:40 -0800382 return new GLEllipseEffect;
joshualitteb2a6762014-12-04 11:35:33 -0800383}
384
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000385//////////////////////////////////////////////////////////////////////////////
386
bungeman06ca8ec2016-06-09 08:01:03 -0700387sk_sp<GrFragmentProcessor> GrOvalEffect::Make(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
joshualittb0a8a372014-09-23 09:50:21 -0700388 if (kHairlineAA_GrProcessorEdgeType == edgeType) {
halcanary96fcdcc2015-08-27 07:41:13 -0700389 return nullptr;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000390 }
391 SkScalar w = oval.width();
392 SkScalar h = oval.height();
393 if (SkScalarNearlyEqual(w, h)) {
394 w /= 2;
bungeman06ca8ec2016-06-09 08:01:03 -0700395 return CircleEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000396 } else {
397 w /= 2;
398 h /= 2;
bungeman06ca8ec2016-06-09 08:01:03 -0700399 return EllipseEffect::Make(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000400 }
401
halcanary96fcdcc2015-08-27 07:41:13 -0700402 return nullptr;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000403}