16e1c099dd9f63818829348eaa9782932d0d4f4c
[platform/upstream/libSkiaSharp.git] / src / gpu / effects / GrOvalEffect.cpp
1 /*
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"
9
10 #include "GrFragmentProcessor.h"
11 #include "GrInvariantOutput.h"
12 #include "SkRect.h"
13 #include "glsl/GrGLSLFragmentProcessor.h"
14 #include "glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "glsl/GrGLSLProgramBuilder.h"
16 #include "glsl/GrGLSLProgramDataManager.h"
17
18 //////////////////////////////////////////////////////////////////////////////
19
20 class CircleEffect : public GrFragmentProcessor {
21 public:
22     static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
23
24     virtual ~CircleEffect() {};
25
26     const char* name() const override { return "Circle"; }
27
28     const SkPoint& getCenter() const { return fCenter; }
29     SkScalar getRadius() const { return fRadius; }
30
31     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
32
33 private:
34     CircleEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar radius);
35
36     GrGLSLFragmentProcessor* onCreateGLInstance() const override;
37
38     void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
39
40     bool onIsEqual(const GrFragmentProcessor&) const override;
41
42     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
43
44     SkPoint             fCenter;
45     SkScalar            fRadius;
46     GrPrimitiveEdgeType    fEdgeType;
47
48     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
49
50     typedef GrFragmentProcessor INHERITED;
51 };
52
53 GrFragmentProcessor* CircleEffect::Create(GrPrimitiveEdgeType edgeType, const SkPoint& center,
54                                           SkScalar radius) {
55     SkASSERT(radius >= 0);
56     return new CircleEffect(edgeType, center, radius);
57 }
58
59 void CircleEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
60     inout->mulByUnknownSingleComponent();
61 }
62
63 CircleEffect::CircleEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar r)
64     : fCenter(c)
65     , fRadius(r)
66     , fEdgeType(edgeType) {
67     this->initClassID<CircleEffect>();
68     this->setWillReadFragmentPosition();
69 }
70
71 bool CircleEffect::onIsEqual(const GrFragmentProcessor& other) const {
72     const CircleEffect& ce = other.cast<CircleEffect>();
73     return fEdgeType == ce.fEdgeType && fCenter == ce.fCenter && fRadius == ce.fRadius;
74 }
75
76 //////////////////////////////////////////////////////////////////////////////
77
78 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleEffect);
79
80 const GrFragmentProcessor* CircleEffect::TestCreate(GrProcessorTestData* d) {
81     SkPoint center;
82     center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
83     center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
84     SkScalar radius = d->fRandom->nextRangeF(0.f, 1000.f);
85     GrPrimitiveEdgeType et;
86     do {
87         et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
88     } while (kHairlineAA_GrProcessorEdgeType == et);
89     return CircleEffect::Create(et, center, radius);
90 }
91
92 //////////////////////////////////////////////////////////////////////////////
93
94 class GLCircleEffect : public GrGLSLFragmentProcessor {
95 public:
96     GLCircleEffect(const GrProcessor&);
97
98     virtual void emitCode(EmitArgs&) override;
99
100     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
101
102 protected:
103     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
104
105 private:
106     GrGLSLProgramDataManager::UniformHandle fCircleUniform;
107     SkPoint                                 fPrevCenter;
108     SkScalar                                fPrevRadius;
109
110     typedef GrGLSLFragmentProcessor INHERITED;
111 };
112
113 GLCircleEffect::GLCircleEffect(const GrProcessor&) {
114     fPrevRadius = -1.f;
115 }
116
117 void GLCircleEffect::emitCode(EmitArgs& args) {
118     const CircleEffect& ce = args.fFp.cast<CircleEffect>();
119     const char *circleName;
120     // The circle uniform is (center.x, center.y, radius + 0.5, 1 / (radius + 0.5)) for regular
121     // fills and (..., radius - 0.5, 1 / (radius - 0.5)) for inverse fills.
122     fCircleUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
123                                          kVec4f_GrSLType, kDefault_GrSLPrecision,
124                                          "circle",
125                                          &circleName);
126
127     GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
128     const char* fragmentPos = fsBuilder->fragmentPosition();
129
130     SkASSERT(kHairlineAA_GrProcessorEdgeType != ce.getEdgeType());
131     // TODO: Right now the distance to circle caclulation is performed in a space normalized to the
132     // radius and then denormalized. This is to prevent overflow on devices that have a "real"
133     // mediump. It'd be nice to only to this on mediump devices but we currently don't have the
134     // caps here.
135     if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
136         fsBuilder->codeAppendf("\t\tfloat d = (length((%s.xy - %s.xy) * %s.w) - 1.0) * %s.z;\n",
137                                 circleName, fragmentPos, circleName, circleName);
138     } else {
139         fsBuilder->codeAppendf("\t\tfloat d = (1.0 - length((%s.xy - %s.xy) *  %s.w)) * %s.z;\n",
140                                circleName, fragmentPos, circleName, circleName);
141     }
142     if (GrProcessorEdgeTypeIsAA(ce.getEdgeType())) {
143         fsBuilder->codeAppend("\t\td = clamp(d, 0.0, 1.0);\n");
144     } else {
145         fsBuilder->codeAppend("\t\td = d > 0.5 ? 1.0 : 0.0;\n");
146     }
147
148     fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
149                            (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("d")).c_str());
150 }
151
152 void GLCircleEffect::GenKey(const GrProcessor& processor, const GrGLSLCaps&,
153                             GrProcessorKeyBuilder* b) {
154     const CircleEffect& ce = processor.cast<CircleEffect>();
155     b->add32(ce.getEdgeType());
156 }
157
158 void GLCircleEffect::onSetData(const GrGLSLProgramDataManager& pdman,
159                                const GrProcessor& processor) {
160     const CircleEffect& ce = processor.cast<CircleEffect>();
161     if (ce.getRadius() != fPrevRadius || ce.getCenter() != fPrevCenter) {
162         SkScalar radius = ce.getRadius();
163         if (GrProcessorEdgeTypeIsInverseFill(ce.getEdgeType())) {
164             radius -= 0.5f;
165         } else {
166             radius += 0.5f;
167         }
168         pdman.set4f(fCircleUniform, ce.getCenter().fX, ce.getCenter().fY, radius,
169                     SkScalarInvert(radius));
170         fPrevCenter = ce.getCenter();
171         fPrevRadius = ce.getRadius();
172     }
173 }
174
175 ///////////////////////////////////////////////////////////////////////////////////////////////////
176
177 void CircleEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
178                                      GrProcessorKeyBuilder* b) const {
179     GLCircleEffect::GenKey(*this, caps, b);
180 }
181
182 GrGLSLFragmentProcessor* CircleEffect::onCreateGLInstance() const  {
183     return new GLCircleEffect(*this);
184 }
185
186 //////////////////////////////////////////////////////////////////////////////
187
188 class EllipseEffect : public GrFragmentProcessor {
189 public:
190     static GrFragmentProcessor* Create(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx,
191                                        SkScalar ry);
192
193     virtual ~EllipseEffect() {};
194
195     const char* name() const override { return "Ellipse"; }
196
197     const SkPoint& getCenter() const { return fCenter; }
198     SkVector getRadii() const { return fRadii; }
199
200     GrPrimitiveEdgeType getEdgeType() const { return fEdgeType; }
201
202 private:
203     EllipseEffect(GrPrimitiveEdgeType, const SkPoint& center, SkScalar rx, SkScalar ry);
204
205     GrGLSLFragmentProcessor* onCreateGLInstance() const override;
206
207     void onGetGLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
208
209     bool onIsEqual(const GrFragmentProcessor&) const override;
210
211     void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
212
213     SkPoint             fCenter;
214     SkVector            fRadii;
215     GrPrimitiveEdgeType    fEdgeType;
216
217     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
218
219     typedef GrFragmentProcessor INHERITED;
220 };
221
222 GrFragmentProcessor* EllipseEffect::Create(GrPrimitiveEdgeType edgeType,
223                                            const SkPoint& center,
224                                            SkScalar rx,
225                                            SkScalar ry) {
226     SkASSERT(rx >= 0 && ry >= 0);
227     return new EllipseEffect(edgeType, center, rx, ry);
228 }
229
230 void EllipseEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
231     inout->mulByUnknownSingleComponent();
232 }
233
234 EllipseEffect::EllipseEffect(GrPrimitiveEdgeType edgeType, const SkPoint& c, SkScalar rx, SkScalar ry)
235     : fCenter(c)
236     , fRadii(SkVector::Make(rx, ry))
237     , fEdgeType(edgeType) {
238     this->initClassID<EllipseEffect>();
239     this->setWillReadFragmentPosition();
240 }
241
242 bool EllipseEffect::onIsEqual(const GrFragmentProcessor& other) const {
243     const EllipseEffect& ee = other.cast<EllipseEffect>();
244     return fEdgeType == ee.fEdgeType && fCenter == ee.fCenter && fRadii == ee.fRadii;
245 }
246
247 //////////////////////////////////////////////////////////////////////////////
248
249 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(EllipseEffect);
250
251 const GrFragmentProcessor* EllipseEffect::TestCreate(GrProcessorTestData* d) {
252     SkPoint center;
253     center.fX = d->fRandom->nextRangeScalar(0.f, 1000.f);
254     center.fY = d->fRandom->nextRangeScalar(0.f, 1000.f);
255     SkScalar rx = d->fRandom->nextRangeF(0.f, 1000.f);
256     SkScalar ry = d->fRandom->nextRangeF(0.f, 1000.f);
257     GrPrimitiveEdgeType et;
258     do {
259         et = (GrPrimitiveEdgeType)d->fRandom->nextULessThan(kGrProcessorEdgeTypeCnt);
260     } while (kHairlineAA_GrProcessorEdgeType == et);
261     return EllipseEffect::Create(et, center, rx, ry);
262 }
263
264 //////////////////////////////////////////////////////////////////////////////
265
266 class GLEllipseEffect : public GrGLSLFragmentProcessor {
267 public:
268     GLEllipseEffect(const GrProcessor&);
269
270     virtual void emitCode(EmitArgs&) override;
271
272     static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
273
274 protected:
275     void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
276
277 private:
278     GrGLSLProgramDataManager::UniformHandle fEllipseUniform;
279     SkPoint                                 fPrevCenter;
280     SkVector                                fPrevRadii;
281
282     typedef GrGLSLFragmentProcessor INHERITED;
283 };
284
285 GLEllipseEffect::GLEllipseEffect(const GrProcessor& effect) {
286     fPrevRadii.fX = -1.f;
287 }
288
289 void GLEllipseEffect::emitCode(EmitArgs& args) {
290     const EllipseEffect& ee = args.fFp.cast<EllipseEffect>();
291     const char *ellipseName;
292     // The ellipse uniform is (center.x, center.y, 1 / rx^2, 1 / ry^2)
293     // The last two terms can underflow on mediump, so we use highp.
294     fEllipseUniform = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
295                                          kVec4f_GrSLType, kHigh_GrSLPrecision,
296                                          "ellipse",
297                                          &ellipseName);
298
299     GrGLSLFragmentBuilder* fsBuilder = args.fBuilder->getFragmentShaderBuilder();
300     const char* fragmentPos = fsBuilder->fragmentPosition();
301
302     // d is the offset to the ellipse center
303     fsBuilder->codeAppendf("\t\tvec2 d = %s.xy - %s.xy;\n", fragmentPos, ellipseName);
304     fsBuilder->codeAppendf("\t\tvec2 Z = d * %s.zw;\n", ellipseName);
305     // implicit is the evaluation of (x/rx)^2 + (y/ry)^2 - 1.
306     fsBuilder->codeAppend("\t\tfloat implicit = dot(Z, d) - 1.0;\n");
307     // grad_dot is the squared length of the gradient of the implicit.
308     fsBuilder->codeAppendf("\t\tfloat grad_dot = 4.0 * dot(Z, Z);\n");
309     // avoid calling inversesqrt on zero.
310     fsBuilder->codeAppend("\t\tgrad_dot = max(grad_dot, 1.0e-4);\n");
311     fsBuilder->codeAppendf("\t\tfloat approx_dist = implicit * inversesqrt(grad_dot);\n");
312
313     switch (ee.getEdgeType()) {
314         case kFillAA_GrProcessorEdgeType:
315             fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 - approx_dist, 0.0, 1.0);\n");
316             break;
317         case kInverseFillAA_GrProcessorEdgeType:
318             fsBuilder->codeAppend("\t\tfloat alpha = clamp(0.5 + approx_dist, 0.0, 1.0);\n");
319             break;
320         case kFillBW_GrProcessorEdgeType:
321             fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 0.0 : 1.0;\n");
322             break;
323         case kInverseFillBW_GrProcessorEdgeType:
324             fsBuilder->codeAppend("\t\tfloat alpha = approx_dist > 0.0 ? 1.0 : 0.0;\n");
325             break;
326         case kHairlineAA_GrProcessorEdgeType:
327             SkFAIL("Hairline not expected here.");
328     }
329
330     fsBuilder->codeAppendf("\t\t%s = %s;\n", args.fOutputColor,
331                            (GrGLSLExpr4(args.fInputColor) * GrGLSLExpr1("alpha")).c_str());
332 }
333
334 void GLEllipseEffect::GenKey(const GrProcessor& effect, const GrGLSLCaps&,
335                              GrProcessorKeyBuilder* b) {
336     const EllipseEffect& ee = effect.cast<EllipseEffect>();
337     b->add32(ee.getEdgeType());
338 }
339
340 void GLEllipseEffect::onSetData(const GrGLSLProgramDataManager& pdman,
341                                 const GrProcessor& effect) {
342     const EllipseEffect& ee = effect.cast<EllipseEffect>();
343     if (ee.getRadii() != fPrevRadii || ee.getCenter() != fPrevCenter) {
344         SkScalar invRXSqd = 1.f / (ee.getRadii().fX * ee.getRadii().fX);
345         SkScalar invRYSqd = 1.f / (ee.getRadii().fY * ee.getRadii().fY);
346         pdman.set4f(fEllipseUniform, ee.getCenter().fX, ee.getCenter().fY, invRXSqd, invRYSqd);
347         fPrevCenter = ee.getCenter();
348         fPrevRadii = ee.getRadii();
349     }
350 }
351
352 ///////////////////////////////////////////////////////////////////////////////////////////////////
353
354 void EllipseEffect::onGetGLProcessorKey(const GrGLSLCaps& caps,
355                                      GrProcessorKeyBuilder* b) const {
356     GLEllipseEffect::GenKey(*this, caps, b);
357 }
358
359 GrGLSLFragmentProcessor* EllipseEffect::onCreateGLInstance() const  {
360     return new GLEllipseEffect(*this);
361 }
362
363 //////////////////////////////////////////////////////////////////////////////
364
365 GrFragmentProcessor* GrOvalEffect::Create(GrPrimitiveEdgeType edgeType, const SkRect& oval) {
366     if (kHairlineAA_GrProcessorEdgeType == edgeType) {
367         return nullptr;
368     }
369     SkScalar w = oval.width();
370     SkScalar h = oval.height();
371     if (SkScalarNearlyEqual(w, h)) {
372         w /= 2;
373         return CircleEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + w), w);
374     } else {
375         w /= 2;
376         h /= 2;
377         return EllipseEffect::Create(edgeType, SkPoint::Make(oval.fLeft + w, oval.fTop + h), w, h);
378     }
379
380     return nullptr;
381 }