blob: 41e184351c70a608f2046d08546be874cf93856e [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
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 Salomonf8480b92017-07-27 15:45:59 -040078 sk_sp<GrFragmentProcessor> clone() const override {
79 return sk_sp<GrFragmentProcessor>(new Edge2PtConicalEffect(*this));
80 }
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
bungeman06ca8ec2016-06-09 08:01:03 -0700196sk_sp<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);
Florin Malita4aed1382017-05-25 10:38:07 -0400222 sk_sp<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);
jvanverthde11ee42016-02-26 13:58:40 -0800238 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
239 kVec3f_GrSLType, kDefault_GrSLPrecision,
240 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000241
242 SkString cName("c");
243 SkString tName("t");
244 SkString p0; // start radius
245 SkString p1; // start radius squared
246 SkString p2; // difference in radii (r1 - r0)
247
jvanverthde11ee42016-02-26 13:58:40 -0800248
249 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
250 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
251 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000252
253 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700254 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000255 const char* coords2D;
256 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800257 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700258 if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
egdaniel4ca2e602015-11-18 08:01:26 -0800259 fragBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700260 args.fTransformedCoords[0].c_str(),
261 args.fTransformedCoords[0].c_str(),
262 args.fTransformedCoords[1].c_str(),
263 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000264 coords2D = "interpolants.xy";
265 bVar = "interpolants.z";
266 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700267 coords2D = args.fTransformedCoords[0].c_str();
268 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000269 }
270
271 // output will default to transparent black (we simply won't write anything
272 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800273 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 +0000274
275 // c = (x^2)+(y^2) - params[1]
egdaniel4ca2e602015-11-18 08:01:26 -0800276 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000277 cName.c_str(), coords2D, coords2D, p1.c_str());
278
279 // linear case: t = -c/b
egdaniel4ca2e602015-11-18 08:01:26 -0800280 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000281 cName.c_str(), bVar.c_str());
282
283 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800284 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000285 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800286 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800287 this->emitColor(fragBuilder,
288 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500289 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800290 ge,
291 tName.c_str(),
292 args.fOutputColor,
293 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700294 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800295 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000296}
297
fmenozzi55d318d2016-08-09 08:05:57 -0700298void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400299 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700300 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700301 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000302 SkScalar radius0 = data.radius();
303 SkScalar diffRadius = data.diffRadius();
304
305 if (fCachedRadius != radius0 ||
306 fCachedDiffRadius != diffRadius) {
307
Mike Reed8be952a2017-02-13 20:44:33 -0500308 pdman.set3f(fParamUni, radius0, radius0 * radius0, diffRadius);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000309 fCachedRadius = radius0;
310 fCachedDiffRadius = diffRadius;
311 }
312}
313
fmenozzi55d318d2016-08-09 08:05:57 -0700314void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500315 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700316 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000317}
318
319//////////////////////////////////////////////////////////////////////////////
320// Focal Conical Gradients
321//////////////////////////////////////////////////////////////////////////////
322
323static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
324 SkMatrix* invLMatrix, SkScalar* focalX) {
325 // Inverse of the current local matrix is passed in then,
326 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
327 // and focal point is at the origin.
328 ConicalType conicalType;
329 const SkPoint& focal = shader.getStartCenter();
330 const SkPoint& centerEnd = shader.getEndCenter();
331 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000332 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000333
334 SkMatrix matrix;
335
336 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
337 matrix.postScale(invRadius, invRadius);
338
339 SkPoint focalTrans;
340 matrix.mapPoints(&focalTrans, &focal, 1);
341 *focalX = focalTrans.length();
342
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000343 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000344 SkScalar invFocalX = SkScalarInvert(*focalX);
345 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -0500346 rot.setSinCos(-invFocalX * focalTrans.fY, invFocalX * focalTrans.fX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000347 matrix.postConcat(rot);
348 }
349
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000350 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000351
352 // If the focal point is touching the edge of the circle it will
353 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700354 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
355 // stability trade off versus the linear approx used in the Edge Shader
356 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000357 return kEdge_ConicalType;
358 }
359
360 // Scale factor 1 / (1 - focalX * focalX)
Mike Reed8be952a2017-02-13 20:44:33 -0500361 SkScalar oneMinusF2 = 1.f - *focalX * *focalX;
reed80ea19c2015-05-12 10:37:34 -0700362 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000363
364
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000365 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000366 conicalType = kInside_ConicalType;
367 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
368 } else {
369 conicalType = kOutside_ConicalType;
370 matrix.postScale(s, s);
371 }
372
373 invLMatrix->postConcat(matrix);
374
375 return conicalType;
376}
377
378//////////////////////////////////////////////////////////////////////////////
379
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000380class FocalOutside2PtConicalEffect : public GrGradientEffect {
381public:
fmenozzi55d318d2016-08-09 08:05:57 -0700382 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000383
brianosman9557c272016-09-15 06:59:15 -0700384 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
Brian Salomon6af27012017-06-09 08:21:42 -0400385 auto processor =
386 sk_sp<FocalOutside2PtConicalEffect>(new FocalOutside2PtConicalEffect(args, focalX));
387 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000388 }
389
mtklein36352bf2015-03-25 18:17:31 -0700390 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800391 return "Two-Point Conical Gradient Focal Outside";
392 }
393
Brian Salomonf8480b92017-07-27 15:45:59 -0400394 sk_sp<GrFragmentProcessor> clone() const override {
395 return sk_sp<GrFragmentProcessor>(new FocalOutside2PtConicalEffect(*this));
396 }
397
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000398 bool isFlipped() const { return fIsFlipped; }
399 SkScalar focal() const { return fFocalX; }
400
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000401private:
egdaniel57d3b032015-11-13 11:57:27 -0800402 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700403
Brian Salomon94efbf52016-11-29 13:43:05 -0500404 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700405
mtklein36352bf2015-03-25 18:17:31 -0700406 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700407 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000408 return (INHERITED::onIsEqual(sBase) &&
409 this->fFocalX == s.fFocalX &&
410 this->fIsFlipped == s.fIsFlipped);
411 }
412
Brian Salomon587e08f2017-01-27 10:59:27 -0500413 static bool IsFlipped(const CreateArgs& args) {
414 // eww.
415 return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
416 }
417
brianosman9557c272016-09-15 06:59:15 -0700418 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500419 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
420 , fFocalX(focalX)
421 , fIsFlipped(IsFlipped(args)) {
joshualitteb2a6762014-12-04 11:35:33 -0800422 this->initClassID<FocalOutside2PtConicalEffect>();
423 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000424
Brian Salomonf8480b92017-07-27 15:45:59 -0400425 explicit FocalOutside2PtConicalEffect(const FocalOutside2PtConicalEffect& that)
426 : INHERITED(that), fFocalX(that.fFocalX), fIsFlipped(that.fIsFlipped) {
427 this->initClassID<FocalOutside2PtConicalEffect>();
428 }
429
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400430 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000431
432 SkScalar fFocalX;
433 bool fIsFlipped;
434
435 typedef GrGradientEffect INHERITED;
436};
437
Brian Salomon587e08f2017-01-27 10:59:27 -0500438class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700439 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000440public:
fmenozzi55d318d2016-08-09 08:05:57 -0700441 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000442
wangyix7c157a92015-07-22 15:08:53 -0700443 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000444
Brian Salomon94efbf52016-11-29 13:43:05 -0500445 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000446
447protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400448 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700449
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000450 UniformHandle fParamUni;
451
452 const char* fVSVaryingName;
453 const char* fFSVaryingName;
454
455 bool fIsFlipped;
456
457 // @{
458 /// Values last uploaded as uniforms
459
460 SkScalar fCachedFocal;
461
462 // @}
463
464private:
fmenozzi55d318d2016-08-09 08:05:57 -0700465 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000466
467};
468
Brian Salomon94efbf52016-11-29 13:43:05 -0500469void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800470 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700471 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800472}
473
egdaniel57d3b032015-11-13 11:57:27 -0800474GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700475 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000476}
477
joshualittb0a8a372014-09-23 09:50:21 -0700478GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000479
joshualitt01258472014-09-22 10:29:30 -0700480/*
481 * All Two point conical gradient test create functions may occasionally create edge case shaders
482 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500483#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700484sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(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);
Florin Malita4aed1382017-05-25 10:38:07 -0400508 sk_sp<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);
jvanverthde11ee42016-02-26 13:58:40 -0800527 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
528 kVec2f_GrSLType, kDefault_GrSLPrecision,
529 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000530 SkString tName("t");
531 SkString p0; // focalX
532 SkString p1; // 1 - focalX * focalX
533
jvanverthde11ee42016-02-26 13:58:40 -0800534 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
535 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000536
537 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800538 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700539 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000540 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000541
542 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
543
544 // output will default to transparent black (we simply won't write anything
545 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800546 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 +0000547
egdaniel4ca2e602015-11-18 08:01:26 -0800548 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
549 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
550 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000551
552 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
553 // If so we must also flip sign on sqrt
554 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -0800555 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
556 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000557 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800558 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
559 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000560 }
561
egdaniel4ca2e602015-11-18 08:01:26 -0800562 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
563 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800564 this->emitColor(fragBuilder,
565 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500566 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800567 ge,
568 tName.c_str(),
569 args.fOutputColor,
570 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700571 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800572 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000573}
574
fmenozzi55d318d2016-08-09 08:05:57 -0700575void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400576 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700577 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700578 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000579 SkASSERT(data.isFlipped() == fIsFlipped);
580 SkScalar focal = data.focal();
581
582 if (fCachedFocal != focal) {
Mike Reed8be952a2017-02-13 20:44:33 -0500583 SkScalar oneMinus2F = 1.f - focal * focal;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000584
jvanverthde11ee42016-02-26 13:58:40 -0800585 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000586 fCachedFocal = focal;
587 }
588}
589
fmenozzi55d318d2016-08-09 08:05:57 -0700590void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
591 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500592 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700593 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700594 key[0] = GenBaseGradientKey(processor);
595 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000596}
597
598//////////////////////////////////////////////////////////////////////////////
599
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000600class FocalInside2PtConicalEffect : public GrGradientEffect {
601public:
fmenozzi55d318d2016-08-09 08:05:57 -0700602 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000603
brianosman9557c272016-09-15 06:59:15 -0700604 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
Brian Salomon6af27012017-06-09 08:21:42 -0400605 auto processor =
606 sk_sp<FocalInside2PtConicalEffect>(new FocalInside2PtConicalEffect(args, focalX));
607 return processor->isValid() ? std::move(processor) : nullptr;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000608 }
609
mtklein36352bf2015-03-25 18:17:31 -0700610 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800611 return "Two-Point Conical Gradient Focal Inside";
612 }
613
Brian Salomonf8480b92017-07-27 15:45:59 -0400614 sk_sp<GrFragmentProcessor> clone() const override {
615 return sk_sp<GrFragmentProcessor>(new FocalInside2PtConicalEffect(*this));
616 }
617
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000618 SkScalar focal() const { return fFocalX; }
619
fmenozzi55d318d2016-08-09 08:05:57 -0700620 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000621
622private:
egdaniel57d3b032015-11-13 11:57:27 -0800623 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700624
Brian Salomon94efbf52016-11-29 13:43:05 -0500625 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700626
mtklein36352bf2015-03-25 18:17:31 -0700627 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700628 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000629 return (INHERITED::onIsEqual(sBase) &&
630 this->fFocalX == s.fFocalX);
631 }
632
brianosman9557c272016-09-15 06:59:15 -0700633 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500634 : INHERITED(args, args.fShader->colorsAreOpaque()), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800635 this->initClassID<FocalInside2PtConicalEffect>();
636 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000637
Brian Salomonf8480b92017-07-27 15:45:59 -0400638 explicit FocalInside2PtConicalEffect(const FocalInside2PtConicalEffect& that)
639 : INHERITED(that), fFocalX(that.fFocalX) {
640 this->initClassID<FocalInside2PtConicalEffect>();
641 }
642
Brian Salomon0c26a9d2017-07-06 10:09:38 -0400643 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000644
645 SkScalar fFocalX;
646
647 typedef GrGradientEffect INHERITED;
648};
649
fmenozzi55d318d2016-08-09 08:05:57 -0700650class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
651 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000652public:
fmenozzi55d318d2016-08-09 08:05:57 -0700653 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000654
wangyix7c157a92015-07-22 15:08:53 -0700655 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000656
Brian Salomon94efbf52016-11-29 13:43:05 -0500657 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000658
659protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400660 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700661
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000662 UniformHandle fFocalUni;
663
664 const char* fVSVaryingName;
665 const char* fFSVaryingName;
666
667 // @{
668 /// Values last uploaded as uniforms
669
670 SkScalar fCachedFocal;
671
672 // @}
673
674private:
fmenozzi55d318d2016-08-09 08:05:57 -0700675 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000676
677};
678
Brian Salomon94efbf52016-11-29 13:43:05 -0500679void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800680 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700681 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800682}
683
egdaniel57d3b032015-11-13 11:57:27 -0800684GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700685 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000686}
687
joshualittb0a8a372014-09-23 09:50:21 -0700688GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000689
joshualitt01258472014-09-22 10:29:30 -0700690/*
691 * All Two point conical gradient test create functions may occasionally create edge case shaders
692 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500693#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700694sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(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);
Florin Malita4aed1382017-05-25 10:38:07 -0400719 sk_sp<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);
cdalton5e58cee2016-02-11 12:49:47 -0800735 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800736 kFloat_GrSLType, kDefault_GrSLPrecision,
737 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000738 SkString tName("t");
739
740 // this is the distance along x-axis from the end center to focal point in
741 // transformed coordinates
Brian Salomon99938a82016-11-21 13:41:08 -0500742 GrShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000743
744 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800745 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700746 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000747 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000748
749 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800750 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800751 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000752
egdaniel7ea439b2015-12-03 09:20:44 -0800753 this->emitColor(fragBuilder,
754 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500755 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800756 ge,
757 tName.c_str(),
758 args.fOutputColor,
759 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700760 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000761}
762
fmenozzi55d318d2016-08-09 08:05:57 -0700763void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400764 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700765 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700766 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000767 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000768
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000769 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700770 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000771 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000772 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000773}
774
fmenozzi55d318d2016-08-09 08:05:57 -0700775void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
776 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500777 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700778 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000779}
780
781//////////////////////////////////////////////////////////////////////////////
782// Circle Conical Gradients
783//////////////////////////////////////////////////////////////////////////////
784
785struct CircleConicalInfo {
786 SkPoint fCenterEnd;
787 SkScalar fA;
788 SkScalar fB;
789 SkScalar fC;
790};
791
792// Returns focal distance along x-axis in transformed coords
793static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
794 SkMatrix* invLMatrix, CircleConicalInfo* info) {
795 // Inverse of the current local matrix is passed in then,
796 // translate and scale such that start circle is on the origin and has radius 1
797 const SkPoint& centerStart = shader.getStartCenter();
798 const SkPoint& centerEnd = shader.getEndCenter();
799 SkScalar radiusStart = shader.getStartRadius();
800 SkScalar radiusEnd = shader.getEndRadius();
801
802 SkMatrix matrix;
803
804 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
805
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000806 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000807 matrix.postScale(invStartRad, invStartRad);
808
809 radiusEnd /= radiusStart;
810
811 SkPoint centerEndTrans;
812 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
813
814 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
815 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
816
817 // Check to see if start circle is inside end circle with edges touching.
818 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700819 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
820 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
821 // still accurate.
822 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000823 return kEdge_ConicalType;
824 }
825
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000826 SkScalar C = 1.f / A;
827 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000828
829 matrix.postScale(C, C);
830
831 invLMatrix->postConcat(matrix);
832
833 info->fCenterEnd = centerEndTrans;
834 info->fA = A;
835 info->fB = B;
836 info->fC = C;
837
838 // 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 +0000839 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000840 return kInside_ConicalType;
841 }
842 return kOutside_ConicalType;
843}
844
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000845class CircleInside2PtConicalEffect : public GrGradientEffect {
846public:
fmenozzi55d318d2016-08-09 08:05:57 -0700847 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000848
brianosman9557c272016-09-15 06:59:15 -0700849 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
Brian Salomon6af27012017-06-09 08:21:42 -0400850 auto processor =
851 sk_sp<CircleInside2PtConicalEffect>(new CircleInside2PtConicalEffect(args, info));
852 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 Salomonf8480b92017-07-27 15:45:59 -0400857 sk_sp<GrFragmentProcessor> clone() const override {
858 return sk_sp<GrFragmentProcessor>(new CircleInside2PtConicalEffect(*this));
859 }
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
bungeman06ca8ec2016-06-09 08:01:03 -0700948sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700949 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
950 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000951 SkPoint center2;
952 SkScalar radius2;
953 do {
joshualitt0067ff52015-07-08 14:26:19 -0700954 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000955 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700956 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000957 SkPoint diff = center2 - center1;
958 SkScalar diffLen = diff.length();
959 radius2 = radius1 + diffLen + increase;
960 // If the circles are identical the factory will give us an empty shader.
961 } while (radius1 == radius2 && center1 == center2);
962
Brian Osman3f748602016-10-03 18:29:03 -0400963 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400964 auto shader = params.fUseColors4f ?
965 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
966 params.fColors4f, params.fColorSpace, params.fStops,
967 params.fColorCount, params.fTileMode) :
968 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
969 params.fColors, params.fStops,
970 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400971 GrTest::TestAsFPArgs asFPArgs(d);
Florin Malita4aed1382017-05-25 10:38:07 -0400972 sk_sp<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700973 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700974 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000975}
Hal Canary6f6961e2017-01-31 13:50:44 -0500976#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000977
fmenozzi55d318d2016-08-09 08:05:57 -0700978CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
979 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700980 : fVSVaryingName(nullptr)
981 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000982 , fCachedCenterX(SK_ScalarMax)
983 , fCachedCenterY(SK_ScalarMax)
984 , fCachedA(SK_ScalarMax)
985 , fCachedB(SK_ScalarMax)
986 , fCachedC(SK_ScalarMax) {}
987
fmenozzi55d318d2016-08-09 08:05:57 -0700988void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700989 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800990 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
991 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800992 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800993 kVec2f_GrSLType, kDefault_GrSLPrecision,
994 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800995 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800996 kVec3f_GrSLType, kDefault_GrSLPrecision,
997 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000998 SkString tName("t");
999
Brian Salomon99938a82016-11-21 13:41:08 -05001000 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001001 // params.x = A
1002 // params.y = B
1003 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001004 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001005
1006 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001007 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001008 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001009 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001010
1011 // p = coords2D
1012 // e = center end
1013 // r = radius end
1014 // A = dot(e, e) - r^2 + 2 * r - 1
1015 // B = (r -1) / A
1016 // C = 1 / A
1017 // d = dot(e, p) + B
1018 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -08001019 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1020 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1021 params.c_str());
1022 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
1023 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001024
egdaniel7ea439b2015-12-03 09:20:44 -08001025 this->emitColor(fragBuilder,
1026 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001027 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001028 ge,
1029 tName.c_str(),
1030 args.fOutputColor,
1031 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001032 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001033}
1034
fmenozzi55d318d2016-08-09 08:05:57 -07001035void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001036 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001037 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001038 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001039 SkScalar centerX = data.centerX();
1040 SkScalar centerY = data.centerY();
1041 SkScalar A = data.A();
1042 SkScalar B = data.B();
1043 SkScalar C = data.C();
1044
1045 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1046 fCachedA != A || fCachedB != B || fCachedC != C) {
1047
kkinnunen7510b222014-07-30 00:04:16 -07001048 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1049 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001050
1051 fCachedCenterX = centerX;
1052 fCachedCenterY = centerY;
1053 fCachedA = A;
1054 fCachedB = B;
1055 fCachedC = C;
1056 }
1057}
1058
fmenozzi55d318d2016-08-09 08:05:57 -07001059void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1060 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001061 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001062 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001063}
1064
1065//////////////////////////////////////////////////////////////////////////////
1066
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001067class CircleOutside2PtConicalEffect : public GrGradientEffect {
1068public:
fmenozzi55d318d2016-08-09 08:05:57 -07001069 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001070
brianosman9557c272016-09-15 06:59:15 -07001071 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -07001072 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -07001073 new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001074 }
1075
mtklein36352bf2015-03-25 18:17:31 -07001076 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001077
Brian Salomonf8480b92017-07-27 15:45:59 -04001078 sk_sp<GrFragmentProcessor> clone() const override {
1079 return sk_sp<GrFragmentProcessor>(new CircleOutside2PtConicalEffect(*this));
1080 }
1081
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001082 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1083 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1084 SkScalar A() const { return fInfo.fA; }
1085 SkScalar B() const { return fInfo.fB; }
1086 SkScalar C() const { return fInfo.fC; }
1087 SkScalar tLimit() const { return fTLimit; }
1088 bool isFlipped() const { return fIsFlipped; }
1089
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001090private:
egdaniel57d3b032015-11-13 11:57:27 -08001091 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001092
Brian Salomon94efbf52016-11-29 13:43:05 -05001093 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001094
mtklein36352bf2015-03-25 18:17:31 -07001095 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001096 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001097 return (INHERITED::onIsEqual(sBase) &&
1098 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1099 this->fInfo.fA == s.fInfo.fA &&
1100 this->fInfo.fB == s.fInfo.fB &&
1101 this->fInfo.fC == s.fInfo.fC &&
1102 this->fTLimit == s.fTLimit &&
1103 this->fIsFlipped == s.fIsFlipped);
1104 }
1105
brianosman9557c272016-09-15 06:59:15 -07001106 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -05001107 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
1108 , fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001109 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001110 const SkTwoPointConicalGradient& shader =
1111 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001112 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001113 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001114 } else {
1115 fTLimit = SK_ScalarMin;
1116 }
1117
1118 fIsFlipped = shader.isFlippedGrad();
1119 }
1120
Brian Salomonf8480b92017-07-27 15:45:59 -04001121 explicit CircleOutside2PtConicalEffect(const CircleOutside2PtConicalEffect& that)
1122 : INHERITED(that)
1123 , fInfo(that.fInfo)
1124 , fTLimit(that.fTLimit)
1125 , fIsFlipped(that.fIsFlipped) {
1126 this->initClassID<CircleOutside2PtConicalEffect>();
1127 }
1128
Brian Salomon0c26a9d2017-07-06 10:09:38 -04001129 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001130
1131 const CircleConicalInfo fInfo;
1132 SkScalar fTLimit;
1133 bool fIsFlipped;
1134
1135 typedef GrGradientEffect INHERITED;
1136};
1137
fmenozzi55d318d2016-08-09 08:05:57 -07001138class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1139 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001140public:
fmenozzi55d318d2016-08-09 08:05:57 -07001141 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001142
wangyix7c157a92015-07-22 15:08:53 -07001143 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001144
Brian Salomon94efbf52016-11-29 13:43:05 -05001145 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001146
1147protected:
Brian Salomonab015ef2017-04-04 10:15:51 -04001148 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001149
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001150 UniformHandle fCenterUni;
1151 UniformHandle fParamUni;
1152
1153 const char* fVSVaryingName;
1154 const char* fFSVaryingName;
1155
1156 bool fIsFlipped;
1157
1158 // @{
1159 /// Values last uploaded as uniforms
1160
1161 SkScalar fCachedCenterX;
1162 SkScalar fCachedCenterY;
1163 SkScalar fCachedA;
1164 SkScalar fCachedB;
1165 SkScalar fCachedC;
1166 SkScalar fCachedTLimit;
1167
1168 // @}
1169
1170private:
fmenozzi55d318d2016-08-09 08:05:57 -07001171 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001172
1173};
1174
Brian Salomon94efbf52016-11-29 13:43:05 -05001175void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -08001176 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001177 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001178}
1179
egdaniel57d3b032015-11-13 11:57:27 -08001180GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001181 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001182}
1183
joshualittb0a8a372014-09-23 09:50:21 -07001184GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001185
joshualitt01258472014-09-22 10:29:30 -07001186/*
1187 * All Two point conical gradient test create functions may occasionally create edge case shaders
1188 */
Hal Canary6f6961e2017-01-31 13:50:44 -05001189#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -07001190sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(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);
Florin Malita4aed1382017-05-25 10:38:07 -04001215 sk_sp<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);
cdalton5e58cee2016-02-11 12:49:47 -08001239 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001240 kVec2f_GrSLType, kDefault_GrSLPrecision,
1241 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001242 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001243 kVec4f_GrSLType, kDefault_GrSLPrecision,
1244 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001245 SkString tName("t");
1246
Brian Salomon99938a82016-11-21 13:41:08 -05001247 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001248 // params.x = A
1249 // params.y = B
1250 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001251 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001252
1253 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001254 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001255 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001256 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001257
1258 // output will default to transparent black (we simply won't write anything
1259 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001260 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 +00001261
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001262 // p = coords2D
1263 // e = center end
1264 // r = radius end
1265 // A = dot(e, e) - r^2 + 2 * r - 1
1266 // B = (r -1) / A
1267 // C = 1 / A
1268 // d = dot(e, p) + B
1269 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001270
egdaniel4ca2e602015-11-18 08:01:26 -08001271 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1272 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1273 params.c_str());
1274 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1275 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001276
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001277 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1278 // If so we must also flip sign on sqrt
1279 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001280 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001281 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001282 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001283 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001284
egdaniel7ea439b2015-12-03 09:20:44 -08001285 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1286 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001287 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001288 this->emitColor(fragBuilder,
1289 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001290 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001291 ge,
1292 tName.c_str(),
1293 args.fOutputColor,
1294 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001295 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001296 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001297}
1298
fmenozzi55d318d2016-08-09 08:05:57 -07001299void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001300 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001301 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001302 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001303 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001304 SkScalar centerX = data.centerX();
1305 SkScalar centerY = data.centerY();
1306 SkScalar A = data.A();
1307 SkScalar B = data.B();
1308 SkScalar C = data.C();
1309 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001310
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001311 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1312 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001313
kkinnunen7510b222014-07-30 00:04:16 -07001314 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1315 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001316 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001317
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001318 fCachedCenterX = centerX;
1319 fCachedCenterY = centerY;
1320 fCachedA = A;
1321 fCachedB = B;
1322 fCachedC = C;
1323 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001324 }
1325}
1326
fmenozzi55d318d2016-08-09 08:05:57 -07001327void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1328 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001329 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001330 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001331 key[0] = GenBaseGradientKey(processor);
1332 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001333}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001334
1335//////////////////////////////////////////////////////////////////////////////
1336
brianosman9557c272016-09-15 06:59:15 -07001337sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1338 const GrGradientEffect::CreateArgs& args) {
1339 const SkTwoPointConicalGradient& shader =
1340 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1341
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001342 SkMatrix matrix;
1343 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001344 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001345 }
brianosman9557c272016-09-15 06:59:15 -07001346 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001347 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001348 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001349 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001350 }
1351 matrix.postConcat(inv);
1352 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001353
brianosmanb9c51372016-09-15 11:09:45 -07001354 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1355 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001356
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001357 if (shader.getStartRadius() < kErrorTol) {
1358 SkScalar focalX;
1359 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1360 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001361 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001362 } else if(type == kEdge_ConicalType) {
1363 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001364 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001365 } else {
brianosman9557c272016-09-15 06:59:15 -07001366 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001367 }
1368 }
1369
1370 CircleConicalInfo info;
1371 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1372
1373 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001374 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001375 } else if (type == kEdge_ConicalType) {
1376 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001377 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001378 } else {
brianosman9557c272016-09-15 06:59:15 -07001379 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001380 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001381}
1382
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001383#endif