blob: 314b000819372cd4c20e33487e6a2bd8743fc08e [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"
egdaniel605dd0f2014-11-12 08:35:25 -080011#include "GrInvariantOutput.h"
joshualitteb2a6762014-12-04 11:35:33 -080012#include "SkRect.h"
joshualittb0a8a372014-09-23 09:50:21 -070013#include "gl/GrGLProcessor.h"
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000014#include "gl/GrGLSL.h"
joshualitteb2a6762014-12-04 11:35:33 -080015#include "gl/builders/GrGLProgramBuilder.h"
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000016
17//////////////////////////////////////////////////////////////////////////////
18
joshualittb0a8a372014-09-23 09:50:21 -070019class CircleEffect : public GrFragmentProcessor {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000020public:
joshualittb0a8a372014-09-23 09:50:21 -070021 static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000022
23 virtual ~CircleEffect() {};
joshualitteb2a6762014-12-04 11:35:33 -080024
mtklein72c9faa2015-01-09 10:06:39 -080025 const char* name() const SK_OVERRIDE { return "Circle"; }
joshualitteb2a6762014-12-04 11:35:33 -080026
mtklein72c9faa2015-01-09 10:06:39 -080027 void getGLProcessorKey(const GrGLCaps&, GrProcessorKeyBuilder*) const SK_OVERRIDE;
joshualitteb2a6762014-12-04 11:35:33 -080028
mtklein72c9faa2015-01-09 10:06:39 -080029 GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000030
31 const SkPoint& getCenter() const { return fCenter; }
32 SkScalar getRadius() const { return fRadius; }
33
joshualittb0a8a372014-09-23 09:50:21 -070034 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000035
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000036private:
joshualittb0a8a372014-09-23 09:50:21 -070037 CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000038
mtklein72c9faa2015-01-09 10:06:39 -080039 bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000040
mtklein72c9faa2015-01-09 10:06:39 -080041 void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
egdaniel1a8ecdf2014-10-03 06:24:12 -070042
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000043 SkPoint fCenter;
44 SkScalar fRadius;
joshualittb0a8a372014-09-23 09:50:21 -070045 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000046
joshualittb0a8a372014-09-23 09:50:21 -070047 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000048
joshualittb0a8a372014-09-23 09:50:21 -070049 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000050};
51
joshualittb0a8a372014-09-23 09:50:21 -070052GrFragmentProcessor* CircleEffect::Create(GrPrimitiveEdgeType edgeType, const SkPoint& center,
53 SkScalar radius) {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000054 SkASSERT(radius >= 0);
bsalomon55fad7a2014-07-08 07:34:20 -070055 return SkNEW_ARGS(CircleEffect, (edgeType, center, radius));
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000056}
57
egdaniel605dd0f2014-11-12 08:35:25 -080058void CircleEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
joshualitt56995b52014-12-11 15:44:02 -080059 inout->mulByUnknownSingleComponent();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000060}
61
joshualittb0a8a372014-09-23 09:50:21 -070062CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000063 : fCenter(c)
64 , fRadius(r)
65 , fEdgeType(edgeType) {
joshualitteb2a6762014-12-04 11:35:33 -080066 this->initClassID<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000067 this->setWillReadFragmentPosition();
68}
69
bsalomon0e08fc12014-10-15 08:19:04 -070070bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -070071 const CircleEffect& ce = other.cast<CircleEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +000072 return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000073}
74
75//////////////////////////////////////////////////////////////////////////////
76
joshualittb0a8a372014-09-23 09:50:21 -070077GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleEffect);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000078
joshualittb0a8a372014-09-23 09:50:21 -070079GrFragmentProcessor* CircleEffect::TestCreate(SkRandom* random,
80 GrContext*,
81 const GrDrawTargetCaps& caps,
82 GrTexture*[]) {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000083 SkPoint center;
84 center.fX = random->nextRangeScalar(0.f, 1000.f);
85 center.fY = random->nextRangeScalar(0.f, 1000.f);
86 SkScalar radius = random->nextRangeF(0.f, 1000.f);
joshualittb0a8a372014-09-23 09:50:21 -070087 GrPrimitiveEdgeType et;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000088 do {
joshualittb0a8a372014-09-23 09:50:21 -070089 et = (GrPrimitiveEdgeType)random->nextULessThan(kGrProcessorEdgeTypeCnt);
90 } while (kHairlineAA_GrProcessorEdgeType == et);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000091 return CircleEffect::Create(et, center, radius);
92}
93
94//////////////////////////////////////////////////////////////////////////////
95
joshualittb0a8a372014-09-23 09:50:21 -070096class GLCircleEffect : public GrGLFragmentProcessor {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000097public:
joshualitteb2a6762014-12-04 11:35:33 -080098 GLCircleEffect(const GrProcessor&);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +000099
joshualitt15988992014-10-09 15:04:05 -0700100 virtual void emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700101 const GrFragmentProcessor& fp,
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000102 const char* outputColor,
103 const char* inputColor,
104 const TransformedCoordsArray&,
105 const TextureSamplerArray&) SK_OVERRIDE;
106
joshualittb0a8a372014-09-23 09:50:21 -0700107 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000108
mtklein72c9faa2015-01-09 10:06:39 -0800109 void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000110
111private:
kkinnunen7510b222014-07-30 00:04:16 -0700112 GrGLProgramDataManager::UniformHandle fCircleUniform;
113 SkPoint fPrevCenter;
114 SkScalar fPrevRadius;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000115
joshualittb0a8a372014-09-23 09:50:21 -0700116 typedef GrGLFragmentProcessor INHERITED;
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000117};
118
joshualitteb2a6762014-12-04 11:35:33 -0800119GLCircleEffect::GLCircleEffect(const GrProcessor&) {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000120 fPrevRadius = -1.f;
121}
122
joshualitt15988992014-10-09 15:04:05 -0700123void GLCircleEffect::emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700124 const GrFragmentProcessor& fp,
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000125 const char* outputColor,
126 const char* inputColor,
127 const TransformedCoordsArray&,
128 const TextureSamplerArray& samplers) {
joshualittb0a8a372014-09-23 09:50:21 -0700129 const CircleEffect& ce = fp.cast<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000130 const char *circleName;
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000131 // The circle uniform is (center.x, center.y, radius + 0.5) for regular fills and
132 // (... ,radius - 0.5) for inverse fills.
joshualitt30ba4362014-08-21 20:18:45 -0700133 fCircleUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800134 kVec3f_GrSLType, kDefault_GrSLPrecision,
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000135 "circle",
136 &circleName);
joshualitt30ba4362014-08-21 20:18:45 -0700137
joshualitt15988992014-10-09 15:04:05 -0700138 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
joshualitt30ba4362014-08-21 20:18:45 -0700139 const char* fragmentPos = fsBuilder->fragmentPosition();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000140
joshualittb0a8a372014-09-23 09:50:21 -0700141 SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
142 if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
joshualitt30ba4362014-08-21 20:18:45 -0700143 fsBuilder->codeAppendf("\t\tfloat d = length(%s.xy - %s.xy) - %s.z;\n",
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000144 circleName, fragmentPos, circleName);
145 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700146 fsBuilder->codeAppendf("\t\tfloat d = %s.z - length(%s.xy - %s.xy);\n",
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000147 circleName, fragmentPos, circleName);
148 }
joshualittb0a8a372014-09-23 09:50:21 -0700149 if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
joshualitt30ba4362014-08-21 20:18:45 -0700150 fsBuilder->codeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000151 } else {
joshualitt30ba4362014-08-21 20:18:45 -0700152 fsBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000153 }
154
joshualitt30ba4362014-08-21 20:18:45 -0700155 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000156 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("d")).c_str());
157}
158
joshualittb0a8a372014-09-23 09:50:21 -0700159void GLCircleEffect::GenKey(const GrProcessor& processor, const GrGLCaps&,
160 GrProcessorKeyBuilder* b) {
161 const CircleEffect& ce = processor.cast<CircleEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700162 b->add32(ce.getEdgeType());
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000163}
164
joshualittb0a8a372014-09-23 09:50:21 -0700165void GLCircleEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& processor) {
166 const CircleEffect& ce = processor.cast<CircleEffect>();
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000167 if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000168 SkScalar radius = ce.getRadius();
joshualittb0a8a372014-09-23 09:50:21 -0700169 if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
commit-bot@chromium.org0a09d712014-04-09 21:26:11 +0000170 radius -= 0.5f;
171 } else {
172 radius += 0.5f;
173 }
kkinnunen7510b222014-07-30 00:04:16 -0700174 pdman.set3f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000175 fPrevCenter = ce.getCenter();
176 fPrevRadius = ce.getRadius();
177 }
178}
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000179
joshualitteb2a6762014-12-04 11:35:33 -0800180///////////////////////////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000181
joshualitteb2a6762014-12-04 11:35:33 -0800182void CircleEffect::getGLProcessorKey(const GrGLCaps& caps,
183 GrProcessorKeyBuilder* b) const {
184 GLCircleEffect::GenKey(*this, caps, b);
185}
186
187GrGLFragmentProcessor* CircleEffect::createGLInstance() const {
188 return SkNEW_ARGS(GLCircleEffect, (*this));
189}
190
191//////////////////////////////////////////////////////////////////////////////
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000192
joshualittb0a8a372014-09-23 09:50:21 -0700193class EllipseEffect : public GrFragmentProcessor {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000194public:
joshualittb0a8a372014-09-23 09:50:21 -0700195 static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx,
196 SkScalar ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000197
198 virtual ~EllipseEffect() {};
joshualitteb2a6762014-12-04 11:35:33 -0800199
mtklein72c9faa2015-01-09 10:06:39 -0800200 const char* name() const SK_OVERRIDE { return "Ellipse"; }
joshualitteb2a6762014-12-04 11:35:33 -0800201
mtklein72c9faa2015-01-09 10:06:39 -0800202 void getGLProcessorKey(const GrGLCaps&, GrProcessorKeyBuilder*) const SK_OVERRIDE;
joshualitteb2a6762014-12-04 11:35:33 -0800203
mtklein72c9faa2015-01-09 10:06:39 -0800204 GrGLFragmentProcessor* createGLInstance() const SK_OVERRIDE;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000205
206 const SkPoint& getCenter() const { return fCenter; }
207 SkVector getRadii() const { return fRadii; }
208
joshualittb0a8a372014-09-23 09:50:21 -0700209 GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000210
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000211private:
joshualittb0a8a372014-09-23 09:50:21 -0700212 EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000213
mtklein72c9faa2015-01-09 10:06:39 -0800214 bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000215
mtklein72c9faa2015-01-09 10:06:39 -0800216 void onComputeInvariantOutput(GrInvariantOutput* inout) const SK_OVERRIDE;
egdaniel1a8ecdf2014-10-03 06:24:12 -0700217
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000218 SkPoint fCenter;
219 SkVector fRadii;
joshualittb0a8a372014-09-23 09:50:21 -0700220 GrPrimitiveEdgeType fEdgeType;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000221
joshualittb0a8a372014-09-23 09:50:21 -0700222 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000223
joshualittb0a8a372014-09-23 09:50:21 -0700224 typedef GrFragmentProcessor INHERITED;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000225};
226
joshualittb0a8a372014-09-23 09:50:21 -0700227GrFragmentProcessor* EllipseEffect::Create(GrPrimitiveEdgeType edgeType,
228 const SkPoint& center,
229 SkScalar rx,
230 SkScalar ry) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000231 SkASSERT(rx >= 0 && ry >= 0);
bsalomon55fad7a2014-07-08 07:34:20 -0700232 return SkNEW_ARGS(EllipseEffect, (edgeType, center, rx, ry));
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000233}
234
egdaniel605dd0f2014-11-12 08:35:25 -0800235void EllipseEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
joshualitt56995b52014-12-11 15:44:02 -0800236 inout->mulByUnknownSingleComponent();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000237}
238
joshualittb0a8a372014-09-23 09:50:21 -0700239EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx, SkScalar ry)
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000240 : fCenter(c)
241 , fRadii(SkVector::Make(rx, ry))
242 , fEdgeType(edgeType) {
joshualitteb2a6762014-12-04 11:35:33 -0800243 this->initClassID<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000244 this->setWillReadFragmentPosition();
245}
246
bsalomon0e08fc12014-10-15 08:19:04 -0700247bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
joshualitt49586be2014-09-16 08:21:41 -0700248 const EllipseEffect& ee = other.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000249 return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
250}
251
252//////////////////////////////////////////////////////////////////////////////
253
joshualittb0a8a372014-09-23 09:50:21 -0700254GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000255
joshualittb0a8a372014-09-23 09:50:21 -0700256GrFragmentProcessor* EllipseEffect::TestCreate(SkRandom* random,
257 GrContext*,
258 const GrDrawTargetCaps& caps,
259 GrTexture*[]) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000260 SkPoint center;
261 center.fX = random->nextRangeScalar(0.f, 1000.f);
262 center.fY = random->nextRangeScalar(0.f, 1000.f);
263 SkScalar rx = random->nextRangeF(0.f, 1000.f);
264 SkScalar ry = random->nextRangeF(0.f, 1000.f);
joshualittb0a8a372014-09-23 09:50:21 -0700265 GrPrimitiveEdgeType et;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000266 do {
joshualittb0a8a372014-09-23 09:50:21 -0700267 et = (GrPrimitiveEdgeType)random->nextULessThan(kGrProcessorEdgeTypeCnt);
268 } while (kHairlineAA_GrProcessorEdgeType == et);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000269 return EllipseEffect::Create(et, center, rx, ry);
270}
271
272//////////////////////////////////////////////////////////////////////////////
273
joshualittb0a8a372014-09-23 09:50:21 -0700274class GLEllipseEffect : public GrGLFragmentProcessor {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000275public:
joshualitteb2a6762014-12-04 11:35:33 -0800276 GLEllipseEffect(const GrProcessor&);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000277
joshualitt15988992014-10-09 15:04:05 -0700278 virtual void emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700279 const GrFragmentProcessor& fp,
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000280 const char* outputColor,
281 const char* inputColor,
282 const TransformedCoordsArray&,
283 const TextureSamplerArray&) SK_OVERRIDE;
284
joshualittb0a8a372014-09-23 09:50:21 -0700285 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000286
mtklein72c9faa2015-01-09 10:06:39 -0800287 void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000288
289private:
kkinnunen7510b222014-07-30 00:04:16 -0700290 GrGLProgramDataManager::UniformHandle fEllipseUniform;
291 SkPoint fPrevCenter;
292 SkVector fPrevRadii;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000293
joshualittb0a8a372014-09-23 09:50:21 -0700294 typedef GrGLFragmentProcessor INHERITED;
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000295};
296
joshualitteb2a6762014-12-04 11:35:33 -0800297GLEllipseEffect::GLEllipseEffect(const GrProcessor& effect) {
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000298 fPrevRadii.fX = -1.f;
299}
300
joshualitt15988992014-10-09 15:04:05 -0700301void GLEllipseEffect::emitCode(GrGLFPBuilder* builder,
joshualittb0a8a372014-09-23 09:50:21 -0700302 const GrFragmentProcessor& fp,
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000303 const char* outputColor,
304 const char* inputColor,
305 const TransformedCoordsArray&,
306 const TextureSamplerArray& samplers) {
joshualittb0a8a372014-09-23 09:50:21 -0700307 const EllipseEffect& ee = fp.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000308 const char *ellipseName;
309 // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
joshualitt30ba4362014-08-21 20:18:45 -0700310 fEllipseUniform = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
bsalomon422f56f2014-12-09 10:18:12 -0800311 kVec4f_GrSLType, kDefault_GrSLPrecision,
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000312 "ellipse",
313 &ellipseName);
joshualitt30ba4362014-08-21 20:18:45 -0700314
joshualitt15988992014-10-09 15:04:05 -0700315 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
joshualitt30ba4362014-08-21 20:18:45 -0700316 const char* fragmentPos = fsBuilder->fragmentPosition();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000317
318 // d is the offset to the ellipse center
joshualitt30ba4362014-08-21 20:18:45 -0700319 fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
320 fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000321 // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
joshualitt30ba4362014-08-21 20:18:45 -0700322 fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000323 // grad_dot is the squared length of the gradient of the implicit.
joshualitt30ba4362014-08-21 20:18:45 -0700324 fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
commit-bot@chromium.org1b035d82014-04-09 17:11:09 +0000325 // avoid calling inversesqrt on zero.
joshualitt30ba4362014-08-21 20:18:45 -0700326 fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
327 fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000328
329 switch (ee.getEdgeType()) {
joshualittb0a8a372014-09-23 09:50:21 -0700330 case kFillAA_GrProcessorEdgeType:
joshualitt30ba4362014-08-21 20:18:45 -0700331 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000332 break;
joshualittb0a8a372014-09-23 09:50:21 -0700333 case kInverseFillAA_GrProcessorEdgeType:
joshualitt30ba4362014-08-21 20:18:45 -0700334 fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000335 break;
joshualittb0a8a372014-09-23 09:50:21 -0700336 case kFillBW_GrProcessorEdgeType:
joshualitt30ba4362014-08-21 20:18:45 -0700337 fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000338 break;
joshualittb0a8a372014-09-23 09:50:21 -0700339 case kInverseFillBW_GrProcessorEdgeType:
joshualitt30ba4362014-08-21 20:18:45 -0700340 fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000341 break;
joshualittb0a8a372014-09-23 09:50:21 -0700342 case kHairlineAA_GrProcessorEdgeType:
commit-bot@chromium.org88cb22b2014-04-30 14:17:00 +0000343 SkFAIL("Hairline not expected here.");
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000344 }
345
joshualitt30ba4362014-08-21 20:18:45 -0700346 fsBuilder->codeAppendf("\t\t%s = %s;\n", outputColor,
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000347 (GrGLSLExpr4(inputColor) * GrGLSLExpr1("alpha")).c_str());
348}
349
joshualittb0a8a372014-09-23 09:50:21 -0700350void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrGLCaps&,
351 GrProcessorKeyBuilder* b) {
joshualitt49586be2014-09-16 08:21:41 -0700352 const EllipseEffect& ee = effect.cast<EllipseEffect>();
bsalomon63e99f72014-07-21 08:03:14 -0700353 b->add32(ee.getEdgeType());
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000354}
355
joshualittb0a8a372014-09-23 09:50:21 -0700356void GLEllipseEffect::setData(const GrGLProgramDataManager& pdman, const GrProcessor& effect) {
joshualitt49586be2014-09-16 08:21:41 -0700357 const EllipseEffect& ee = effect.cast<EllipseEffect>();
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000358 if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
359 SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
360 SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
kkinnunen7510b222014-07-30 00:04:16 -0700361 pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000362 fPrevCenter = ee.getCenter();
363 fPrevRadii = ee.getRadii();
364 }
365}
366
joshualitteb2a6762014-12-04 11:35:33 -0800367///////////////////////////////////////////////////////////////////////////////////////////////////
368
369void EllipseEffect::getGLProcessorKey(const GrGLCaps& caps,
370 GrProcessorKeyBuilder* b) const {
371 GLEllipseEffect::GenKey(*this, caps, b);
372}
373
374GrGLFragmentProcessor* EllipseEffect::createGLInstance() const {
375 return SkNEW_ARGS(GLEllipseEffect, (*this));
376}
377
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000378//////////////////////////////////////////////////////////////////////////////
379
joshualittb0a8a372014-09-23 09:50:21 -0700380GrFragmentProcessor* GrOvalEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
381 if (kHairlineAA_GrProcessorEdgeType == edgeType) {
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000382 return NULL;
383 }
384 SkScalar w = oval.width();
385 SkScalar h = oval.height();
386 if (SkScalarNearlyEqual(w, h)) {
387 w /= 2;
388 return CircleEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
commit-bot@chromium.orgd0a50292014-04-02 15:00:39 +0000389 } else {
390 w /= 2;
391 h /= 2;
392 return EllipseEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
commit-bot@chromium.org3eedb802014-03-28 15:58:31 +0000393 }
394
395 return NULL;
396}