blob: caada921597cb3bcb0df8b29e698384db8eb33ee [file] [log] [blame]
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +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 */
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00007
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00008
9#include "SkTwoPointConicalGradient.h"
10
commit-bot@chromium.orgef93d292014-04-10 15:37:52 +000011#if SK_SUPPORT_GPU
egdaniel7ea439b2015-12-03 09:20:44 -080012#include "GrCoordTransform.h"
joshualitt8ca93e72015-07-08 06:51:43 -070013#include "GrPaint.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"
brianosman9557c272016-09-15 06:59:15 -070017#include "SkTwoPointConicalGradient_gpu.h"
18
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000019// For brevity
egdaniel018fb622015-10-28 07:26:40 -070020typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000021
commit-bot@chromium.org80894672014-04-22 21:24:22 +000022static const SkScalar kErrorTol = 0.00001f;
egdaniel8405ef92014-06-09 11:57:28 -070023static const SkScalar kEdgeErrorTol = 5.f * kErrorTol;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000024
25/**
26 * We have three general cases for 2pt conical gradients. First we always assume that
27 * the start radius <= end radius. Our first case (kInside_) is when the start circle
28 * is completely enclosed by the end circle. The second case (kOutside_) is the case
29 * when the start circle is either completely outside the end circle or the circles
30 * overlap. The final case (kEdge_) is when the start circle is inside the end one,
31 * but the two are just barely touching at 1 point along their edges.
32 */
33enum ConicalType {
34 kInside_ConicalType,
35 kOutside_ConicalType,
36 kEdge_ConicalType,
37};
38
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000039//////////////////////////////////////////////////////////////////////////////
40
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000041static void set_matrix_edge_conical(const SkTwoPointConicalGradient& shader,
42 SkMatrix* invLMatrix) {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000043 // Inverse of the current local matrix is passed in then,
44 // translate to center1, rotate so center2 is on x axis.
45 const SkPoint& center1 = shader.getStartCenter();
46 const SkPoint& center2 = shader.getEndCenter();
47
48 invLMatrix->postTranslate(-center1.fX, -center1.fY);
49
50 SkPoint diff = center2 - center1;
51 SkScalar diffLen = diff.length();
52 if (0 != diffLen) {
53 SkScalar invDiffLen = SkScalarInvert(diffLen);
54 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -050055 rot.setSinCos(-invDiffLen * diff.fY, invDiffLen * diff.fX);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000056 invLMatrix->postConcat(rot);
57 }
58}
59
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000060class Edge2PtConicalEffect : public GrGradientEffect {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000061public:
fmenozzi55d318d2016-08-09 08:05:57 -070062 class GLSLEdge2PtConicalProcessor;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000063
Brian Salomonaff329b2017-08-11 09:40:37 -040064 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args) {
65 auto processor = std::unique_ptr<Edge2PtConicalEffect>(new Edge2PtConicalEffect(args));
Brian Salomon6af27012017-06-09 08:21:42 -040066 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000067 }
68
mtklein36352bf2015-03-25 18:17:31 -070069 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -080070 return "Two-Point Conical Gradient Edge Touching";
71 }
72
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000073 // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000074 SkScalar center() const { return fCenterX1; }
75 SkScalar diffRadius() const { return fDiffRadius; }
76 SkScalar radius() const { return fRadius0; }
77
Brian Salomonaff329b2017-08-11 09:40:37 -040078 std::unique_ptr<GrFragmentProcessor> clone() const override {
79 return std::unique_ptr<GrFragmentProcessor>(new Edge2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -040080 }
81
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000082private:
egdaniel57d3b032015-11-13 11:57:27 -080083 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070084
Brian Salomon94efbf52016-11-29 13:43:05 -050085 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070086
mtklein36352bf2015-03-25 18:17:31 -070087 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -070088 const Edge2PtConicalEffect& s = sBase.cast<Edge2PtConicalEffect>();
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000089 return (INHERITED::onIsEqual(sBase) &&
90 this->fCenterX1 == s.fCenterX1 &&
91 this->fRadius0 == s.fRadius0 &&
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000092 this->fDiffRadius == s.fDiffRadius);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000093 }
94
Brian Salomonf8480b92017-07-27 15:45:59 -040095 explicit Edge2PtConicalEffect(const CreateArgs& args)
Brian Salomon587e08f2017-01-27 10:59:27 -050096 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */) {
brianosman9557c272016-09-15 06:59:15 -070097 const SkTwoPointConicalGradient& shader =
98 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
99 fCenterX1 = shader.getCenterX1();
100 fRadius0 = shader.getStartRadius();
101 fDiffRadius = shader.getDiffRadius();
joshualitteb2a6762014-12-04 11:35:33 -0800102 this->initClassID<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000103 // We should only be calling this shader if we are degenerate case with touching circles
egdaniel8405ef92014-06-09 11:57:28 -0700104 // When deciding if we are in edge case, we scaled by the end radius for cases when the
joshualitt01258472014-09-22 10:29:30 -0700105 // start radius was close to zero, otherwise we scaled by the start radius. In addition
106 // Our test for the edge case in set_matrix_circle_conical has a higher tolerance so we
107 // need the sqrt value below
108 SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - fCenterX1) <
109 (fRadius0 < kErrorTol ? shader.getEndRadius() * kEdgeErrorTol :
110 fRadius0 * sqrt(kEdgeErrorTol)));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000111
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000112 // We pass the linear part of the quadratic as a varying.
113 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
114 fBTransform = this->getCoordTransform();
115 SkMatrix& bMatrix = *fBTransform.accessMatrix();
Mike Reed8be952a2017-02-13 20:44:33 -0500116 SkScalar r0dr = fRadius0 * fDiffRadius;
117 bMatrix[SkMatrix::kMScaleX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMScaleX] +
118 r0dr * bMatrix[SkMatrix::kMPersp0]);
119 bMatrix[SkMatrix::kMSkewX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMSkewX] +
120 r0dr * bMatrix[SkMatrix::kMPersp1]);
121 bMatrix[SkMatrix::kMTransX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMTransX] +
122 r0dr * bMatrix[SkMatrix::kMPersp2]);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000123 this->addCoordTransform(&fBTransform);
124 }
125
Brian Salomonf8480b92017-07-27 15:45:59 -0400126 explicit Edge2PtConicalEffect(const Edge2PtConicalEffect& that)
127 : INHERITED(that)
128 , fBTransform(that.fBTransform)
129 , fCenterX1(that.fCenterX1)
130 , fRadius0(that.fRadius0)
131 , fDiffRadius(that.fDiffRadius) {
132 this->initClassID<Edge2PtConicalEffect>();
133 this->addCoordTransform(&fBTransform);
134 }
135
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400136 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000137
138 // @{
139 // Cache of values - these can change arbitrarily, EXCEPT
140 // we shouldn't change between degenerate and non-degenerate?!
141
142 GrCoordTransform fBTransform;
143 SkScalar fCenterX1;
144 SkScalar fRadius0;
145 SkScalar fDiffRadius;
146
147 // @}
148
149 typedef GrGradientEffect INHERITED;
150};
151
fmenozzi55d318d2016-08-09 08:05:57 -0700152class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000153public:
fmenozzi55d318d2016-08-09 08:05:57 -0700154 GLSLEdge2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000155
wangyix7c157a92015-07-22 15:08:53 -0700156 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000157
Brian Salomon94efbf52016-11-29 13:43:05 -0500158 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000159
160protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400161 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700162
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000163 UniformHandle fParamUni;
164
165 const char* fVSVaryingName;
166 const char* fFSVaryingName;
167
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000168 // @{
169 /// Values last uploaded as uniforms
170
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000171 SkScalar fCachedRadius;
172 SkScalar fCachedDiffRadius;
173
174 // @}
175
176private:
fmenozzi55d318d2016-08-09 08:05:57 -0700177 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000178
179};
180
Brian Salomon94efbf52016-11-29 13:43:05 -0500181void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800182 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700183 Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800184}
185
egdaniel57d3b032015-11-13 11:57:27 -0800186GrGLSLFragmentProcessor* Edge2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700187 return new Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor(*this);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000188}
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000189
joshualittb0a8a372014-09-23 09:50:21 -0700190GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Edge2PtConicalEffect);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000191
joshualitt01258472014-09-22 10:29:30 -0700192/*
193 * All Two point conical gradient test create functions may occasionally create edge case shaders
194 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500195#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400196std::unique_ptr<GrFragmentProcessor> Edge2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700197 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
198 SkScalar radius1 = d->fRandom->nextUScalar1();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000199 SkPoint center2;
200 SkScalar radius2;
201 do {
joshualitt0067ff52015-07-08 14:26:19 -0700202 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000203 // If the circles are identical the factory will give us an empty shader.
204 // This will happen if we pick identical centers
205 } while (center1 == center2);
206
207 // Below makes sure that circle one is contained within circle two
208 // and both circles are touching on an edge
209 SkPoint diff = center2 - center1;
210 SkScalar diffLen = diff.length();
211 radius2 = radius1 + diffLen;
212
Brian Osman3f748602016-10-03 18:29:03 -0400213 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400214 auto shader = params.fUseColors4f ?
215 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
216 params.fColors4f, params.fColorSpace, params.fStops,
217 params.fColorCount, params.fTileMode) :
218 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
219 params.fColors, params.fStops,
220 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400221 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400222 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700223 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700224 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000225}
Hal Canary6f6961e2017-01-31 13:50:44 -0500226#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000227
fmenozzi55d318d2016-08-09 08:05:57 -0700228Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GLSLEdge2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700229 : fVSVaryingName(nullptr)
230 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000231 , fCachedRadius(-SK_ScalarMax)
232 , fCachedDiffRadius(-SK_ScalarMax) {}
233
fmenozzi55d318d2016-08-09 08:05:57 -0700234void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700235 const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800236 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
237 this->emitUniforms(uniformHandler, ge);
Brian Salomon1d816b92017-08-17 11:07:59 -0400238 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
239 kVec3f_GrSLType, kDefault_GrSLPrecision,
jvanverthde11ee42016-02-26 13:58:40 -0800240 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000241
242 SkString cName("c");
243 SkString tName("t");
244 SkString p0; // start radius
245 SkString p1; // start radius squared
246 SkString p2; // difference in radii (r1 - r0)
247
jvanverthde11ee42016-02-26 13:58:40 -0800248
249 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
250 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
251 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000252
253 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700254 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000255 const char* coords2D;
256 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800257 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Brian Salomon1d816b92017-08-17 11:07:59 -0400258 if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
259 fragBuilder->codeAppendf("\tfloat3 interpolants = float3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700260 args.fTransformedCoords[0].c_str(),
261 args.fTransformedCoords[0].c_str(),
262 args.fTransformedCoords[1].c_str(),
263 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000264 coords2D = "interpolants.xy";
265 bVar = "interpolants.z";
266 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700267 coords2D = args.fTransformedCoords[0].c_str();
268 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000269 }
270
271 // output will default to transparent black (we simply won't write anything
272 // else to it if invalid, instead of discarding or returning prematurely)
Brian Salomon1d816b92017-08-17 11:07:59 -0400273 fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000274
275 // c = (x^2)+(y^2) - params[1]
Brian Salomon1d816b92017-08-17 11:07:59 -0400276 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000277 cName.c_str(), coords2D, coords2D, p1.c_str());
278
279 // linear case: t = -c/b
Brian Salomon1d816b92017-08-17 11:07:59 -0400280 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000281 cName.c_str(), bVar.c_str());
282
283 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800284 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000285 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800286 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800287 this->emitColor(fragBuilder,
288 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500289 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800290 ge,
291 tName.c_str(),
292 args.fOutputColor,
293 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700294 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800295 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000296}
297
fmenozzi55d318d2016-08-09 08:05:57 -0700298void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400299 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700300 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700301 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000302 SkScalar radius0 = data.radius();
303 SkScalar diffRadius = data.diffRadius();
304
305 if (fCachedRadius != radius0 ||
306 fCachedDiffRadius != diffRadius) {
307
Mike Reed8be952a2017-02-13 20:44:33 -0500308 pdman.set3f(fParamUni, radius0, radius0 * radius0, diffRadius);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000309 fCachedRadius = radius0;
310 fCachedDiffRadius = diffRadius;
311 }
312}
313
fmenozzi55d318d2016-08-09 08:05:57 -0700314void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500315 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700316 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000317}
318
319//////////////////////////////////////////////////////////////////////////////
320// Focal Conical Gradients
321//////////////////////////////////////////////////////////////////////////////
322
323static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
324 SkMatrix* invLMatrix, SkScalar* focalX) {
325 // Inverse of the current local matrix is passed in then,
326 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
327 // and focal point is at the origin.
328 ConicalType conicalType;
329 const SkPoint& focal = shader.getStartCenter();
330 const SkPoint& centerEnd = shader.getEndCenter();
331 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000332 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000333
334 SkMatrix matrix;
335
336 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
337 matrix.postScale(invRadius, invRadius);
338
339 SkPoint focalTrans;
340 matrix.mapPoints(&focalTrans, &focal, 1);
341 *focalX = focalTrans.length();
342
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000343 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000344 SkScalar invFocalX = SkScalarInvert(*focalX);
345 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -0500346 rot.setSinCos(-invFocalX * focalTrans.fY, invFocalX * focalTrans.fX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000347 matrix.postConcat(rot);
348 }
349
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000350 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000351
352 // If the focal point is touching the edge of the circle it will
353 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700354 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
355 // stability trade off versus the linear approx used in the Edge Shader
356 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000357 return kEdge_ConicalType;
358 }
359
360 // Scale factor 1 / (1 - focalX * focalX)
Mike Reed8be952a2017-02-13 20:44:33 -0500361 SkScalar oneMinusF2 = 1.f - *focalX * *focalX;
reed80ea19c2015-05-12 10:37:34 -0700362 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000363
364
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000365 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000366 conicalType = kInside_ConicalType;
367 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
368 } else {
369 conicalType = kOutside_ConicalType;
370 matrix.postScale(s, s);
371 }
372
373 invLMatrix->postConcat(matrix);
374
375 return conicalType;
376}
377
378//////////////////////////////////////////////////////////////////////////////
379
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000380class FocalOutside2PtConicalEffect : public GrGradientEffect {
381public:
fmenozzi55d318d2016-08-09 08:05:57 -0700382 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000383
Brian Salomonaff329b2017-08-11 09:40:37 -0400384 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
385 auto processor = std::unique_ptr<FocalOutside2PtConicalEffect>(
386 new FocalOutside2PtConicalEffect(args, focalX));
Brian Salomon6af27012017-06-09 08:21:42 -0400387 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000388 }
389
mtklein36352bf2015-03-25 18:17:31 -0700390 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800391 return "Two-Point Conical Gradient Focal Outside";
392 }
393
Brian Salomonaff329b2017-08-11 09:40:37 -0400394 std::unique_ptr<GrFragmentProcessor> clone() const override {
395 return std::unique_ptr<GrFragmentProcessor>(new FocalOutside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -0400396 }
397
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000398 bool isFlipped() const { return fIsFlipped; }
399 SkScalar focal() const { return fFocalX; }
400
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000401private:
egdaniel57d3b032015-11-13 11:57:27 -0800402 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700403
Brian Salomon94efbf52016-11-29 13:43:05 -0500404 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700405
mtklein36352bf2015-03-25 18:17:31 -0700406 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700407 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000408 return (INHERITED::onIsEqual(sBase) &&
409 this->fFocalX == s.fFocalX &&
410 this->fIsFlipped == s.fIsFlipped);
411 }
412
Brian Salomon587e08f2017-01-27 10:59:27 -0500413 static bool IsFlipped(const CreateArgs& args) {
414 // eww.
415 return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
416 }
417
brianosman9557c272016-09-15 06:59:15 -0700418 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500419 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
420 , fFocalX(focalX)
421 , fIsFlipped(IsFlipped(args)) {
joshualitteb2a6762014-12-04 11:35:33 -0800422 this->initClassID<FocalOutside2PtConicalEffect>();
423 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000424
Brian Salomonf8480b92017-07-27 15:45:59 -0400425 explicit FocalOutside2PtConicalEffect(const FocalOutside2PtConicalEffect& that)
426 : INHERITED(that), fFocalX(that.fFocalX), fIsFlipped(that.fIsFlipped) {
427 this->initClassID<FocalOutside2PtConicalEffect>();
428 }
429
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400430 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000431
432 SkScalar fFocalX;
433 bool fIsFlipped;
434
435 typedef GrGradientEffect INHERITED;
436};
437
Brian Salomon587e08f2017-01-27 10:59:27 -0500438class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700439 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000440public:
fmenozzi55d318d2016-08-09 08:05:57 -0700441 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000442
wangyix7c157a92015-07-22 15:08:53 -0700443 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000444
Brian Salomon94efbf52016-11-29 13:43:05 -0500445 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000446
447protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400448 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700449
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000450 UniformHandle fParamUni;
451
452 const char* fVSVaryingName;
453 const char* fFSVaryingName;
454
455 bool fIsFlipped;
456
457 // @{
458 /// Values last uploaded as uniforms
459
460 SkScalar fCachedFocal;
461
462 // @}
463
464private:
fmenozzi55d318d2016-08-09 08:05:57 -0700465 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000466
467};
468
Brian Salomon94efbf52016-11-29 13:43:05 -0500469void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800470 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700471 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800472}
473
egdaniel57d3b032015-11-13 11:57:27 -0800474GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700475 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000476}
477
joshualittb0a8a372014-09-23 09:50:21 -0700478GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000479
joshualitt01258472014-09-22 10:29:30 -0700480/*
481 * All Two point conical gradient test create functions may occasionally create edge case shaders
482 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500483#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400484std::unique_ptr<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(
485 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700486 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000487 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000488 SkPoint center2;
489 SkScalar radius2;
490 do {
joshualitt0067ff52015-07-08 14:26:19 -0700491 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000492 // Need to make sure the centers are not the same or else focal point will be inside
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000493 } while (center1 == center2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000494
Brian Osman3f748602016-10-03 18:29:03 -0400495 SkPoint diff = center2 - center1;
496 SkScalar diffLen = diff.length();
497 // Below makes sure that the focal point is not contained within circle two
498 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
499
500 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400501 auto shader = params.fUseColors4f ?
502 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
503 params.fColors4f, params.fColorSpace, params.fStops,
504 params.fColorCount, params.fTileMode) :
505 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
506 params.fColors, params.fStops,
507 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400508 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400509 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700510 GrAlwaysAssert(fp);
511 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000512}
Hal Canary6f6961e2017-01-31 13:50:44 -0500513#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000514
fmenozzi55d318d2016-08-09 08:05:57 -0700515FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
516 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700517 : fVSVaryingName(nullptr)
518 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000519 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700520 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000521 fIsFlipped = data.isFlipped();
522}
523
fmenozzi55d318d2016-08-09 08:05:57 -0700524void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700525 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800526 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
527 this->emitUniforms(uniformHandler, ge);
Brian Salomon1d816b92017-08-17 11:07:59 -0400528 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
529 kVec2f_GrSLType, kDefault_GrSLPrecision,
jvanverthde11ee42016-02-26 13:58:40 -0800530 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000531 SkString tName("t");
532 SkString p0; // focalX
533 SkString p1; // 1 - focalX * focalX
534
jvanverthde11ee42016-02-26 13:58:40 -0800535 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
536 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000537
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400538 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -0800539 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700540 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000541 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000542
543 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
544
545 // output will default to transparent black (we simply won't write anything
546 // else to it if invalid, instead of discarding or returning prematurely)
Brian Salomon1d816b92017-08-17 11:07:59 -0400547 fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000548
Brian Salomon1d816b92017-08-17 11:07:59 -0400549 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
550 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
551 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000552
553 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
554 // If so we must also flip sign on sqrt
555 if (!fIsFlipped) {
Brian Salomon1d816b92017-08-17 11:07:59 -0400556 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -0800557 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000558 } else {
Brian Salomon1d816b92017-08-17 11:07:59 -0400559 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -0800560 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000561 }
562
egdaniel4ca2e602015-11-18 08:01:26 -0800563 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
564 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800565 this->emitColor(fragBuilder,
566 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500567 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800568 ge,
569 tName.c_str(),
570 args.fOutputColor,
571 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700572 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800573 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000574}
575
fmenozzi55d318d2016-08-09 08:05:57 -0700576void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400577 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700578 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700579 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000580 SkASSERT(data.isFlipped() == fIsFlipped);
581 SkScalar focal = data.focal();
582
583 if (fCachedFocal != focal) {
Mike Reed8be952a2017-02-13 20:44:33 -0500584 SkScalar oneMinus2F = 1.f - focal * focal;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000585
jvanverthde11ee42016-02-26 13:58:40 -0800586 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000587 fCachedFocal = focal;
588 }
589}
590
fmenozzi55d318d2016-08-09 08:05:57 -0700591void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
592 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500593 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700594 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700595 key[0] = GenBaseGradientKey(processor);
596 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000597}
598
599//////////////////////////////////////////////////////////////////////////////
600
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000601class FocalInside2PtConicalEffect : public GrGradientEffect {
602public:
fmenozzi55d318d2016-08-09 08:05:57 -0700603 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000604
Brian Salomonaff329b2017-08-11 09:40:37 -0400605 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
606 auto processor = std::unique_ptr<FocalInside2PtConicalEffect>(
607 new FocalInside2PtConicalEffect(args, focalX));
Brian Salomon6af27012017-06-09 08:21:42 -0400608 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000609 }
610
mtklein36352bf2015-03-25 18:17:31 -0700611 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800612 return "Two-Point Conical Gradient Focal Inside";
613 }
614
Brian Salomonaff329b2017-08-11 09:40:37 -0400615 std::unique_ptr<GrFragmentProcessor> clone() const override {
616 return std::unique_ptr<GrFragmentProcessor>(new FocalInside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -0400617 }
618
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000619 SkScalar focal() const { return fFocalX; }
620
fmenozzi55d318d2016-08-09 08:05:57 -0700621 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000622
623private:
egdaniel57d3b032015-11-13 11:57:27 -0800624 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700625
Brian Salomon94efbf52016-11-29 13:43:05 -0500626 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700627
mtklein36352bf2015-03-25 18:17:31 -0700628 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700629 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000630 return (INHERITED::onIsEqual(sBase) &&
631 this->fFocalX == s.fFocalX);
632 }
633
brianosman9557c272016-09-15 06:59:15 -0700634 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500635 : INHERITED(args, args.fShader->colorsAreOpaque()), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800636 this->initClassID<FocalInside2PtConicalEffect>();
637 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000638
Brian Salomonf8480b92017-07-27 15:45:59 -0400639 explicit FocalInside2PtConicalEffect(const FocalInside2PtConicalEffect& that)
640 : INHERITED(that), fFocalX(that.fFocalX) {
641 this->initClassID<FocalInside2PtConicalEffect>();
642 }
643
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400644 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000645
646 SkScalar fFocalX;
647
648 typedef GrGradientEffect INHERITED;
649};
650
fmenozzi55d318d2016-08-09 08:05:57 -0700651class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
652 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000653public:
fmenozzi55d318d2016-08-09 08:05:57 -0700654 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000655
wangyix7c157a92015-07-22 15:08:53 -0700656 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000657
Brian Salomon94efbf52016-11-29 13:43:05 -0500658 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000659
660protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400661 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700662
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000663 UniformHandle fFocalUni;
664
665 const char* fVSVaryingName;
666 const char* fFSVaryingName;
667
668 // @{
669 /// Values last uploaded as uniforms
670
671 SkScalar fCachedFocal;
672
673 // @}
674
675private:
fmenozzi55d318d2016-08-09 08:05:57 -0700676 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000677
678};
679
Brian Salomon94efbf52016-11-29 13:43:05 -0500680void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800681 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700682 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800683}
684
egdaniel57d3b032015-11-13 11:57:27 -0800685GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700686 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000687}
688
joshualittb0a8a372014-09-23 09:50:21 -0700689GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000690
joshualitt01258472014-09-22 10:29:30 -0700691/*
692 * All Two point conical gradient test create functions may occasionally create edge case shaders
693 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500694#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400695std::unique_ptr<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(
696 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700697 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000698 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000699 SkPoint center2;
700 SkScalar radius2;
701 do {
joshualitt0067ff52015-07-08 14:26:19 -0700702 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000703 // Below makes sure radius2 is larger enouch such that the focal point
704 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700705 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000706 SkPoint diff = center2 - center1;
707 SkScalar diffLen = diff.length();
708 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000709 // If the circles are identical the factory will give us an empty shader.
710 } while (radius1 == radius2 && center1 == center2);
711
Brian Osman3f748602016-10-03 18:29:03 -0400712 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400713 auto shader = params.fUseColors4f ?
714 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
715 params.fColors4f, params.fColorSpace, params.fStops,
716 params.fColorCount, params.fTileMode) :
717 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
718 params.fColors, params.fStops,
719 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400720 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400721 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700722 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700723 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000724}
Hal Canary6f6961e2017-01-31 13:50:44 -0500725#endif
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000726
fmenozzi55d318d2016-08-09 08:05:57 -0700727FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
728 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700729 : fVSVaryingName(nullptr)
730 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000731 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000732
fmenozzi55d318d2016-08-09 08:05:57 -0700733void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700734 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800735 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
736 this->emitUniforms(uniformHandler, ge);
Brian Salomon1d816b92017-08-17 11:07:59 -0400737 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
738 kFloat_GrSLType, kDefault_GrSLPrecision,
egdaniel7ea439b2015-12-03 09:20:44 -0800739 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000740 SkString tName("t");
741
742 // this is the distance along x-axis from the end center to focal point in
743 // transformed coordinates
Brian Salomon99938a82016-11-21 13:41:08 -0500744 GrShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000745
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400746 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -0800747 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700748 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000749 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000750
751 // t = p.x * focalX + length(p)
Brian Salomon1d816b92017-08-17 11:07:59 -0400752 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800753 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000754
egdaniel7ea439b2015-12-03 09:20:44 -0800755 this->emitColor(fragBuilder,
756 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500757 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800758 ge,
759 tName.c_str(),
760 args.fOutputColor,
761 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700762 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000763}
764
fmenozzi55d318d2016-08-09 08:05:57 -0700765void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400766 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700767 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700768 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000769 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000770
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000771 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700772 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000773 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000774 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000775}
776
fmenozzi55d318d2016-08-09 08:05:57 -0700777void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
778 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500779 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700780 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000781}
782
783//////////////////////////////////////////////////////////////////////////////
784// Circle Conical Gradients
785//////////////////////////////////////////////////////////////////////////////
786
787struct CircleConicalInfo {
788 SkPoint fCenterEnd;
789 SkScalar fA;
790 SkScalar fB;
791 SkScalar fC;
792};
793
794// Returns focal distance along x-axis in transformed coords
795static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
796 SkMatrix* invLMatrix, CircleConicalInfo* info) {
797 // Inverse of the current local matrix is passed in then,
798 // translate and scale such that start circle is on the origin and has radius 1
799 const SkPoint& centerStart = shader.getStartCenter();
800 const SkPoint& centerEnd = shader.getEndCenter();
801 SkScalar radiusStart = shader.getStartRadius();
802 SkScalar radiusEnd = shader.getEndRadius();
803
804 SkMatrix matrix;
805
806 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
807
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000808 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000809 matrix.postScale(invStartRad, invStartRad);
810
811 radiusEnd /= radiusStart;
812
813 SkPoint centerEndTrans;
814 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
815
816 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
817 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
818
819 // Check to see if start circle is inside end circle with edges touching.
820 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700821 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
822 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
823 // still accurate.
824 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000825 return kEdge_ConicalType;
826 }
827
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000828 SkScalar C = 1.f / A;
829 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000830
831 matrix.postScale(C, C);
832
833 invLMatrix->postConcat(matrix);
834
835 info->fCenterEnd = centerEndTrans;
836 info->fA = A;
837 info->fB = B;
838 info->fC = C;
839
840 // if A ends up being negative, the start circle is contained completely inside the end cirlce
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000841 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000842 return kInside_ConicalType;
843 }
844 return kOutside_ConicalType;
845}
846
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000847class CircleInside2PtConicalEffect : public GrGradientEffect {
848public:
fmenozzi55d318d2016-08-09 08:05:57 -0700849 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000850
Brian Salomonaff329b2017-08-11 09:40:37 -0400851 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args,
852 const CircleConicalInfo& info) {
853 auto processor = std::unique_ptr<CircleInside2PtConicalEffect>(
854 new CircleInside2PtConicalEffect(args, info));
Brian Salomon6af27012017-06-09 08:21:42 -0400855 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000856 }
857
mtklein36352bf2015-03-25 18:17:31 -0700858 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800859
Brian Salomonaff329b2017-08-11 09:40:37 -0400860 std::unique_ptr<GrFragmentProcessor> clone() const override {
861 return std::unique_ptr<GrFragmentProcessor>(new CircleInside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -0400862 }
863
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000864 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
865 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
866 SkScalar A() const { return fInfo.fA; }
867 SkScalar B() const { return fInfo.fB; }
868 SkScalar C() const { return fInfo.fC; }
869
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000870private:
egdaniel57d3b032015-11-13 11:57:27 -0800871 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700872
Brian Salomon94efbf52016-11-29 13:43:05 -0500873 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800874 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700875
mtklein36352bf2015-03-25 18:17:31 -0700876 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700877 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000878 return (INHERITED::onIsEqual(sBase) &&
879 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
880 this->fInfo.fA == s.fInfo.fA &&
881 this->fInfo.fB == s.fInfo.fB &&
882 this->fInfo.fC == s.fInfo.fC);
883 }
884
brianosman9557c272016-09-15 06:59:15 -0700885 CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -0500886 : INHERITED(args, args.fShader->colorsAreOpaque()), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800887 this->initClassID<CircleInside2PtConicalEffect>();
888 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000889
Brian Salomonf8480b92017-07-27 15:45:59 -0400890 explicit CircleInside2PtConicalEffect(const CircleInside2PtConicalEffect& that)
891 : INHERITED(that), fInfo(that.fInfo) {
892 this->initClassID<CircleInside2PtConicalEffect>();
893 }
894
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400895 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000896
897 const CircleConicalInfo fInfo;
898
899 typedef GrGradientEffect INHERITED;
900};
901
Brian Salomonf8480b92017-07-27 15:45:59 -0400902class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700903 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000904public:
fmenozzi55d318d2016-08-09 08:05:57 -0700905 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000906
wangyix7c157a92015-07-22 15:08:53 -0700907 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000908
Brian Salomon94efbf52016-11-29 13:43:05 -0500909 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000910
911protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400912 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700913
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000914 UniformHandle fCenterUni;
915 UniformHandle fParamUni;
916
917 const char* fVSVaryingName;
918 const char* fFSVaryingName;
919
920 // @{
921 /// Values last uploaded as uniforms
922
923 SkScalar fCachedCenterX;
924 SkScalar fCachedCenterY;
925 SkScalar fCachedA;
926 SkScalar fCachedB;
927 SkScalar fCachedC;
928
929 // @}
930
931private:
fmenozzi55d318d2016-08-09 08:05:57 -0700932 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000933
934};
935
Brian Salomon94efbf52016-11-29 13:43:05 -0500936void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800937 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700938 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800939}
940
egdaniel57d3b032015-11-13 11:57:27 -0800941GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700942 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000943}
944
joshualittb0a8a372014-09-23 09:50:21 -0700945GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000946
joshualitt01258472014-09-22 10:29:30 -0700947/*
948 * All Two point conical gradient test create functions may occasionally create edge case shaders
949 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500950#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400951std::unique_ptr<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(
952 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700953 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
954 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000955 SkPoint center2;
956 SkScalar radius2;
957 do {
joshualitt0067ff52015-07-08 14:26:19 -0700958 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000959 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700960 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000961 SkPoint diff = center2 - center1;
962 SkScalar diffLen = diff.length();
963 radius2 = radius1 + diffLen + increase;
964 // If the circles are identical the factory will give us an empty shader.
965 } while (radius1 == radius2 && center1 == center2);
966
Brian Osman3f748602016-10-03 18:29:03 -0400967 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400968 auto shader = params.fUseColors4f ?
969 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
970 params.fColors4f, params.fColorSpace, params.fStops,
971 params.fColorCount, params.fTileMode) :
972 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
973 params.fColors, params.fStops,
974 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400975 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400976 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700977 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700978 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000979}
Hal Canary6f6961e2017-01-31 13:50:44 -0500980#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000981
fmenozzi55d318d2016-08-09 08:05:57 -0700982CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
983 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700984 : fVSVaryingName(nullptr)
985 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000986 , fCachedCenterX(SK_ScalarMax)
987 , fCachedCenterY(SK_ScalarMax)
988 , fCachedA(SK_ScalarMax)
989 , fCachedB(SK_ScalarMax)
990 , fCachedC(SK_ScalarMax) {}
991
fmenozzi55d318d2016-08-09 08:05:57 -0700992void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700993 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800994 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
995 this->emitUniforms(uniformHandler, ge);
Brian Salomon1d816b92017-08-17 11:07:59 -0400996 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
997 kVec2f_GrSLType, kDefault_GrSLPrecision,
egdaniel7ea439b2015-12-03 09:20:44 -0800998 "Conical2FSCenter");
Brian Salomon1d816b92017-08-17 11:07:59 -0400999 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1000 kVec3f_GrSLType, kDefault_GrSLPrecision,
egdaniel7ea439b2015-12-03 09:20:44 -08001001 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001002 SkString tName("t");
1003
Brian Salomon99938a82016-11-21 13:41:08 -05001004 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001005 // params.x = A
1006 // params.y = B
1007 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001008 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001009
Ethan Nicholas5af9ea32017-07-28 15:19:46 -04001010 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -08001011 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001012 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001013 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001014
1015 // p = coords2D
1016 // e = center end
1017 // r = radius end
1018 // A = dot(e, e) - r^2 + 2 * r - 1
1019 // B = (r -1) / A
1020 // C = 1 / A
1021 // d = dot(e, p) + B
1022 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
Brian Salomon1d816b92017-08-17 11:07:59 -04001023 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1024 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -08001025 params.c_str());
Brian Salomon1d816b92017-08-17 11:07:59 -04001026 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
egdaniel4ca2e602015-11-18 08:01:26 -08001027 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001028
egdaniel7ea439b2015-12-03 09:20:44 -08001029 this->emitColor(fragBuilder,
1030 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001031 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001032 ge,
1033 tName.c_str(),
1034 args.fOutputColor,
1035 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001036 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001037}
1038
fmenozzi55d318d2016-08-09 08:05:57 -07001039void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001040 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001041 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001042 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001043 SkScalar centerX = data.centerX();
1044 SkScalar centerY = data.centerY();
1045 SkScalar A = data.A();
1046 SkScalar B = data.B();
1047 SkScalar C = data.C();
1048
1049 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1050 fCachedA != A || fCachedB != B || fCachedC != C) {
1051
kkinnunen7510b222014-07-30 00:04:16 -07001052 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1053 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001054
1055 fCachedCenterX = centerX;
1056 fCachedCenterY = centerY;
1057 fCachedA = A;
1058 fCachedB = B;
1059 fCachedC = C;
1060 }
1061}
1062
fmenozzi55d318d2016-08-09 08:05:57 -07001063void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1064 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001065 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001066 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001067}
1068
1069//////////////////////////////////////////////////////////////////////////////
1070
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001071class CircleOutside2PtConicalEffect : public GrGradientEffect {
1072public:
fmenozzi55d318d2016-08-09 08:05:57 -07001073 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001074
Brian Salomonaff329b2017-08-11 09:40:37 -04001075 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args,
1076 const CircleConicalInfo& info) {
1077 return std::unique_ptr<GrFragmentProcessor>(new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001078 }
1079
mtklein36352bf2015-03-25 18:17:31 -07001080 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001081
Brian Salomonaff329b2017-08-11 09:40:37 -04001082 std::unique_ptr<GrFragmentProcessor> clone() const override {
1083 return std::unique_ptr<GrFragmentProcessor>(new CircleOutside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -04001084 }
1085
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001086 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1087 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1088 SkScalar A() const { return fInfo.fA; }
1089 SkScalar B() const { return fInfo.fB; }
1090 SkScalar C() const { return fInfo.fC; }
1091 SkScalar tLimit() const { return fTLimit; }
1092 bool isFlipped() const { return fIsFlipped; }
1093
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001094private:
egdaniel57d3b032015-11-13 11:57:27 -08001095 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001096
Brian Salomon94efbf52016-11-29 13:43:05 -05001097 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001098
mtklein36352bf2015-03-25 18:17:31 -07001099 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001100 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001101 return (INHERITED::onIsEqual(sBase) &&
1102 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1103 this->fInfo.fA == s.fInfo.fA &&
1104 this->fInfo.fB == s.fInfo.fB &&
1105 this->fInfo.fC == s.fInfo.fC &&
1106 this->fTLimit == s.fTLimit &&
1107 this->fIsFlipped == s.fIsFlipped);
1108 }
1109
brianosman9557c272016-09-15 06:59:15 -07001110 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -05001111 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
1112 , fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001113 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001114 const SkTwoPointConicalGradient& shader =
1115 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001116 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001117 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001118 } else {
1119 fTLimit = SK_ScalarMin;
1120 }
1121
1122 fIsFlipped = shader.isFlippedGrad();
1123 }
1124
Brian Salomonf8480b92017-07-27 15:45:59 -04001125 explicit CircleOutside2PtConicalEffect(const CircleOutside2PtConicalEffect& that)
1126 : INHERITED(that)
1127 , fInfo(that.fInfo)
1128 , fTLimit(that.fTLimit)
1129 , fIsFlipped(that.fIsFlipped) {
1130 this->initClassID<CircleOutside2PtConicalEffect>();
1131 }
1132
Brian Salomon0c26a9d2017-07-06 10:09:38 -04001133 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001134
1135 const CircleConicalInfo fInfo;
1136 SkScalar fTLimit;
1137 bool fIsFlipped;
1138
1139 typedef GrGradientEffect INHERITED;
1140};
1141
fmenozzi55d318d2016-08-09 08:05:57 -07001142class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1143 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001144public:
fmenozzi55d318d2016-08-09 08:05:57 -07001145 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001146
wangyix7c157a92015-07-22 15:08:53 -07001147 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001148
Brian Salomon94efbf52016-11-29 13:43:05 -05001149 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001150
1151protected:
Brian Salomonab015ef2017-04-04 10:15:51 -04001152 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001153
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001154 UniformHandle fCenterUni;
1155 UniformHandle fParamUni;
1156
1157 const char* fVSVaryingName;
1158 const char* fFSVaryingName;
1159
1160 bool fIsFlipped;
1161
1162 // @{
1163 /// Values last uploaded as uniforms
1164
1165 SkScalar fCachedCenterX;
1166 SkScalar fCachedCenterY;
1167 SkScalar fCachedA;
1168 SkScalar fCachedB;
1169 SkScalar fCachedC;
1170 SkScalar fCachedTLimit;
1171
1172 // @}
1173
1174private:
fmenozzi55d318d2016-08-09 08:05:57 -07001175 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001176
1177};
1178
Brian Salomon94efbf52016-11-29 13:43:05 -05001179void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -08001180 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001181 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001182}
1183
egdaniel57d3b032015-11-13 11:57:27 -08001184GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001185 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001186}
1187
joshualittb0a8a372014-09-23 09:50:21 -07001188GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001189
joshualitt01258472014-09-22 10:29:30 -07001190/*
1191 * All Two point conical gradient test create functions may occasionally create edge case shaders
1192 */
Hal Canary6f6961e2017-01-31 13:50:44 -05001193#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -04001194std::unique_ptr<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(
1195 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001196 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1197 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001198 SkPoint center2;
1199 SkScalar radius2;
1200 SkScalar diffLen;
1201 do {
joshualitt0067ff52015-07-08 14:26:19 -07001202 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001203 // If the circles share a center than we can't be in the outside case
1204 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001205 SkPoint diff = center2 - center1;
1206 diffLen = diff.length();
1207 // Below makes sure that circle one is not contained within circle two
1208 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001209 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001210
Brian Osman3f748602016-10-03 18:29:03 -04001211 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -04001212 auto shader = params.fUseColors4f ?
1213 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1214 params.fColors4f, params.fColorSpace, params.fStops,
1215 params.fColorCount, params.fTileMode) :
1216 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1217 params.fColors, params.fStops,
1218 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -04001219 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -04001220 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -07001221 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001222 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001223}
Hal Canary6f6961e2017-01-31 13:50:44 -05001224#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001225
fmenozzi55d318d2016-08-09 08:05:57 -07001226CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1227 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001228 : fVSVaryingName(nullptr)
1229 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001230 , fCachedCenterX(SK_ScalarMax)
1231 , fCachedCenterY(SK_ScalarMax)
1232 , fCachedA(SK_ScalarMax)
1233 , fCachedB(SK_ScalarMax)
1234 , fCachedC(SK_ScalarMax)
1235 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001236 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001237 fIsFlipped = data.isFlipped();
1238 }
1239
fmenozzi55d318d2016-08-09 08:05:57 -07001240void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001241 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001242 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1243 this->emitUniforms(uniformHandler, ge);
Brian Salomon1d816b92017-08-17 11:07:59 -04001244 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1245 kVec2f_GrSLType, kDefault_GrSLPrecision,
egdaniel7ea439b2015-12-03 09:20:44 -08001246 "Conical2FSCenter");
Brian Salomon1d816b92017-08-17 11:07:59 -04001247 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1248 kVec4f_GrSLType, kDefault_GrSLPrecision,
egdaniel7ea439b2015-12-03 09:20:44 -08001249 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001250 SkString tName("t");
1251
Brian Salomon99938a82016-11-21 13:41:08 -05001252 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001253 // params.x = A
1254 // params.y = B
1255 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001256 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001257
Ethan Nicholas5af9ea32017-07-28 15:19:46 -04001258 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -08001259 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001260 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001261 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001262
1263 // output will default to transparent black (we simply won't write anything
1264 // else to it if invalid, instead of discarding or returning prematurely)
Brian Salomon1d816b92017-08-17 11:07:59 -04001265 fragBuilder->codeAppendf("\t%s = float4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001266
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001267 // p = coords2D
1268 // e = center end
1269 // r = radius end
1270 // A = dot(e, e) - r^2 + 2 * r - 1
1271 // B = (r -1) / A
1272 // C = 1 / A
1273 // d = dot(e, p) + B
1274 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001275
Brian Salomon1d816b92017-08-17 11:07:59 -04001276 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1277 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -08001278 params.c_str());
Brian Salomon1d816b92017-08-17 11:07:59 -04001279 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -08001280 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001281
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001282 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1283 // If so we must also flip sign on sqrt
1284 if (!fIsFlipped) {
Brian Salomon1d816b92017-08-17 11:07:59 -04001285 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001286 } else {
Brian Salomon1d816b92017-08-17 11:07:59 -04001287 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001288 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001289
egdaniel7ea439b2015-12-03 09:20:44 -08001290 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1291 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001292 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001293 this->emitColor(fragBuilder,
1294 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001295 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001296 ge,
1297 tName.c_str(),
1298 args.fOutputColor,
1299 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001300 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001301 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001302}
1303
fmenozzi55d318d2016-08-09 08:05:57 -07001304void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001305 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001306 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001307 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001308 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001309 SkScalar centerX = data.centerX();
1310 SkScalar centerY = data.centerY();
1311 SkScalar A = data.A();
1312 SkScalar B = data.B();
1313 SkScalar C = data.C();
1314 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001315
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001316 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1317 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001318
kkinnunen7510b222014-07-30 00:04:16 -07001319 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1320 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001321 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001322
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001323 fCachedCenterX = centerX;
1324 fCachedCenterY = centerY;
1325 fCachedA = A;
1326 fCachedB = B;
1327 fCachedC = C;
1328 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001329 }
1330}
1331
fmenozzi55d318d2016-08-09 08:05:57 -07001332void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1333 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001334 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001335 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001336 key[0] = GenBaseGradientKey(processor);
1337 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001338}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001339
1340//////////////////////////////////////////////////////////////////////////////
1341
Brian Salomonaff329b2017-08-11 09:40:37 -04001342std::unique_ptr<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1343 const GrGradientEffect::CreateArgs& args) {
brianosman9557c272016-09-15 06:59:15 -07001344 const SkTwoPointConicalGradient& shader =
1345 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1346
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001347 SkMatrix matrix;
1348 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001349 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001350 }
brianosman9557c272016-09-15 06:59:15 -07001351 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001352 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001353 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001354 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001355 }
1356 matrix.postConcat(inv);
1357 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001358
brianosmanb9c51372016-09-15 11:09:45 -07001359 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1360 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001361
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001362 if (shader.getStartRadius() < kErrorTol) {
1363 SkScalar focalX;
1364 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1365 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001366 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001367 } else if(type == kEdge_ConicalType) {
1368 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001369 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001370 } else {
brianosman9557c272016-09-15 06:59:15 -07001371 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001372 }
1373 }
1374
1375 CircleConicalInfo info;
1376 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1377
1378 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001379 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001380 } else if (type == kEdge_ConicalType) {
1381 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001382 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001383 } else {
brianosman9557c272016-09-15 06:59:15 -07001384 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001385 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001386}
1387
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001388#endif