blob: 1e3404cdd66969d83d65241f7d58105f937816f2 [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
brianosman9557c272016-09-15 06:59:15 -070064 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args) {
Brian Salomon6af27012017-06-09 08:21:42 -040065 auto processor = sk_sp<Edge2PtConicalEffect>(new Edge2PtConicalEffect(args));
66 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000067 }
68
Brian Salomond3b65972017-03-22 12:05:03 -040069 ~Edge2PtConicalEffect() override {}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000070
mtklein36352bf2015-03-25 18:17:31 -070071 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -080072 return "Two-Point Conical Gradient Edge Touching";
73 }
74
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000075 // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000076 SkScalar center() const { return fCenterX1; }
77 SkScalar diffRadius() const { return fDiffRadius; }
78 SkScalar radius() const { return fRadius0; }
79
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000080private:
egdaniel57d3b032015-11-13 11:57:27 -080081 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070082
Brian Salomon94efbf52016-11-29 13:43:05 -050083 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070084
mtklein36352bf2015-03-25 18:17:31 -070085 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -070086 const Edge2PtConicalEffect& s = sBase.cast<Edge2PtConicalEffect>();
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000087 return (INHERITED::onIsEqual(sBase) &&
88 this->fCenterX1 == s.fCenterX1 &&
89 this->fRadius0 == s.fRadius0 &&
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000090 this->fDiffRadius == s.fDiffRadius);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000091 }
92
brianosman9557c272016-09-15 06:59:15 -070093 Edge2PtConicalEffect(const CreateArgs& args)
Brian Salomon587e08f2017-01-27 10:59:27 -050094 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */) {
brianosman9557c272016-09-15 06:59:15 -070095 const SkTwoPointConicalGradient& shader =
96 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
97 fCenterX1 = shader.getCenterX1();
98 fRadius0 = shader.getStartRadius();
99 fDiffRadius = shader.getDiffRadius();
joshualitteb2a6762014-12-04 11:35:33 -0800100 this->initClassID<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000101 // We should only be calling this shader if we are degenerate case with touching circles
egdaniel8405ef92014-06-09 11:57:28 -0700102 // When deciding if we are in edge case, we scaled by the end radius for cases when the
joshualitt01258472014-09-22 10:29:30 -0700103 // start radius was close to zero, otherwise we scaled by the start radius. In addition
104 // Our test for the edge case in set_matrix_circle_conical has a higher tolerance so we
105 // need the sqrt value below
106 SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - fCenterX1) <
107 (fRadius0 < kErrorTol ? shader.getEndRadius() * kEdgeErrorTol :
108 fRadius0 * sqrt(kEdgeErrorTol)));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000109
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000110 // We pass the linear part of the quadratic as a varying.
111 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
112 fBTransform = this->getCoordTransform();
113 SkMatrix& bMatrix = *fBTransform.accessMatrix();
Mike Reed8be952a2017-02-13 20:44:33 -0500114 SkScalar r0dr = fRadius0 * fDiffRadius;
115 bMatrix[SkMatrix::kMScaleX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMScaleX] +
116 r0dr * bMatrix[SkMatrix::kMPersp0]);
117 bMatrix[SkMatrix::kMSkewX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMSkewX] +
118 r0dr * bMatrix[SkMatrix::kMPersp1]);
119 bMatrix[SkMatrix::kMTransX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMTransX] +
120 r0dr * bMatrix[SkMatrix::kMPersp2]);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000121 this->addCoordTransform(&fBTransform);
122 }
123
joshualittb0a8a372014-09-23 09:50:21 -0700124 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000125
126 // @{
127 // Cache of values - these can change arbitrarily, EXCEPT
128 // we shouldn't change between degenerate and non-degenerate?!
129
130 GrCoordTransform fBTransform;
131 SkScalar fCenterX1;
132 SkScalar fRadius0;
133 SkScalar fDiffRadius;
134
135 // @}
136
137 typedef GrGradientEffect INHERITED;
138};
139
fmenozzi55d318d2016-08-09 08:05:57 -0700140class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000141public:
fmenozzi55d318d2016-08-09 08:05:57 -0700142 GLSLEdge2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400143 ~GLSLEdge2PtConicalProcessor() override {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000144
wangyix7c157a92015-07-22 15:08:53 -0700145 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000146
Brian Salomon94efbf52016-11-29 13:43:05 -0500147 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000148
149protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400150 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700151
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000152 UniformHandle fParamUni;
153
154 const char* fVSVaryingName;
155 const char* fFSVaryingName;
156
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000157 // @{
158 /// Values last uploaded as uniforms
159
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000160 SkScalar fCachedRadius;
161 SkScalar fCachedDiffRadius;
162
163 // @}
164
165private:
fmenozzi55d318d2016-08-09 08:05:57 -0700166 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000167
168};
169
Brian Salomon94efbf52016-11-29 13:43:05 -0500170void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800171 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700172 Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800173}
174
egdaniel57d3b032015-11-13 11:57:27 -0800175GrGLSLFragmentProcessor* Edge2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700176 return new Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor(*this);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000177}
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000178
joshualittb0a8a372014-09-23 09:50:21 -0700179GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Edge2PtConicalEffect);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000180
joshualitt01258472014-09-22 10:29:30 -0700181/*
182 * All Two point conical gradient test create functions may occasionally create edge case shaders
183 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500184#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700185sk_sp<GrFragmentProcessor> Edge2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700186 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
187 SkScalar radius1 = d->fRandom->nextUScalar1();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000188 SkPoint center2;
189 SkScalar radius2;
190 do {
joshualitt0067ff52015-07-08 14:26:19 -0700191 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000192 // If the circles are identical the factory will give us an empty shader.
193 // This will happen if we pick identical centers
194 } while (center1 == center2);
195
196 // Below makes sure that circle one is contained within circle two
197 // and both circles are touching on an edge
198 SkPoint diff = center2 - center1;
199 SkScalar diffLen = diff.length();
200 radius2 = radius1 + diffLen;
201
Brian Osman3f748602016-10-03 18:29:03 -0400202 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400203 auto shader = params.fUseColors4f ?
204 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
205 params.fColors4f, params.fColorSpace, params.fStops,
206 params.fColorCount, params.fTileMode) :
207 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
208 params.fColors, params.fStops,
209 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400210 GrTest::TestAsFPArgs asFPArgs(d);
Florin Malita4aed1382017-05-25 10:38:07 -0400211 sk_sp<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700212 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700213 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000214}
Hal Canary6f6961e2017-01-31 13:50:44 -0500215#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000216
fmenozzi55d318d2016-08-09 08:05:57 -0700217Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GLSLEdge2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700218 : fVSVaryingName(nullptr)
219 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000220 , fCachedRadius(-SK_ScalarMax)
221 , fCachedDiffRadius(-SK_ScalarMax) {}
222
fmenozzi55d318d2016-08-09 08:05:57 -0700223void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700224 const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800225 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
226 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800227 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
228 kVec3f_GrSLType, kDefault_GrSLPrecision,
229 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000230
231 SkString cName("c");
232 SkString tName("t");
233 SkString p0; // start radius
234 SkString p1; // start radius squared
235 SkString p2; // difference in radii (r1 - r0)
236
jvanverthde11ee42016-02-26 13:58:40 -0800237
238 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
239 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
240 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000241
242 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700243 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000244 const char* coords2D;
245 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800246 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700247 if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
egdaniel4ca2e602015-11-18 08:01:26 -0800248 fragBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700249 args.fTransformedCoords[0].c_str(),
250 args.fTransformedCoords[0].c_str(),
251 args.fTransformedCoords[1].c_str(),
252 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000253 coords2D = "interpolants.xy";
254 bVar = "interpolants.z";
255 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700256 coords2D = args.fTransformedCoords[0].c_str();
257 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000258 }
259
260 // output will default to transparent black (we simply won't write anything
261 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800262 fragBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000263
264 // c = (x^2)+(y^2) - params[1]
egdaniel4ca2e602015-11-18 08:01:26 -0800265 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000266 cName.c_str(), coords2D, coords2D, p1.c_str());
267
268 // linear case: t = -c/b
egdaniel4ca2e602015-11-18 08:01:26 -0800269 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000270 cName.c_str(), bVar.c_str());
271
272 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800273 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000274 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800275 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800276 this->emitColor(fragBuilder,
277 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500278 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800279 ge,
280 tName.c_str(),
281 args.fOutputColor,
282 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700283 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800284 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000285}
286
fmenozzi55d318d2016-08-09 08:05:57 -0700287void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400288 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700289 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700290 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000291 SkScalar radius0 = data.radius();
292 SkScalar diffRadius = data.diffRadius();
293
294 if (fCachedRadius != radius0 ||
295 fCachedDiffRadius != diffRadius) {
296
Mike Reed8be952a2017-02-13 20:44:33 -0500297 pdman.set3f(fParamUni, radius0, radius0 * radius0, diffRadius);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000298 fCachedRadius = radius0;
299 fCachedDiffRadius = diffRadius;
300 }
301}
302
fmenozzi55d318d2016-08-09 08:05:57 -0700303void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500304 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700305 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000306}
307
308//////////////////////////////////////////////////////////////////////////////
309// Focal Conical Gradients
310//////////////////////////////////////////////////////////////////////////////
311
312static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
313 SkMatrix* invLMatrix, SkScalar* focalX) {
314 // Inverse of the current local matrix is passed in then,
315 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
316 // and focal point is at the origin.
317 ConicalType conicalType;
318 const SkPoint& focal = shader.getStartCenter();
319 const SkPoint& centerEnd = shader.getEndCenter();
320 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000321 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000322
323 SkMatrix matrix;
324
325 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
326 matrix.postScale(invRadius, invRadius);
327
328 SkPoint focalTrans;
329 matrix.mapPoints(&focalTrans, &focal, 1);
330 *focalX = focalTrans.length();
331
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000332 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000333 SkScalar invFocalX = SkScalarInvert(*focalX);
334 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -0500335 rot.setSinCos(-invFocalX * focalTrans.fY, invFocalX * focalTrans.fX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000336 matrix.postConcat(rot);
337 }
338
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000339 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000340
341 // If the focal point is touching the edge of the circle it will
342 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700343 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
344 // stability trade off versus the linear approx used in the Edge Shader
345 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000346 return kEdge_ConicalType;
347 }
348
349 // Scale factor 1 / (1 - focalX * focalX)
Mike Reed8be952a2017-02-13 20:44:33 -0500350 SkScalar oneMinusF2 = 1.f - *focalX * *focalX;
reed80ea19c2015-05-12 10:37:34 -0700351 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000352
353
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000354 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000355 conicalType = kInside_ConicalType;
356 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
357 } else {
358 conicalType = kOutside_ConicalType;
359 matrix.postScale(s, s);
360 }
361
362 invLMatrix->postConcat(matrix);
363
364 return conicalType;
365}
366
367//////////////////////////////////////////////////////////////////////////////
368
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000369class FocalOutside2PtConicalEffect : public GrGradientEffect {
370public:
fmenozzi55d318d2016-08-09 08:05:57 -0700371 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000372
brianosman9557c272016-09-15 06:59:15 -0700373 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
Brian Salomon6af27012017-06-09 08:21:42 -0400374 auto processor =
375 sk_sp<FocalOutside2PtConicalEffect>(new FocalOutside2PtConicalEffect(args, focalX));
376 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000377 }
378
Brian Salomond3b65972017-03-22 12:05:03 -0400379 ~FocalOutside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000380
mtklein36352bf2015-03-25 18:17:31 -0700381 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800382 return "Two-Point Conical Gradient Focal Outside";
383 }
384
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000385 bool isFlipped() const { return fIsFlipped; }
386 SkScalar focal() const { return fFocalX; }
387
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000388private:
egdaniel57d3b032015-11-13 11:57:27 -0800389 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700390
Brian Salomon94efbf52016-11-29 13:43:05 -0500391 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700392
mtklein36352bf2015-03-25 18:17:31 -0700393 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700394 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000395 return (INHERITED::onIsEqual(sBase) &&
396 this->fFocalX == s.fFocalX &&
397 this->fIsFlipped == s.fIsFlipped);
398 }
399
Brian Salomon587e08f2017-01-27 10:59:27 -0500400 static bool IsFlipped(const CreateArgs& args) {
401 // eww.
402 return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
403 }
404
brianosman9557c272016-09-15 06:59:15 -0700405 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500406 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
407 , fFocalX(focalX)
408 , fIsFlipped(IsFlipped(args)) {
joshualitteb2a6762014-12-04 11:35:33 -0800409 this->initClassID<FocalOutside2PtConicalEffect>();
410 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000411
joshualittb0a8a372014-09-23 09:50:21 -0700412 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000413
414 SkScalar fFocalX;
415 bool fIsFlipped;
416
417 typedef GrGradientEffect INHERITED;
418};
419
Brian Salomon587e08f2017-01-27 10:59:27 -0500420class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700421 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000422public:
fmenozzi55d318d2016-08-09 08:05:57 -0700423 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400424 ~GLSLFocalOutside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000425
wangyix7c157a92015-07-22 15:08:53 -0700426 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000427
Brian Salomon94efbf52016-11-29 13:43:05 -0500428 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000429
430protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400431 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700432
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000433 UniformHandle fParamUni;
434
435 const char* fVSVaryingName;
436 const char* fFSVaryingName;
437
438 bool fIsFlipped;
439
440 // @{
441 /// Values last uploaded as uniforms
442
443 SkScalar fCachedFocal;
444
445 // @}
446
447private:
fmenozzi55d318d2016-08-09 08:05:57 -0700448 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000449
450};
451
Brian Salomon94efbf52016-11-29 13:43:05 -0500452void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800453 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700454 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800455}
456
egdaniel57d3b032015-11-13 11:57:27 -0800457GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700458 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000459}
460
joshualittb0a8a372014-09-23 09:50:21 -0700461GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000462
joshualitt01258472014-09-22 10:29:30 -0700463/*
464 * All Two point conical gradient test create functions may occasionally create edge case shaders
465 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500466#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700467sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700468 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000469 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000470 SkPoint center2;
471 SkScalar radius2;
472 do {
joshualitt0067ff52015-07-08 14:26:19 -0700473 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000474 // 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 +0000475 } while (center1 == center2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000476
Brian Osman3f748602016-10-03 18:29:03 -0400477 SkPoint diff = center2 - center1;
478 SkScalar diffLen = diff.length();
479 // Below makes sure that the focal point is not contained within circle two
480 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
481
482 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400483 auto shader = params.fUseColors4f ?
484 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
485 params.fColors4f, params.fColorSpace, params.fStops,
486 params.fColorCount, params.fTileMode) :
487 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
488 params.fColors, params.fStops,
489 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400490 GrTest::TestAsFPArgs asFPArgs(d);
Florin Malita4aed1382017-05-25 10:38:07 -0400491 sk_sp<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700492 GrAlwaysAssert(fp);
493 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000494}
Hal Canary6f6961e2017-01-31 13:50:44 -0500495#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000496
fmenozzi55d318d2016-08-09 08:05:57 -0700497FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
498 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700499 : fVSVaryingName(nullptr)
500 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000501 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700502 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000503 fIsFlipped = data.isFlipped();
504}
505
fmenozzi55d318d2016-08-09 08:05:57 -0700506void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700507 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800508 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
509 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800510 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
511 kVec2f_GrSLType, kDefault_GrSLPrecision,
512 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000513 SkString tName("t");
514 SkString p0; // focalX
515 SkString p1; // 1 - focalX * focalX
516
jvanverthde11ee42016-02-26 13:58:40 -0800517 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
518 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000519
520 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800521 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700522 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000523 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000524
525 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
526
527 // output will default to transparent black (we simply won't write anything
528 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800529 fragBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000530
egdaniel4ca2e602015-11-18 08:01:26 -0800531 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
532 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
533 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000534
535 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
536 // If so we must also flip sign on sqrt
537 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -0800538 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
539 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000540 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800541 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
542 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000543 }
544
egdaniel4ca2e602015-11-18 08:01:26 -0800545 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
546 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800547 this->emitColor(fragBuilder,
548 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500549 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800550 ge,
551 tName.c_str(),
552 args.fOutputColor,
553 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700554 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800555 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000556}
557
fmenozzi55d318d2016-08-09 08:05:57 -0700558void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400559 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700560 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700561 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000562 SkASSERT(data.isFlipped() == fIsFlipped);
563 SkScalar focal = data.focal();
564
565 if (fCachedFocal != focal) {
Mike Reed8be952a2017-02-13 20:44:33 -0500566 SkScalar oneMinus2F = 1.f - focal * focal;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000567
jvanverthde11ee42016-02-26 13:58:40 -0800568 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000569 fCachedFocal = focal;
570 }
571}
572
fmenozzi55d318d2016-08-09 08:05:57 -0700573void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
574 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500575 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700576 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700577 key[0] = GenBaseGradientKey(processor);
578 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000579}
580
581//////////////////////////////////////////////////////////////////////////////
582
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000583class FocalInside2PtConicalEffect : public GrGradientEffect {
584public:
fmenozzi55d318d2016-08-09 08:05:57 -0700585 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000586
brianosman9557c272016-09-15 06:59:15 -0700587 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
Brian Salomon6af27012017-06-09 08:21:42 -0400588 auto processor =
589 sk_sp<FocalInside2PtConicalEffect>(new FocalInside2PtConicalEffect(args, focalX));
590 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000591 }
592
Brian Salomond3b65972017-03-22 12:05:03 -0400593 ~FocalInside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000594
mtklein36352bf2015-03-25 18:17:31 -0700595 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800596 return "Two-Point Conical Gradient Focal Inside";
597 }
598
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000599 SkScalar focal() const { return fFocalX; }
600
fmenozzi55d318d2016-08-09 08:05:57 -0700601 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000602
603private:
egdaniel57d3b032015-11-13 11:57:27 -0800604 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700605
Brian Salomon94efbf52016-11-29 13:43:05 -0500606 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700607
mtklein36352bf2015-03-25 18:17:31 -0700608 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700609 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000610 return (INHERITED::onIsEqual(sBase) &&
611 this->fFocalX == s.fFocalX);
612 }
613
brianosman9557c272016-09-15 06:59:15 -0700614 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500615 : INHERITED(args, args.fShader->colorsAreOpaque()), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800616 this->initClassID<FocalInside2PtConicalEffect>();
617 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000618
joshualittb0a8a372014-09-23 09:50:21 -0700619 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000620
621 SkScalar fFocalX;
622
623 typedef GrGradientEffect INHERITED;
624};
625
fmenozzi55d318d2016-08-09 08:05:57 -0700626class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
627 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000628public:
fmenozzi55d318d2016-08-09 08:05:57 -0700629 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400630 ~GLSLFocalInside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000631
wangyix7c157a92015-07-22 15:08:53 -0700632 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000633
Brian Salomon94efbf52016-11-29 13:43:05 -0500634 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000635
636protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400637 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700638
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000639 UniformHandle fFocalUni;
640
641 const char* fVSVaryingName;
642 const char* fFSVaryingName;
643
644 // @{
645 /// Values last uploaded as uniforms
646
647 SkScalar fCachedFocal;
648
649 // @}
650
651private:
fmenozzi55d318d2016-08-09 08:05:57 -0700652 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000653
654};
655
Brian Salomon94efbf52016-11-29 13:43:05 -0500656void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800657 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700658 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800659}
660
egdaniel57d3b032015-11-13 11:57:27 -0800661GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700662 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000663}
664
joshualittb0a8a372014-09-23 09:50:21 -0700665GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000666
joshualitt01258472014-09-22 10:29:30 -0700667/*
668 * All Two point conical gradient test create functions may occasionally create edge case shaders
669 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500670#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700671sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700672 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000673 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000674 SkPoint center2;
675 SkScalar radius2;
676 do {
joshualitt0067ff52015-07-08 14:26:19 -0700677 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000678 // Below makes sure radius2 is larger enouch such that the focal point
679 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700680 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000681 SkPoint diff = center2 - center1;
682 SkScalar diffLen = diff.length();
683 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000684 // If the circles are identical the factory will give us an empty shader.
685 } while (radius1 == radius2 && center1 == center2);
686
Brian Osman3f748602016-10-03 18:29:03 -0400687 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400688 auto shader = params.fUseColors4f ?
689 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
690 params.fColors4f, params.fColorSpace, params.fStops,
691 params.fColorCount, params.fTileMode) :
692 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
693 params.fColors, params.fStops,
694 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400695 GrTest::TestAsFPArgs asFPArgs(d);
Florin Malita4aed1382017-05-25 10:38:07 -0400696 sk_sp<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700697 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700698 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000699}
Hal Canary6f6961e2017-01-31 13:50:44 -0500700#endif
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000701
fmenozzi55d318d2016-08-09 08:05:57 -0700702FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
703 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700704 : fVSVaryingName(nullptr)
705 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000706 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000707
fmenozzi55d318d2016-08-09 08:05:57 -0700708void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700709 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800710 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
711 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800712 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800713 kFloat_GrSLType, kDefault_GrSLPrecision,
714 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000715 SkString tName("t");
716
717 // this is the distance along x-axis from the end center to focal point in
718 // transformed coordinates
Brian Salomon99938a82016-11-21 13:41:08 -0500719 GrShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000720
721 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800722 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700723 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000724 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000725
726 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800727 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800728 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000729
egdaniel7ea439b2015-12-03 09:20:44 -0800730 this->emitColor(fragBuilder,
731 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500732 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800733 ge,
734 tName.c_str(),
735 args.fOutputColor,
736 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700737 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000738}
739
fmenozzi55d318d2016-08-09 08:05:57 -0700740void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400741 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700742 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700743 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000744 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000745
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000746 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700747 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000748 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000749 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000750}
751
fmenozzi55d318d2016-08-09 08:05:57 -0700752void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
753 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500754 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700755 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000756}
757
758//////////////////////////////////////////////////////////////////////////////
759// Circle Conical Gradients
760//////////////////////////////////////////////////////////////////////////////
761
762struct CircleConicalInfo {
763 SkPoint fCenterEnd;
764 SkScalar fA;
765 SkScalar fB;
766 SkScalar fC;
767};
768
769// Returns focal distance along x-axis in transformed coords
770static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
771 SkMatrix* invLMatrix, CircleConicalInfo* info) {
772 // Inverse of the current local matrix is passed in then,
773 // translate and scale such that start circle is on the origin and has radius 1
774 const SkPoint& centerStart = shader.getStartCenter();
775 const SkPoint& centerEnd = shader.getEndCenter();
776 SkScalar radiusStart = shader.getStartRadius();
777 SkScalar radiusEnd = shader.getEndRadius();
778
779 SkMatrix matrix;
780
781 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
782
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000783 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000784 matrix.postScale(invStartRad, invStartRad);
785
786 radiusEnd /= radiusStart;
787
788 SkPoint centerEndTrans;
789 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
790
791 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
792 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
793
794 // Check to see if start circle is inside end circle with edges touching.
795 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700796 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
797 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
798 // still accurate.
799 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000800 return kEdge_ConicalType;
801 }
802
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000803 SkScalar C = 1.f / A;
804 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000805
806 matrix.postScale(C, C);
807
808 invLMatrix->postConcat(matrix);
809
810 info->fCenterEnd = centerEndTrans;
811 info->fA = A;
812 info->fB = B;
813 info->fC = C;
814
815 // 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 +0000816 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000817 return kInside_ConicalType;
818 }
819 return kOutside_ConicalType;
820}
821
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000822class CircleInside2PtConicalEffect : public GrGradientEffect {
823public:
fmenozzi55d318d2016-08-09 08:05:57 -0700824 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000825
brianosman9557c272016-09-15 06:59:15 -0700826 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
Brian Salomon6af27012017-06-09 08:21:42 -0400827 auto processor =
828 sk_sp<CircleInside2PtConicalEffect>(new CircleInside2PtConicalEffect(args, info));
829 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000830 }
831
Brian Salomond3b65972017-03-22 12:05:03 -0400832 ~CircleInside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000833
mtklein36352bf2015-03-25 18:17:31 -0700834 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800835
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000836 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
837 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
838 SkScalar A() const { return fInfo.fA; }
839 SkScalar B() const { return fInfo.fB; }
840 SkScalar C() const { return fInfo.fC; }
841
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000842private:
egdaniel57d3b032015-11-13 11:57:27 -0800843 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700844
Brian Salomon94efbf52016-11-29 13:43:05 -0500845 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800846 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700847
mtklein36352bf2015-03-25 18:17:31 -0700848 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700849 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000850 return (INHERITED::onIsEqual(sBase) &&
851 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
852 this->fInfo.fA == s.fInfo.fA &&
853 this->fInfo.fB == s.fInfo.fB &&
854 this->fInfo.fC == s.fInfo.fC);
855 }
856
brianosman9557c272016-09-15 06:59:15 -0700857 CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -0500858 : INHERITED(args, args.fShader->colorsAreOpaque()), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800859 this->initClassID<CircleInside2PtConicalEffect>();
860 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000861
joshualittb0a8a372014-09-23 09:50:21 -0700862 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000863
864 const CircleConicalInfo fInfo;
865
866 typedef GrGradientEffect INHERITED;
867};
868
fmenozzi55d318d2016-08-09 08:05:57 -0700869class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
870 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000871public:
fmenozzi55d318d2016-08-09 08:05:57 -0700872 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400873 ~GLSLCircleInside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000874
wangyix7c157a92015-07-22 15:08:53 -0700875 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000876
Brian Salomon94efbf52016-11-29 13:43:05 -0500877 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000878
879protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400880 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700881
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000882 UniformHandle fCenterUni;
883 UniformHandle fParamUni;
884
885 const char* fVSVaryingName;
886 const char* fFSVaryingName;
887
888 // @{
889 /// Values last uploaded as uniforms
890
891 SkScalar fCachedCenterX;
892 SkScalar fCachedCenterY;
893 SkScalar fCachedA;
894 SkScalar fCachedB;
895 SkScalar fCachedC;
896
897 // @}
898
899private:
fmenozzi55d318d2016-08-09 08:05:57 -0700900 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000901
902};
903
Brian Salomon94efbf52016-11-29 13:43:05 -0500904void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800905 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700906 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800907}
908
egdaniel57d3b032015-11-13 11:57:27 -0800909GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700910 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000911}
912
joshualittb0a8a372014-09-23 09:50:21 -0700913GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000914
joshualitt01258472014-09-22 10:29:30 -0700915/*
916 * All Two point conical gradient test create functions may occasionally create edge case shaders
917 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500918#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700919sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700920 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
921 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000922 SkPoint center2;
923 SkScalar radius2;
924 do {
joshualitt0067ff52015-07-08 14:26:19 -0700925 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000926 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700927 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000928 SkPoint diff = center2 - center1;
929 SkScalar diffLen = diff.length();
930 radius2 = radius1 + diffLen + increase;
931 // If the circles are identical the factory will give us an empty shader.
932 } while (radius1 == radius2 && center1 == center2);
933
Brian Osman3f748602016-10-03 18:29:03 -0400934 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400935 auto shader = params.fUseColors4f ?
936 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
937 params.fColors4f, params.fColorSpace, params.fStops,
938 params.fColorCount, params.fTileMode) :
939 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
940 params.fColors, params.fStops,
941 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400942 GrTest::TestAsFPArgs asFPArgs(d);
Florin Malita4aed1382017-05-25 10:38:07 -0400943 sk_sp<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700944 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700945 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000946}
Hal Canary6f6961e2017-01-31 13:50:44 -0500947#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000948
fmenozzi55d318d2016-08-09 08:05:57 -0700949CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
950 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700951 : fVSVaryingName(nullptr)
952 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000953 , fCachedCenterX(SK_ScalarMax)
954 , fCachedCenterY(SK_ScalarMax)
955 , fCachedA(SK_ScalarMax)
956 , fCachedB(SK_ScalarMax)
957 , fCachedC(SK_ScalarMax) {}
958
fmenozzi55d318d2016-08-09 08:05:57 -0700959void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700960 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800961 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
962 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800963 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800964 kVec2f_GrSLType, kDefault_GrSLPrecision,
965 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800966 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800967 kVec3f_GrSLType, kDefault_GrSLPrecision,
968 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000969 SkString tName("t");
970
Brian Salomon99938a82016-11-21 13:41:08 -0500971 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000972 // params.x = A
973 // params.y = B
974 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -0500975 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000976
977 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800978 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700979 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000980 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000981
982 // p = coords2D
983 // e = center end
984 // r = radius end
985 // A = dot(e, e) - r^2 + 2 * r - 1
986 // B = (r -1) / A
987 // C = 1 / A
988 // d = dot(e, p) + B
989 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -0800990 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
991 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
992 params.c_str());
993 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
994 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000995
egdaniel7ea439b2015-12-03 09:20:44 -0800996 this->emitColor(fragBuilder,
997 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500998 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800999 ge,
1000 tName.c_str(),
1001 args.fOutputColor,
1002 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001003 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001004}
1005
fmenozzi55d318d2016-08-09 08:05:57 -07001006void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001007 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001008 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001009 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001010 SkScalar centerX = data.centerX();
1011 SkScalar centerY = data.centerY();
1012 SkScalar A = data.A();
1013 SkScalar B = data.B();
1014 SkScalar C = data.C();
1015
1016 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1017 fCachedA != A || fCachedB != B || fCachedC != C) {
1018
kkinnunen7510b222014-07-30 00:04:16 -07001019 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1020 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001021
1022 fCachedCenterX = centerX;
1023 fCachedCenterY = centerY;
1024 fCachedA = A;
1025 fCachedB = B;
1026 fCachedC = C;
1027 }
1028}
1029
fmenozzi55d318d2016-08-09 08:05:57 -07001030void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1031 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001032 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001033 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001034}
1035
1036//////////////////////////////////////////////////////////////////////////////
1037
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001038class CircleOutside2PtConicalEffect : public GrGradientEffect {
1039public:
fmenozzi55d318d2016-08-09 08:05:57 -07001040 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001041
brianosman9557c272016-09-15 06:59:15 -07001042 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -07001043 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -07001044 new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001045 }
1046
Brian Salomond3b65972017-03-22 12:05:03 -04001047 ~CircleOutside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001048
mtklein36352bf2015-03-25 18:17:31 -07001049 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001050
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001051 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1052 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1053 SkScalar A() const { return fInfo.fA; }
1054 SkScalar B() const { return fInfo.fB; }
1055 SkScalar C() const { return fInfo.fC; }
1056 SkScalar tLimit() const { return fTLimit; }
1057 bool isFlipped() const { return fIsFlipped; }
1058
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001059private:
egdaniel57d3b032015-11-13 11:57:27 -08001060 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001061
Brian Salomon94efbf52016-11-29 13:43:05 -05001062 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001063
mtklein36352bf2015-03-25 18:17:31 -07001064 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001065 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001066 return (INHERITED::onIsEqual(sBase) &&
1067 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1068 this->fInfo.fA == s.fInfo.fA &&
1069 this->fInfo.fB == s.fInfo.fB &&
1070 this->fInfo.fC == s.fInfo.fC &&
1071 this->fTLimit == s.fTLimit &&
1072 this->fIsFlipped == s.fIsFlipped);
1073 }
1074
brianosman9557c272016-09-15 06:59:15 -07001075 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -05001076 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
1077 , fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001078 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001079 const SkTwoPointConicalGradient& shader =
1080 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001081 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001082 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001083 } else {
1084 fTLimit = SK_ScalarMin;
1085 }
1086
1087 fIsFlipped = shader.isFlippedGrad();
1088 }
1089
joshualittb0a8a372014-09-23 09:50:21 -07001090 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001091
1092 const CircleConicalInfo fInfo;
1093 SkScalar fTLimit;
1094 bool fIsFlipped;
1095
1096 typedef GrGradientEffect INHERITED;
1097};
1098
fmenozzi55d318d2016-08-09 08:05:57 -07001099class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1100 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001101public:
fmenozzi55d318d2016-08-09 08:05:57 -07001102 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -04001103 ~GLSLCircleOutside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001104
wangyix7c157a92015-07-22 15:08:53 -07001105 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001106
Brian Salomon94efbf52016-11-29 13:43:05 -05001107 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001108
1109protected:
Brian Salomonab015ef2017-04-04 10:15:51 -04001110 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001111
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001112 UniformHandle fCenterUni;
1113 UniformHandle fParamUni;
1114
1115 const char* fVSVaryingName;
1116 const char* fFSVaryingName;
1117
1118 bool fIsFlipped;
1119
1120 // @{
1121 /// Values last uploaded as uniforms
1122
1123 SkScalar fCachedCenterX;
1124 SkScalar fCachedCenterY;
1125 SkScalar fCachedA;
1126 SkScalar fCachedB;
1127 SkScalar fCachedC;
1128 SkScalar fCachedTLimit;
1129
1130 // @}
1131
1132private:
fmenozzi55d318d2016-08-09 08:05:57 -07001133 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001134
1135};
1136
Brian Salomon94efbf52016-11-29 13:43:05 -05001137void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -08001138 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001139 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001140}
1141
egdaniel57d3b032015-11-13 11:57:27 -08001142GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001143 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001144}
1145
joshualittb0a8a372014-09-23 09:50:21 -07001146GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001147
joshualitt01258472014-09-22 10:29:30 -07001148/*
1149 * All Two point conical gradient test create functions may occasionally create edge case shaders
1150 */
Hal Canary6f6961e2017-01-31 13:50:44 -05001151#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -07001152sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001153 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1154 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001155 SkPoint center2;
1156 SkScalar radius2;
1157 SkScalar diffLen;
1158 do {
joshualitt0067ff52015-07-08 14:26:19 -07001159 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001160 // If the circles share a center than we can't be in the outside case
1161 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001162 SkPoint diff = center2 - center1;
1163 diffLen = diff.length();
1164 // Below makes sure that circle one is not contained within circle two
1165 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001166 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001167
Brian Osman3f748602016-10-03 18:29:03 -04001168 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -04001169 auto shader = params.fUseColors4f ?
1170 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1171 params.fColors4f, params.fColorSpace, params.fStops,
1172 params.fColorCount, params.fTileMode) :
1173 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1174 params.fColors, params.fStops,
1175 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -04001176 GrTest::TestAsFPArgs asFPArgs(d);
Florin Malita4aed1382017-05-25 10:38:07 -04001177 sk_sp<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -07001178 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001179 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001180}
Hal Canary6f6961e2017-01-31 13:50:44 -05001181#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001182
fmenozzi55d318d2016-08-09 08:05:57 -07001183CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1184 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001185 : fVSVaryingName(nullptr)
1186 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001187 , fCachedCenterX(SK_ScalarMax)
1188 , fCachedCenterY(SK_ScalarMax)
1189 , fCachedA(SK_ScalarMax)
1190 , fCachedB(SK_ScalarMax)
1191 , fCachedC(SK_ScalarMax)
1192 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001193 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001194 fIsFlipped = data.isFlipped();
1195 }
1196
fmenozzi55d318d2016-08-09 08:05:57 -07001197void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001198 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001199 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1200 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -08001201 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001202 kVec2f_GrSLType, kDefault_GrSLPrecision,
1203 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001204 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001205 kVec4f_GrSLType, kDefault_GrSLPrecision,
1206 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001207 SkString tName("t");
1208
Brian Salomon99938a82016-11-21 13:41:08 -05001209 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001210 // params.x = A
1211 // params.y = B
1212 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001213 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001214
1215 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001216 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001217 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001218 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001219
1220 // output will default to transparent black (we simply won't write anything
1221 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001222 fragBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001223
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001224 // p = coords2D
1225 // e = center end
1226 // r = radius end
1227 // A = dot(e, e) - r^2 + 2 * r - 1
1228 // B = (r -1) / A
1229 // C = 1 / A
1230 // d = dot(e, p) + B
1231 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001232
egdaniel4ca2e602015-11-18 08:01:26 -08001233 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1234 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1235 params.c_str());
1236 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1237 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001238
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001239 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1240 // If so we must also flip sign on sqrt
1241 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001242 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001243 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001244 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001245 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001246
egdaniel7ea439b2015-12-03 09:20:44 -08001247 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1248 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001249 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001250 this->emitColor(fragBuilder,
1251 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001252 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001253 ge,
1254 tName.c_str(),
1255 args.fOutputColor,
1256 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001257 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001258 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001259}
1260
fmenozzi55d318d2016-08-09 08:05:57 -07001261void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001262 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001263 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001264 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001265 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001266 SkScalar centerX = data.centerX();
1267 SkScalar centerY = data.centerY();
1268 SkScalar A = data.A();
1269 SkScalar B = data.B();
1270 SkScalar C = data.C();
1271 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001272
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001273 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1274 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001275
kkinnunen7510b222014-07-30 00:04:16 -07001276 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1277 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001278 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001279
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001280 fCachedCenterX = centerX;
1281 fCachedCenterY = centerY;
1282 fCachedA = A;
1283 fCachedB = B;
1284 fCachedC = C;
1285 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001286 }
1287}
1288
fmenozzi55d318d2016-08-09 08:05:57 -07001289void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1290 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001291 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001292 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001293 key[0] = GenBaseGradientKey(processor);
1294 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001295}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001296
1297//////////////////////////////////////////////////////////////////////////////
1298
brianosman9557c272016-09-15 06:59:15 -07001299sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1300 const GrGradientEffect::CreateArgs& args) {
1301 const SkTwoPointConicalGradient& shader =
1302 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1303
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001304 SkMatrix matrix;
1305 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001306 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001307 }
brianosman9557c272016-09-15 06:59:15 -07001308 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001309 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001310 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001311 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001312 }
1313 matrix.postConcat(inv);
1314 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001315
brianosmanb9c51372016-09-15 11:09:45 -07001316 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1317 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001318
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001319 if (shader.getStartRadius() < kErrorTol) {
1320 SkScalar focalX;
1321 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1322 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001323 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001324 } else if(type == kEdge_ConicalType) {
1325 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001326 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001327 } else {
brianosman9557c272016-09-15 06:59:15 -07001328 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001329 }
1330 }
1331
1332 CircleConicalInfo info;
1333 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1334
1335 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001336 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001337 } else if (type == kEdge_ConicalType) {
1338 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001339 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001340 } else {
brianosman9557c272016-09-15 06:59:15 -07001341 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001342 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001343}
1344
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001345#endif