blob: 126a82a515c3ea656931b04a31addcc197b0be9a [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);
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400238 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
jvanverthde11ee42016-02-26 13:58:40 -0800239 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000240
241 SkString cName("c");
242 SkString tName("t");
243 SkString p0; // start radius
244 SkString p1; // start radius squared
245 SkString p2; // difference in radii (r1 - r0)
246
jvanverthde11ee42016-02-26 13:58:40 -0800247
248 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
249 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
250 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000251
252 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700253 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000254 const char* coords2D;
255 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800256 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400257 if (kHalf3_GrSLType == args.fTransformedCoords[0].getType()) {
258 fragBuilder->codeAppendf("\thalf3 interpolants = half3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700259 args.fTransformedCoords[0].c_str(),
260 args.fTransformedCoords[0].c_str(),
261 args.fTransformedCoords[1].c_str(),
262 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000263 coords2D = "interpolants.xy";
264 bVar = "interpolants.z";
265 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700266 coords2D = args.fTransformedCoords[0].c_str();
267 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000268 }
269
270 // output will default to transparent black (we simply won't write anything
271 // else to it if invalid, instead of discarding or returning prematurely)
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400272 fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000273
274 // c = (x^2)+(y^2) - params[1]
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400275 fragBuilder->codeAppendf("\thalf %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000276 cName.c_str(), coords2D, coords2D, p1.c_str());
277
278 // linear case: t = -c/b
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400279 fragBuilder->codeAppendf("\thalf %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000280 cName.c_str(), bVar.c_str());
281
282 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800283 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000284 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800285 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800286 this->emitColor(fragBuilder,
287 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500288 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800289 ge,
290 tName.c_str(),
291 args.fOutputColor,
292 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700293 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800294 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000295}
296
fmenozzi55d318d2016-08-09 08:05:57 -0700297void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400298 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700299 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700300 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000301 SkScalar radius0 = data.radius();
302 SkScalar diffRadius = data.diffRadius();
303
304 if (fCachedRadius != radius0 ||
305 fCachedDiffRadius != diffRadius) {
306
Mike Reed8be952a2017-02-13 20:44:33 -0500307 pdman.set3f(fParamUni, radius0, radius0 * radius0, diffRadius);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000308 fCachedRadius = radius0;
309 fCachedDiffRadius = diffRadius;
310 }
311}
312
fmenozzi55d318d2016-08-09 08:05:57 -0700313void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500314 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700315 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000316}
317
318//////////////////////////////////////////////////////////////////////////////
319// Focal Conical Gradients
320//////////////////////////////////////////////////////////////////////////////
321
322static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
323 SkMatrix* invLMatrix, SkScalar* focalX) {
324 // Inverse of the current local matrix is passed in then,
325 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
326 // and focal point is at the origin.
327 ConicalType conicalType;
328 const SkPoint& focal = shader.getStartCenter();
329 const SkPoint& centerEnd = shader.getEndCenter();
330 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000331 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000332
333 SkMatrix matrix;
334
335 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
336 matrix.postScale(invRadius, invRadius);
337
338 SkPoint focalTrans;
339 matrix.mapPoints(&focalTrans, &focal, 1);
340 *focalX = focalTrans.length();
341
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000342 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000343 SkScalar invFocalX = SkScalarInvert(*focalX);
344 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -0500345 rot.setSinCos(-invFocalX * focalTrans.fY, invFocalX * focalTrans.fX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000346 matrix.postConcat(rot);
347 }
348
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000349 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000350
351 // If the focal point is touching the edge of the circle it will
352 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700353 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
354 // stability trade off versus the linear approx used in the Edge Shader
355 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000356 return kEdge_ConicalType;
357 }
358
359 // Scale factor 1 / (1 - focalX * focalX)
Mike Reed8be952a2017-02-13 20:44:33 -0500360 SkScalar oneMinusF2 = 1.f - *focalX * *focalX;
reed80ea19c2015-05-12 10:37:34 -0700361 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000362
363
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000364 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000365 conicalType = kInside_ConicalType;
366 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
367 } else {
368 conicalType = kOutside_ConicalType;
369 matrix.postScale(s, s);
370 }
371
372 invLMatrix->postConcat(matrix);
373
374 return conicalType;
375}
376
377//////////////////////////////////////////////////////////////////////////////
378
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000379class FocalOutside2PtConicalEffect : public GrGradientEffect {
380public:
fmenozzi55d318d2016-08-09 08:05:57 -0700381 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000382
Brian Salomonaff329b2017-08-11 09:40:37 -0400383 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
384 auto processor = std::unique_ptr<FocalOutside2PtConicalEffect>(
385 new FocalOutside2PtConicalEffect(args, focalX));
Brian Salomon6af27012017-06-09 08:21:42 -0400386 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000387 }
388
mtklein36352bf2015-03-25 18:17:31 -0700389 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800390 return "Two-Point Conical Gradient Focal Outside";
391 }
392
Brian Salomonaff329b2017-08-11 09:40:37 -0400393 std::unique_ptr<GrFragmentProcessor> clone() const override {
394 return std::unique_ptr<GrFragmentProcessor>(new FocalOutside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -0400395 }
396
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000397 bool isFlipped() const { return fIsFlipped; }
398 SkScalar focal() const { return fFocalX; }
399
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000400private:
egdaniel57d3b032015-11-13 11:57:27 -0800401 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700402
Brian Salomon94efbf52016-11-29 13:43:05 -0500403 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700404
mtklein36352bf2015-03-25 18:17:31 -0700405 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700406 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000407 return (INHERITED::onIsEqual(sBase) &&
408 this->fFocalX == s.fFocalX &&
409 this->fIsFlipped == s.fIsFlipped);
410 }
411
Brian Salomon587e08f2017-01-27 10:59:27 -0500412 static bool IsFlipped(const CreateArgs& args) {
413 // eww.
414 return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
415 }
416
brianosman9557c272016-09-15 06:59:15 -0700417 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500418 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
419 , fFocalX(focalX)
420 , fIsFlipped(IsFlipped(args)) {
joshualitteb2a6762014-12-04 11:35:33 -0800421 this->initClassID<FocalOutside2PtConicalEffect>();
422 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000423
Brian Salomonf8480b92017-07-27 15:45:59 -0400424 explicit FocalOutside2PtConicalEffect(const FocalOutside2PtConicalEffect& that)
425 : INHERITED(that), fFocalX(that.fFocalX), fIsFlipped(that.fIsFlipped) {
426 this->initClassID<FocalOutside2PtConicalEffect>();
427 }
428
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400429 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000430
431 SkScalar fFocalX;
432 bool fIsFlipped;
433
434 typedef GrGradientEffect INHERITED;
435};
436
Brian Salomon587e08f2017-01-27 10:59:27 -0500437class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700438 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000439public:
fmenozzi55d318d2016-08-09 08:05:57 -0700440 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000441
wangyix7c157a92015-07-22 15:08:53 -0700442 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000443
Brian Salomon94efbf52016-11-29 13:43:05 -0500444 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000445
446protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400447 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700448
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000449 UniformHandle fParamUni;
450
451 const char* fVSVaryingName;
452 const char* fFSVaryingName;
453
454 bool fIsFlipped;
455
456 // @{
457 /// Values last uploaded as uniforms
458
459 SkScalar fCachedFocal;
460
461 // @}
462
463private:
fmenozzi55d318d2016-08-09 08:05:57 -0700464 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000465
466};
467
Brian Salomon94efbf52016-11-29 13:43:05 -0500468void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800469 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700470 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800471}
472
egdaniel57d3b032015-11-13 11:57:27 -0800473GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700474 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000475}
476
joshualittb0a8a372014-09-23 09:50:21 -0700477GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000478
joshualitt01258472014-09-22 10:29:30 -0700479/*
480 * All Two point conical gradient test create functions may occasionally create edge case shaders
481 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500482#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400483std::unique_ptr<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(
484 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700485 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000486 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000487 SkPoint center2;
488 SkScalar radius2;
489 do {
joshualitt0067ff52015-07-08 14:26:19 -0700490 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000491 // 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 +0000492 } while (center1 == center2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000493
Brian Osman3f748602016-10-03 18:29:03 -0400494 SkPoint diff = center2 - center1;
495 SkScalar diffLen = diff.length();
496 // Below makes sure that the focal point is not contained within circle two
497 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
498
499 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400500 auto shader = params.fUseColors4f ?
501 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
502 params.fColors4f, params.fColorSpace, params.fStops,
503 params.fColorCount, params.fTileMode) :
504 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
505 params.fColors, params.fStops,
506 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400507 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400508 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700509 GrAlwaysAssert(fp);
510 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000511}
Hal Canary6f6961e2017-01-31 13:50:44 -0500512#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000513
fmenozzi55d318d2016-08-09 08:05:57 -0700514FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
515 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700516 : fVSVaryingName(nullptr)
517 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000518 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700519 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000520 fIsFlipped = data.isFlipped();
521}
522
fmenozzi55d318d2016-08-09 08:05:57 -0700523void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700524 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800525 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
526 this->emitUniforms(uniformHandler, ge);
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400527 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
jvanverthde11ee42016-02-26 13:58:40 -0800528 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000529 SkString tName("t");
530 SkString p0; // focalX
531 SkString p1; // 1 - focalX * focalX
532
jvanverthde11ee42016-02-26 13:58:40 -0800533 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
534 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000535
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400536 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -0800537 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700538 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000539 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000540
541 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
542
543 // output will default to transparent black (we simply won't write anything
544 // else to it if invalid, instead of discarding or returning prematurely)
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400545 fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000546
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400547 fragBuilder->codeAppendf("\thalf xs = %s.x * %s.x;\n", coords2D, coords2D);
548 fragBuilder->codeAppendf("\thalf ys = %s.y * %s.y;\n", coords2D, coords2D);
549 fragBuilder->codeAppendf("\thalf d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000550
551 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
552 // If so we must also flip sign on sqrt
553 if (!fIsFlipped) {
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400554 fragBuilder->codeAppendf("\thalf %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -0800555 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000556 } else {
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400557 fragBuilder->codeAppendf("\thalf %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -0800558 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000559 }
560
egdaniel4ca2e602015-11-18 08:01:26 -0800561 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
562 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800563 this->emitColor(fragBuilder,
564 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500565 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800566 ge,
567 tName.c_str(),
568 args.fOutputColor,
569 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700570 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800571 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000572}
573
fmenozzi55d318d2016-08-09 08:05:57 -0700574void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400575 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700576 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700577 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000578 SkASSERT(data.isFlipped() == fIsFlipped);
579 SkScalar focal = data.focal();
580
581 if (fCachedFocal != focal) {
Mike Reed8be952a2017-02-13 20:44:33 -0500582 SkScalar oneMinus2F = 1.f - focal * focal;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000583
jvanverthde11ee42016-02-26 13:58:40 -0800584 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000585 fCachedFocal = focal;
586 }
587}
588
fmenozzi55d318d2016-08-09 08:05:57 -0700589void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
590 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500591 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700592 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700593 key[0] = GenBaseGradientKey(processor);
594 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000595}
596
597//////////////////////////////////////////////////////////////////////////////
598
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000599class FocalInside2PtConicalEffect : public GrGradientEffect {
600public:
fmenozzi55d318d2016-08-09 08:05:57 -0700601 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000602
Brian Salomonaff329b2017-08-11 09:40:37 -0400603 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
604 auto processor = std::unique_ptr<FocalInside2PtConicalEffect>(
605 new FocalInside2PtConicalEffect(args, focalX));
Brian Salomon6af27012017-06-09 08:21:42 -0400606 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000607 }
608
mtklein36352bf2015-03-25 18:17:31 -0700609 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800610 return "Two-Point Conical Gradient Focal Inside";
611 }
612
Brian Salomonaff329b2017-08-11 09:40:37 -0400613 std::unique_ptr<GrFragmentProcessor> clone() const override {
614 return std::unique_ptr<GrFragmentProcessor>(new FocalInside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -0400615 }
616
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000617 SkScalar focal() const { return fFocalX; }
618
fmenozzi55d318d2016-08-09 08:05:57 -0700619 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000620
621private:
egdaniel57d3b032015-11-13 11:57:27 -0800622 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700623
Brian Salomon94efbf52016-11-29 13:43:05 -0500624 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700625
mtklein36352bf2015-03-25 18:17:31 -0700626 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700627 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000628 return (INHERITED::onIsEqual(sBase) &&
629 this->fFocalX == s.fFocalX);
630 }
631
brianosman9557c272016-09-15 06:59:15 -0700632 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500633 : INHERITED(args, args.fShader->colorsAreOpaque()), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800634 this->initClassID<FocalInside2PtConicalEffect>();
635 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000636
Brian Salomonf8480b92017-07-27 15:45:59 -0400637 explicit FocalInside2PtConicalEffect(const FocalInside2PtConicalEffect& that)
638 : INHERITED(that), fFocalX(that.fFocalX) {
639 this->initClassID<FocalInside2PtConicalEffect>();
640 }
641
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400642 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000643
644 SkScalar fFocalX;
645
646 typedef GrGradientEffect INHERITED;
647};
648
fmenozzi55d318d2016-08-09 08:05:57 -0700649class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
650 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000651public:
fmenozzi55d318d2016-08-09 08:05:57 -0700652 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000653
wangyix7c157a92015-07-22 15:08:53 -0700654 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000655
Brian Salomon94efbf52016-11-29 13:43:05 -0500656 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000657
658protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400659 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700660
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000661 UniformHandle fFocalUni;
662
663 const char* fVSVaryingName;
664 const char* fFSVaryingName;
665
666 // @{
667 /// Values last uploaded as uniforms
668
669 SkScalar fCachedFocal;
670
671 // @}
672
673private:
fmenozzi55d318d2016-08-09 08:05:57 -0700674 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000675
676};
677
Brian Salomon94efbf52016-11-29 13:43:05 -0500678void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800679 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700680 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800681}
682
egdaniel57d3b032015-11-13 11:57:27 -0800683GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700684 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000685}
686
joshualittb0a8a372014-09-23 09:50:21 -0700687GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000688
joshualitt01258472014-09-22 10:29:30 -0700689/*
690 * All Two point conical gradient test create functions may occasionally create edge case shaders
691 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500692#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400693std::unique_ptr<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(
694 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700695 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000696 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000697 SkPoint center2;
698 SkScalar radius2;
699 do {
joshualitt0067ff52015-07-08 14:26:19 -0700700 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000701 // Below makes sure radius2 is larger enouch such that the focal point
702 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700703 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000704 SkPoint diff = center2 - center1;
705 SkScalar diffLen = diff.length();
706 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000707 // If the circles are identical the factory will give us an empty shader.
708 } while (radius1 == radius2 && center1 == center2);
709
Brian Osman3f748602016-10-03 18:29:03 -0400710 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400711 auto shader = params.fUseColors4f ?
712 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
713 params.fColors4f, params.fColorSpace, params.fStops,
714 params.fColorCount, params.fTileMode) :
715 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
716 params.fColors, params.fStops,
717 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400718 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400719 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700720 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700721 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000722}
Hal Canary6f6961e2017-01-31 13:50:44 -0500723#endif
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000724
fmenozzi55d318d2016-08-09 08:05:57 -0700725FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
726 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700727 : fVSVaryingName(nullptr)
728 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000729 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000730
fmenozzi55d318d2016-08-09 08:05:57 -0700731void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700732 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800733 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
734 this->emitUniforms(uniformHandler, ge);
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400735 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -0800736 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000737 SkString tName("t");
738
739 // this is the distance along x-axis from the end center to focal point in
740 // transformed coordinates
Brian Salomon99938a82016-11-21 13:41:08 -0500741 GrShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000742
Ethan Nicholas5af9ea32017-07-28 15:19:46 -0400743 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -0800744 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700745 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000746 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000747
748 // t = p.x * focalX + length(p)
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400749 fragBuilder->codeAppendf("\thalf %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800750 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000751
egdaniel7ea439b2015-12-03 09:20:44 -0800752 this->emitColor(fragBuilder,
753 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500754 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800755 ge,
756 tName.c_str(),
757 args.fOutputColor,
758 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700759 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000760}
761
fmenozzi55d318d2016-08-09 08:05:57 -0700762void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400763 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700764 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700765 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000766 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000767
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000768 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700769 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000770 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000771 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000772}
773
fmenozzi55d318d2016-08-09 08:05:57 -0700774void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
775 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500776 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700777 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000778}
779
780//////////////////////////////////////////////////////////////////////////////
781// Circle Conical Gradients
782//////////////////////////////////////////////////////////////////////////////
783
784struct CircleConicalInfo {
785 SkPoint fCenterEnd;
786 SkScalar fA;
787 SkScalar fB;
788 SkScalar fC;
789};
790
791// Returns focal distance along x-axis in transformed coords
792static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
793 SkMatrix* invLMatrix, CircleConicalInfo* info) {
794 // Inverse of the current local matrix is passed in then,
795 // translate and scale such that start circle is on the origin and has radius 1
796 const SkPoint& centerStart = shader.getStartCenter();
797 const SkPoint& centerEnd = shader.getEndCenter();
798 SkScalar radiusStart = shader.getStartRadius();
799 SkScalar radiusEnd = shader.getEndRadius();
800
801 SkMatrix matrix;
802
803 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
804
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000805 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000806 matrix.postScale(invStartRad, invStartRad);
807
808 radiusEnd /= radiusStart;
809
810 SkPoint centerEndTrans;
811 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
812
813 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
814 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
815
816 // Check to see if start circle is inside end circle with edges touching.
817 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700818 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
819 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
820 // still accurate.
821 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000822 return kEdge_ConicalType;
823 }
824
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000825 SkScalar C = 1.f / A;
826 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000827
828 matrix.postScale(C, C);
829
830 invLMatrix->postConcat(matrix);
831
832 info->fCenterEnd = centerEndTrans;
833 info->fA = A;
834 info->fB = B;
835 info->fC = C;
836
837 // 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 +0000838 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000839 return kInside_ConicalType;
840 }
841 return kOutside_ConicalType;
842}
843
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000844class CircleInside2PtConicalEffect : public GrGradientEffect {
845public:
fmenozzi55d318d2016-08-09 08:05:57 -0700846 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000847
Brian Salomonaff329b2017-08-11 09:40:37 -0400848 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args,
849 const CircleConicalInfo& info) {
850 auto processor = std::unique_ptr<CircleInside2PtConicalEffect>(
851 new CircleInside2PtConicalEffect(args, info));
Brian Salomon6af27012017-06-09 08:21:42 -0400852 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000853 }
854
mtklein36352bf2015-03-25 18:17:31 -0700855 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800856
Brian Salomonaff329b2017-08-11 09:40:37 -0400857 std::unique_ptr<GrFragmentProcessor> clone() const override {
858 return std::unique_ptr<GrFragmentProcessor>(new CircleInside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -0400859 }
860
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000861 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
862 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
863 SkScalar A() const { return fInfo.fA; }
864 SkScalar B() const { return fInfo.fB; }
865 SkScalar C() const { return fInfo.fC; }
866
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000867private:
egdaniel57d3b032015-11-13 11:57:27 -0800868 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700869
Brian Salomon94efbf52016-11-29 13:43:05 -0500870 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800871 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700872
mtklein36352bf2015-03-25 18:17:31 -0700873 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700874 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000875 return (INHERITED::onIsEqual(sBase) &&
876 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
877 this->fInfo.fA == s.fInfo.fA &&
878 this->fInfo.fB == s.fInfo.fB &&
879 this->fInfo.fC == s.fInfo.fC);
880 }
881
brianosman9557c272016-09-15 06:59:15 -0700882 CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -0500883 : INHERITED(args, args.fShader->colorsAreOpaque()), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800884 this->initClassID<CircleInside2PtConicalEffect>();
885 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000886
Brian Salomonf8480b92017-07-27 15:45:59 -0400887 explicit CircleInside2PtConicalEffect(const CircleInside2PtConicalEffect& that)
888 : INHERITED(that), fInfo(that.fInfo) {
889 this->initClassID<CircleInside2PtConicalEffect>();
890 }
891
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400892 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000893
894 const CircleConicalInfo fInfo;
895
896 typedef GrGradientEffect INHERITED;
897};
898
Brian Salomonf8480b92017-07-27 15:45:59 -0400899class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700900 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000901public:
fmenozzi55d318d2016-08-09 08:05:57 -0700902 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000903
wangyix7c157a92015-07-22 15:08:53 -0700904 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000905
Brian Salomon94efbf52016-11-29 13:43:05 -0500906 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000907
908protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400909 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700910
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000911 UniformHandle fCenterUni;
912 UniformHandle fParamUni;
913
914 const char* fVSVaryingName;
915 const char* fFSVaryingName;
916
917 // @{
918 /// Values last uploaded as uniforms
919
920 SkScalar fCachedCenterX;
921 SkScalar fCachedCenterY;
922 SkScalar fCachedA;
923 SkScalar fCachedB;
924 SkScalar fCachedC;
925
926 // @}
927
928private:
fmenozzi55d318d2016-08-09 08:05:57 -0700929 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000930
931};
932
Brian Salomon94efbf52016-11-29 13:43:05 -0500933void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800934 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700935 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800936}
937
egdaniel57d3b032015-11-13 11:57:27 -0800938GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700939 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000940}
941
joshualittb0a8a372014-09-23 09:50:21 -0700942GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000943
joshualitt01258472014-09-22 10:29:30 -0700944/*
945 * All Two point conical gradient test create functions may occasionally create edge case shaders
946 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500947#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -0400948std::unique_ptr<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(
949 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700950 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
951 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000952 SkPoint center2;
953 SkScalar radius2;
954 do {
joshualitt0067ff52015-07-08 14:26:19 -0700955 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000956 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700957 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000958 SkPoint diff = center2 - center1;
959 SkScalar diffLen = diff.length();
960 radius2 = radius1 + diffLen + increase;
961 // If the circles are identical the factory will give us an empty shader.
962 } while (radius1 == radius2 && center1 == center2);
963
Brian Osman3f748602016-10-03 18:29:03 -0400964 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400965 auto shader = params.fUseColors4f ?
966 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
967 params.fColors4f, params.fColorSpace, params.fStops,
968 params.fColorCount, params.fTileMode) :
969 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
970 params.fColors, params.fStops,
971 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400972 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -0400973 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700974 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700975 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000976}
Hal Canary6f6961e2017-01-31 13:50:44 -0500977#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000978
fmenozzi55d318d2016-08-09 08:05:57 -0700979CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
980 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700981 : fVSVaryingName(nullptr)
982 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000983 , fCachedCenterX(SK_ScalarMax)
984 , fCachedCenterY(SK_ScalarMax)
985 , fCachedA(SK_ScalarMax)
986 , fCachedB(SK_ScalarMax)
987 , fCachedC(SK_ScalarMax) {}
988
fmenozzi55d318d2016-08-09 08:05:57 -0700989void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700990 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800991 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
992 this->emitUniforms(uniformHandler, ge);
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400993 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -0800994 "Conical2FSCenter");
Ethan Nicholas88d99c62017-08-16 16:41:30 -0400995 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -0800996 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000997 SkString tName("t");
998
Brian Salomon99938a82016-11-21 13:41:08 -0500999 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001000 // params.x = A
1001 // params.y = B
1002 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001003 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001004
Ethan Nicholas5af9ea32017-07-28 15:19:46 -04001005 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -08001006 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001007 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001008 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001009
1010 // p = coords2D
1011 // e = center end
1012 // r = radius end
1013 // A = dot(e, e) - r^2 + 2 * r - 1
1014 // B = (r -1) / A
1015 // C = 1 / A
1016 // d = dot(e, p) + B
1017 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001018 fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
1019 fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -08001020 params.c_str());
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001021 fragBuilder->codeAppendf("\thalf %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
egdaniel4ca2e602015-11-18 08:01:26 -08001022 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001023
egdaniel7ea439b2015-12-03 09:20:44 -08001024 this->emitColor(fragBuilder,
1025 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001026 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001027 ge,
1028 tName.c_str(),
1029 args.fOutputColor,
1030 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001031 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001032}
1033
fmenozzi55d318d2016-08-09 08:05:57 -07001034void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001035 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001036 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001037 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001038 SkScalar centerX = data.centerX();
1039 SkScalar centerY = data.centerY();
1040 SkScalar A = data.A();
1041 SkScalar B = data.B();
1042 SkScalar C = data.C();
1043
1044 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1045 fCachedA != A || fCachedB != B || fCachedC != C) {
1046
kkinnunen7510b222014-07-30 00:04:16 -07001047 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1048 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001049
1050 fCachedCenterX = centerX;
1051 fCachedCenterY = centerY;
1052 fCachedA = A;
1053 fCachedB = B;
1054 fCachedC = C;
1055 }
1056}
1057
fmenozzi55d318d2016-08-09 08:05:57 -07001058void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1059 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001060 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001061 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001062}
1063
1064//////////////////////////////////////////////////////////////////////////////
1065
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001066class CircleOutside2PtConicalEffect : public GrGradientEffect {
1067public:
fmenozzi55d318d2016-08-09 08:05:57 -07001068 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001069
Brian Salomonaff329b2017-08-11 09:40:37 -04001070 static std::unique_ptr<GrFragmentProcessor> Make(const CreateArgs& args,
1071 const CircleConicalInfo& info) {
1072 return std::unique_ptr<GrFragmentProcessor>(new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001073 }
1074
mtklein36352bf2015-03-25 18:17:31 -07001075 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001076
Brian Salomonaff329b2017-08-11 09:40:37 -04001077 std::unique_ptr<GrFragmentProcessor> clone() const override {
1078 return std::unique_ptr<GrFragmentProcessor>(new CircleOutside2PtConicalEffect(*this));
Brian Salomonf8480b92017-07-27 15:45:59 -04001079 }
1080
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001081 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1082 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1083 SkScalar A() const { return fInfo.fA; }
1084 SkScalar B() const { return fInfo.fB; }
1085 SkScalar C() const { return fInfo.fC; }
1086 SkScalar tLimit() const { return fTLimit; }
1087 bool isFlipped() const { return fIsFlipped; }
1088
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001089private:
egdaniel57d3b032015-11-13 11:57:27 -08001090 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001091
Brian Salomon94efbf52016-11-29 13:43:05 -05001092 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001093
mtklein36352bf2015-03-25 18:17:31 -07001094 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001095 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001096 return (INHERITED::onIsEqual(sBase) &&
1097 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1098 this->fInfo.fA == s.fInfo.fA &&
1099 this->fInfo.fB == s.fInfo.fB &&
1100 this->fInfo.fC == s.fInfo.fC &&
1101 this->fTLimit == s.fTLimit &&
1102 this->fIsFlipped == s.fIsFlipped);
1103 }
1104
brianosman9557c272016-09-15 06:59:15 -07001105 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -05001106 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
1107 , fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001108 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001109 const SkTwoPointConicalGradient& shader =
1110 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001111 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001112 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001113 } else {
1114 fTLimit = SK_ScalarMin;
1115 }
1116
1117 fIsFlipped = shader.isFlippedGrad();
1118 }
1119
Brian Salomonf8480b92017-07-27 15:45:59 -04001120 explicit CircleOutside2PtConicalEffect(const CircleOutside2PtConicalEffect& that)
1121 : INHERITED(that)
1122 , fInfo(that.fInfo)
1123 , fTLimit(that.fTLimit)
1124 , fIsFlipped(that.fIsFlipped) {
1125 this->initClassID<CircleOutside2PtConicalEffect>();
1126 }
1127
Brian Salomon0c26a9d2017-07-06 10:09:38 -04001128 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001129
1130 const CircleConicalInfo fInfo;
1131 SkScalar fTLimit;
1132 bool fIsFlipped;
1133
1134 typedef GrGradientEffect INHERITED;
1135};
1136
fmenozzi55d318d2016-08-09 08:05:57 -07001137class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1138 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001139public:
fmenozzi55d318d2016-08-09 08:05:57 -07001140 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001141
wangyix7c157a92015-07-22 15:08:53 -07001142 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001143
Brian Salomon94efbf52016-11-29 13:43:05 -05001144 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001145
1146protected:
Brian Salomonab015ef2017-04-04 10:15:51 -04001147 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001148
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001149 UniformHandle fCenterUni;
1150 UniformHandle fParamUni;
1151
1152 const char* fVSVaryingName;
1153 const char* fFSVaryingName;
1154
1155 bool fIsFlipped;
1156
1157 // @{
1158 /// Values last uploaded as uniforms
1159
1160 SkScalar fCachedCenterX;
1161 SkScalar fCachedCenterY;
1162 SkScalar fCachedA;
1163 SkScalar fCachedB;
1164 SkScalar fCachedC;
1165 SkScalar fCachedTLimit;
1166
1167 // @}
1168
1169private:
fmenozzi55d318d2016-08-09 08:05:57 -07001170 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001171
1172};
1173
Brian Salomon94efbf52016-11-29 13:43:05 -05001174void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -08001175 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001176 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001177}
1178
egdaniel57d3b032015-11-13 11:57:27 -08001179GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001180 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001181}
1182
joshualittb0a8a372014-09-23 09:50:21 -07001183GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001184
joshualitt01258472014-09-22 10:29:30 -07001185/*
1186 * All Two point conical gradient test create functions may occasionally create edge case shaders
1187 */
Hal Canary6f6961e2017-01-31 13:50:44 -05001188#if GR_TEST_UTILS
Brian Salomonaff329b2017-08-11 09:40:37 -04001189std::unique_ptr<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(
1190 GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001191 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1192 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001193 SkPoint center2;
1194 SkScalar radius2;
1195 SkScalar diffLen;
1196 do {
joshualitt0067ff52015-07-08 14:26:19 -07001197 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001198 // If the circles share a center than we can't be in the outside case
1199 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001200 SkPoint diff = center2 - center1;
1201 diffLen = diff.length();
1202 // Below makes sure that circle one is not contained within circle two
1203 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001204 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001205
Brian Osman3f748602016-10-03 18:29:03 -04001206 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -04001207 auto shader = params.fUseColors4f ?
1208 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1209 params.fColors4f, params.fColorSpace, params.fStops,
1210 params.fColorCount, params.fTileMode) :
1211 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1212 params.fColors, params.fStops,
1213 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -04001214 GrTest::TestAsFPArgs asFPArgs(d);
Brian Salomonaff329b2017-08-11 09:40:37 -04001215 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -07001216 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001217 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001218}
Hal Canary6f6961e2017-01-31 13:50:44 -05001219#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001220
fmenozzi55d318d2016-08-09 08:05:57 -07001221CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1222 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001223 : fVSVaryingName(nullptr)
1224 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001225 , fCachedCenterX(SK_ScalarMax)
1226 , fCachedCenterY(SK_ScalarMax)
1227 , fCachedA(SK_ScalarMax)
1228 , fCachedB(SK_ScalarMax)
1229 , fCachedC(SK_ScalarMax)
1230 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001231 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001232 fIsFlipped = data.isFlipped();
1233 }
1234
fmenozzi55d318d2016-08-09 08:05:57 -07001235void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001236 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001237 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1238 this->emitUniforms(uniformHandler, ge);
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001239 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf2_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -08001240 "Conical2FSCenter");
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001241 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf4_GrSLType,
egdaniel7ea439b2015-12-03 09:20:44 -08001242 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001243 SkString tName("t");
1244
Brian Salomon99938a82016-11-21 13:41:08 -05001245 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001246 // params.x = A
1247 // params.y = B
1248 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001249 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001250
Ethan Nicholas5af9ea32017-07-28 15:19:46 -04001251 // if we have a float3 from being in perspective, convert it to a float2 first
cdalton85285412016-02-18 12:37:07 -08001252 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001253 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001254 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001255
1256 // output will default to transparent black (we simply won't write anything
1257 // else to it if invalid, instead of discarding or returning prematurely)
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001258 fragBuilder->codeAppendf("\t%s = half4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001259
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001260 // p = coords2D
1261 // e = center end
1262 // r = radius end
1263 // A = dot(e, e) - r^2 + 2 * r - 1
1264 // B = (r -1) / A
1265 // C = 1 / A
1266 // d = dot(e, p) + B
1267 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001268
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001269 fragBuilder->codeAppendf("\thalf pDotp = dot(%s, %s);\n", coords2D, coords2D);
1270 fragBuilder->codeAppendf("\thalf d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -08001271 params.c_str());
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001272 fragBuilder->codeAppendf("\thalf deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
egdaniel4ca2e602015-11-18 08:01:26 -08001273 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001274
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001275 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1276 // If so we must also flip sign on sqrt
1277 if (!fIsFlipped) {
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001278 fragBuilder->codeAppendf("\thalf %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001279 } else {
Ethan Nicholas88d99c62017-08-16 16:41:30 -04001280 fragBuilder->codeAppendf("\thalf %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001281 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001282
egdaniel7ea439b2015-12-03 09:20:44 -08001283 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1284 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001285 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001286 this->emitColor(fragBuilder,
1287 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001288 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001289 ge,
1290 tName.c_str(),
1291 args.fOutputColor,
1292 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001293 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001294 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001295}
1296
fmenozzi55d318d2016-08-09 08:05:57 -07001297void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001298 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001299 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001300 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001301 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001302 SkScalar centerX = data.centerX();
1303 SkScalar centerY = data.centerY();
1304 SkScalar A = data.A();
1305 SkScalar B = data.B();
1306 SkScalar C = data.C();
1307 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001308
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001309 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1310 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001311
kkinnunen7510b222014-07-30 00:04:16 -07001312 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1313 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001314 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001315
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001316 fCachedCenterX = centerX;
1317 fCachedCenterY = centerY;
1318 fCachedA = A;
1319 fCachedB = B;
1320 fCachedC = C;
1321 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001322 }
1323}
1324
fmenozzi55d318d2016-08-09 08:05:57 -07001325void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1326 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001327 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001328 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001329 key[0] = GenBaseGradientKey(processor);
1330 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001331}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001332
1333//////////////////////////////////////////////////////////////////////////////
1334
Brian Salomonaff329b2017-08-11 09:40:37 -04001335std::unique_ptr<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1336 const GrGradientEffect::CreateArgs& args) {
brianosman9557c272016-09-15 06:59:15 -07001337 const SkTwoPointConicalGradient& shader =
1338 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1339
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001340 SkMatrix matrix;
1341 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001342 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001343 }
brianosman9557c272016-09-15 06:59:15 -07001344 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001345 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001346 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001347 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001348 }
1349 matrix.postConcat(inv);
1350 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001351
brianosmanb9c51372016-09-15 11:09:45 -07001352 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1353 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001354
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001355 if (shader.getStartRadius() < kErrorTol) {
1356 SkScalar focalX;
1357 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1358 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001359 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001360 } else if(type == kEdge_ConicalType) {
1361 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001362 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001363 } else {
brianosman9557c272016-09-15 06:59:15 -07001364 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001365 }
1366 }
1367
1368 CircleConicalInfo info;
1369 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1370
1371 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001372 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001373 } else if (type == kEdge_ConicalType) {
1374 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001375 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001376 } else {
brianosman9557c272016-09-15 06:59:15 -07001377 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001378 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001379}
1380
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001381#endif