blob: f11ca65d0c0611a4bcb6d1cf11e18a8959453f0c [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#include "SkTwoPointConicalGradient_gpu.h"
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00009
10#include "SkTwoPointConicalGradient.h"
11
commit-bot@chromium.orgef93d292014-04-10 15:37:52 +000012#if SK_SUPPORT_GPU
egdaniel7ea439b2015-12-03 09:20:44 -080013#include "GrCoordTransform.h"
14#include "GrInvariantOutput.h"
joshualitt8ca93e72015-07-08 06:51:43 -070015#include "GrPaint.h"
egdaniel2d721d32015-11-11 13:06:05 -080016#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070017#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080018#include "glsl/GrGLSLUniformHandler.h"
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;
55 rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY),
56 SkScalarMul(invDiffLen, diff.fX));
57 invLMatrix->postConcat(rot);
58 }
59}
60
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000061class Edge2PtConicalEffect : public GrGradientEffect {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000062public:
fmenozzi55d318d2016-08-09 08:05:57 -070063 class GLSLEdge2PtConicalProcessor;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000064
bungeman06ca8ec2016-06-09 08:01:03 -070065 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
66 const SkTwoPointConicalGradient& shader,
67 const SkMatrix& matrix,
68 SkShader::TileMode tm) {
69 return sk_sp<GrFragmentProcessor>(new Edge2PtConicalEffect(ctx, shader, matrix, tm));
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000070 }
71
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000072 virtual ~Edge2PtConicalEffect() {}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000073
mtklein36352bf2015-03-25 18:17:31 -070074 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -080075 return "Two-Point Conical Gradient Edge Touching";
76 }
77
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000078 // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000079 SkScalar center() const { return fCenterX1; }
80 SkScalar diffRadius() const { return fDiffRadius; }
81 SkScalar radius() const { return fRadius0; }
82
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000083private:
egdaniel57d3b032015-11-13 11:57:27 -080084 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070085
egdaniel57d3b032015-11-13 11:57:27 -080086 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070087
mtklein36352bf2015-03-25 18:17:31 -070088 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -070089 const Edge2PtConicalEffect& s = sBase.cast<Edge2PtConicalEffect>();
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000090 return (INHERITED::onIsEqual(sBase) &&
91 this->fCenterX1 == s.fCenterX1 &&
92 this->fRadius0 == s.fRadius0 &&
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000093 this->fDiffRadius == s.fDiffRadius);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000094 }
95
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000096 Edge2PtConicalEffect(GrContext* ctx,
97 const SkTwoPointConicalGradient& shader,
98 const SkMatrix& matrix,
99 SkShader::TileMode tm)
bsalomon4a339522015-10-06 08:40:50 -0700100 : INHERITED(ctx, shader, matrix, tm),
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000101 fCenterX1(shader.getCenterX1()),
102 fRadius0(shader.getStartRadius()),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000103 fDiffRadius(shader.getDiffRadius()){
joshualitteb2a6762014-12-04 11:35:33 -0800104 this->initClassID<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000105 // We should only be calling this shader if we are degenerate case with touching circles
egdaniel8405ef92014-06-09 11:57:28 -0700106 // When deciding if we are in edge case, we scaled by the end radius for cases when the
joshualitt01258472014-09-22 10:29:30 -0700107 // start radius was close to zero, otherwise we scaled by the start radius. In addition
108 // Our test for the edge case in set_matrix_circle_conical has a higher tolerance so we
109 // need the sqrt value below
110 SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - fCenterX1) <
111 (fRadius0 < kErrorTol ? shader.getEndRadius() * kEdgeErrorTol :
112 fRadius0 * sqrt(kEdgeErrorTol)));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000113
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000114 // We pass the linear part of the quadratic as a varying.
115 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
116 fBTransform = this->getCoordTransform();
117 SkMatrix& bMatrix = *fBTransform.accessMatrix();
118 SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius);
119 bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) +
120 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0]));
121 bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) +
122 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1]));
123 bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) +
124 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2]));
125 this->addCoordTransform(&fBTransform);
126 }
127
joshualittb0a8a372014-09-23 09:50:21 -0700128 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000129
130 // @{
131 // Cache of values - these can change arbitrarily, EXCEPT
132 // we shouldn't change between degenerate and non-degenerate?!
133
134 GrCoordTransform fBTransform;
135 SkScalar fCenterX1;
136 SkScalar fRadius0;
137 SkScalar fDiffRadius;
138
139 // @}
140
141 typedef GrGradientEffect INHERITED;
142};
143
fmenozzi55d318d2016-08-09 08:05:57 -0700144class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000145public:
fmenozzi55d318d2016-08-09 08:05:57 -0700146 GLSLEdge2PtConicalProcessor(const GrProcessor&);
147 virtual ~GLSLEdge2PtConicalProcessor() { }
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000148
wangyix7c157a92015-07-22 15:08:53 -0700149 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000150
jvanverthcfc18862015-04-28 08:48:20 -0700151 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000152
153protected:
egdaniel018fb622015-10-28 07:26:40 -0700154 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700155
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000156 UniformHandle fParamUni;
157
158 const char* fVSVaryingName;
159 const char* fFSVaryingName;
160
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000161 // @{
162 /// Values last uploaded as uniforms
163
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000164 SkScalar fCachedRadius;
165 SkScalar fCachedDiffRadius;
166
167 // @}
168
169private:
fmenozzi55d318d2016-08-09 08:05:57 -0700170 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000171
172};
173
egdaniel57d3b032015-11-13 11:57:27 -0800174void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
175 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700176 Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800177}
178
egdaniel57d3b032015-11-13 11:57:27 -0800179GrGLSLFragmentProcessor* Edge2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700180 return new Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor(*this);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000181}
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000182
joshualittb0a8a372014-09-23 09:50:21 -0700183GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Edge2PtConicalEffect);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000184
joshualitt01258472014-09-22 10:29:30 -0700185/*
186 * All Two point conical gradient test create functions may occasionally create edge case shaders
187 */
bungeman06ca8ec2016-06-09 08:01:03 -0700188sk_sp<GrFragmentProcessor> Edge2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700189 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
190 SkScalar radius1 = d->fRandom->nextUScalar1();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000191 SkPoint center2;
192 SkScalar radius2;
193 do {
joshualitt0067ff52015-07-08 14:26:19 -0700194 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000195 // If the circles are identical the factory will give us an empty shader.
196 // This will happen if we pick identical centers
197 } while (center1 == center2);
198
199 // Below makes sure that circle one is contained within circle two
200 // and both circles are touching on an edge
201 SkPoint diff = center2 - center1;
202 SkScalar diffLen = diff.length();
203 radius2 = radius1 + diffLen;
204
205 SkColor colors[kMaxRandomGradientColors];
206 SkScalar stopsArray[kMaxRandomGradientColors];
207 SkScalar* stops = stopsArray;
208 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700209 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800210 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
211 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700212 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
213 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700214 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
215 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700216 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700217 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000218}
219
fmenozzi55d318d2016-08-09 08:05:57 -0700220Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GLSLEdge2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700221 : fVSVaryingName(nullptr)
222 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000223 , fCachedRadius(-SK_ScalarMax)
224 , fCachedDiffRadius(-SK_ScalarMax) {}
225
fmenozzi55d318d2016-08-09 08:05:57 -0700226void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700227 const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800228 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
229 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800230 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
231 kVec3f_GrSLType, kDefault_GrSLPrecision,
232 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000233
234 SkString cName("c");
235 SkString tName("t");
236 SkString p0; // start radius
237 SkString p1; // start radius squared
238 SkString p2; // difference in radii (r1 - r0)
239
jvanverthde11ee42016-02-26 13:58:40 -0800240
241 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
242 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
243 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000244
245 // We interpolate the linear component in coords[1].
wangyix7c157a92015-07-22 15:08:53 -0700246 SkASSERT(args.fCoords[0].getType() == args.fCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000247 const char* coords2D;
248 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800249 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
wangyix7c157a92015-07-22 15:08:53 -0700250 if (kVec3f_GrSLType == args.fCoords[0].getType()) {
egdaniel4ca2e602015-11-18 08:01:26 -0800251 fragBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
wangyix7c157a92015-07-22 15:08:53 -0700252 args.fCoords[0].c_str(), args.fCoords[0].c_str(),
253 args.fCoords[1].c_str(), args.fCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000254 coords2D = "interpolants.xy";
255 bVar = "interpolants.z";
256 } else {
wangyix7c157a92015-07-22 15:08:53 -0700257 coords2D = args.fCoords[0].c_str();
258 bVar.printf("%s.x", args.fCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000259 }
260
261 // output will default to transparent black (we simply won't write anything
262 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800263 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 +0000264
265 // c = (x^2)+(y^2) - params[1]
egdaniel4ca2e602015-11-18 08:01:26 -0800266 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000267 cName.c_str(), coords2D, coords2D, p1.c_str());
268
269 // linear case: t = -c/b
egdaniel4ca2e602015-11-18 08:01:26 -0800270 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000271 cName.c_str(), bVar.c_str());
272
273 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800274 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000275 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800276 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800277 this->emitColor(fragBuilder,
278 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800279 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800280 ge,
281 tName.c_str(),
282 args.fOutputColor,
283 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700284 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800285 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000286}
287
fmenozzi55d318d2016-08-09 08:05:57 -0700288void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
289 const GrGLSLProgramDataManager& pdman,
290 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700291 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700292 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000293 SkScalar radius0 = data.radius();
294 SkScalar diffRadius = data.diffRadius();
295
296 if (fCachedRadius != radius0 ||
297 fCachedDiffRadius != diffRadius) {
298
halcanary9d524f22016-03-29 09:03:52 -0700299 pdman.set3f(fParamUni, SkScalarToFloat(radius0),
jvanverthde11ee42016-02-26 13:58:40 -0800300 SkScalarToFloat(SkScalarMul(radius0, radius0)), SkScalarToFloat(diffRadius));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000301 fCachedRadius = radius0;
302 fCachedDiffRadius = diffRadius;
303 }
304}
305
fmenozzi55d318d2016-08-09 08:05:57 -0700306void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -0700307 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700308 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000309}
310
311//////////////////////////////////////////////////////////////////////////////
312// Focal Conical Gradients
313//////////////////////////////////////////////////////////////////////////////
314
315static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
316 SkMatrix* invLMatrix, SkScalar* focalX) {
317 // Inverse of the current local matrix is passed in then,
318 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
319 // and focal point is at the origin.
320 ConicalType conicalType;
321 const SkPoint& focal = shader.getStartCenter();
322 const SkPoint& centerEnd = shader.getEndCenter();
323 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000324 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000325
326 SkMatrix matrix;
327
328 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
329 matrix.postScale(invRadius, invRadius);
330
331 SkPoint focalTrans;
332 matrix.mapPoints(&focalTrans, &focal, 1);
333 *focalX = focalTrans.length();
334
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000335 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000336 SkScalar invFocalX = SkScalarInvert(*focalX);
337 SkMatrix rot;
338 rot.setSinCos(-SkScalarMul(invFocalX, focalTrans.fY),
339 SkScalarMul(invFocalX, focalTrans.fX));
340 matrix.postConcat(rot);
341 }
342
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000343 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000344
345 // If the focal point is touching the edge of the circle it will
346 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700347 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
348 // stability trade off versus the linear approx used in the Edge Shader
349 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000350 return kEdge_ConicalType;
351 }
352
353 // Scale factor 1 / (1 - focalX * focalX)
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000354 SkScalar oneMinusF2 = 1.f - SkScalarMul(*focalX, *focalX);
reed80ea19c2015-05-12 10:37:34 -0700355 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000356
357
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000358 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000359 conicalType = kInside_ConicalType;
360 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
361 } else {
362 conicalType = kOutside_ConicalType;
363 matrix.postScale(s, s);
364 }
365
366 invLMatrix->postConcat(matrix);
367
368 return conicalType;
369}
370
371//////////////////////////////////////////////////////////////////////////////
372
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000373class FocalOutside2PtConicalEffect : public GrGradientEffect {
374public:
fmenozzi55d318d2016-08-09 08:05:57 -0700375 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000376
bungeman06ca8ec2016-06-09 08:01:03 -0700377 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
378 const SkTwoPointConicalGradient& shader,
379 const SkMatrix& matrix,
380 SkShader::TileMode tm,
381 SkScalar focalX) {
382 return sk_sp<GrFragmentProcessor>(
383 new FocalOutside2PtConicalEffect(ctx, shader, matrix, tm, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000384 }
385
386 virtual ~FocalOutside2PtConicalEffect() { }
387
mtklein36352bf2015-03-25 18:17:31 -0700388 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800389 return "Two-Point Conical Gradient Focal Outside";
390 }
391
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000392 bool isFlipped() const { return fIsFlipped; }
393 SkScalar focal() const { return fFocalX; }
394
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000395private:
egdaniel57d3b032015-11-13 11:57:27 -0800396 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700397
egdaniel57d3b032015-11-13 11:57:27 -0800398 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700399
mtklein36352bf2015-03-25 18:17:31 -0700400 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700401 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000402 return (INHERITED::onIsEqual(sBase) &&
403 this->fFocalX == s.fFocalX &&
404 this->fIsFlipped == s.fIsFlipped);
405 }
406
407 FocalOutside2PtConicalEffect(GrContext* ctx,
408 const SkTwoPointConicalGradient& shader,
409 const SkMatrix& matrix,
410 SkShader::TileMode tm,
411 SkScalar focalX)
bsalomon4a339522015-10-06 08:40:50 -0700412 : INHERITED(ctx, shader, matrix, tm)
joshualittb2456052015-07-08 09:36:59 -0700413 , fFocalX(focalX)
414 , fIsFlipped(shader.isFlippedGrad()) {
joshualitteb2a6762014-12-04 11:35:33 -0800415 this->initClassID<FocalOutside2PtConicalEffect>();
416 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000417
joshualittb0a8a372014-09-23 09:50:21 -0700418 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000419
420 SkScalar fFocalX;
421 bool fIsFlipped;
422
423 typedef GrGradientEffect INHERITED;
424};
425
fmenozzi55d318d2016-08-09 08:05:57 -0700426class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
427 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000428public:
fmenozzi55d318d2016-08-09 08:05:57 -0700429 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
430 virtual ~GLSLFocalOutside2PtConicalProcessor() { }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000431
wangyix7c157a92015-07-22 15:08:53 -0700432 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000433
jvanverthcfc18862015-04-28 08:48:20 -0700434 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000435
436protected:
egdaniel018fb622015-10-28 07:26:40 -0700437 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700438
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000439 UniformHandle fParamUni;
440
441 const char* fVSVaryingName;
442 const char* fFSVaryingName;
443
444 bool fIsFlipped;
445
446 // @{
447 /// Values last uploaded as uniforms
448
449 SkScalar fCachedFocal;
450
451 // @}
452
453private:
fmenozzi55d318d2016-08-09 08:05:57 -0700454 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000455
456};
457
egdaniel57d3b032015-11-13 11:57:27 -0800458void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
459 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700460 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800461}
462
egdaniel57d3b032015-11-13 11:57:27 -0800463GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700464 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000465}
466
joshualittb0a8a372014-09-23 09:50:21 -0700467GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000468
joshualitt01258472014-09-22 10:29:30 -0700469/*
470 * All Two point conical gradient test create functions may occasionally create edge case shaders
471 */
bungeman06ca8ec2016-06-09 08:01:03 -0700472sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700473 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000474 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000475 SkPoint center2;
476 SkScalar radius2;
477 do {
joshualitt0067ff52015-07-08 14:26:19 -0700478 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000479 // 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 +0000480 } while (center1 == center2);
481 SkPoint diff = center2 - center1;
482 SkScalar diffLen = diff.length();
483 // Below makes sure that the focal point is not contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700484 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000485
486 SkColor colors[kMaxRandomGradientColors];
487 SkScalar stopsArray[kMaxRandomGradientColors];
488 SkScalar* stops = stopsArray;
489 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700490 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800491 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
492 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700493 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
494 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700495 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
496 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700497 GrAlwaysAssert(fp);
498 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000499}
500
fmenozzi55d318d2016-08-09 08:05:57 -0700501FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
502 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700503 : fVSVaryingName(nullptr)
504 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000505 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700506 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000507 fIsFlipped = data.isFlipped();
508}
509
fmenozzi55d318d2016-08-09 08:05:57 -0700510void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700511 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800512 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
513 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800514 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
515 kVec2f_GrSLType, kDefault_GrSLPrecision,
516 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000517 SkString tName("t");
518 SkString p0; // focalX
519 SkString p1; // 1 - focalX * focalX
520
jvanverthde11ee42016-02-26 13:58:40 -0800521 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
522 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000523
524 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800525 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
egdaniel4ca2e602015-11-18 08:01:26 -0800526 SkString coords2DString = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000527 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000528
529 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
530
531 // output will default to transparent black (we simply won't write anything
532 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800533 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 +0000534
egdaniel4ca2e602015-11-18 08:01:26 -0800535 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
536 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
537 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000538
539 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
540 // If so we must also flip sign on sqrt
541 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -0800542 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
543 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000544 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800545 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
546 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000547 }
548
egdaniel4ca2e602015-11-18 08:01:26 -0800549 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
550 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800551 this->emitColor(fragBuilder,
552 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800553 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800554 ge,
555 tName.c_str(),
556 args.fOutputColor,
557 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700558 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800559 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000560}
561
fmenozzi55d318d2016-08-09 08:05:57 -0700562void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
563 const GrGLSLProgramDataManager& pdman,
564 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700565 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700566 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000567 SkASSERT(data.isFlipped() == fIsFlipped);
568 SkScalar focal = data.focal();
569
570 if (fCachedFocal != focal) {
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000571 SkScalar oneMinus2F = 1.f - SkScalarMul(focal, focal);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000572
jvanverthde11ee42016-02-26 13:58:40 -0800573 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000574 fCachedFocal = focal;
575 }
576}
577
fmenozzi55d318d2016-08-09 08:05:57 -0700578void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
579 const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -0700580 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700581 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700582 key[0] = GenBaseGradientKey(processor);
583 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000584}
585
586//////////////////////////////////////////////////////////////////////////////
587
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000588class FocalInside2PtConicalEffect : public GrGradientEffect {
589public:
fmenozzi55d318d2016-08-09 08:05:57 -0700590 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000591
bungeman06ca8ec2016-06-09 08:01:03 -0700592 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
593 const SkTwoPointConicalGradient& shader,
594 const SkMatrix& matrix,
595 SkShader::TileMode tm,
596 SkScalar focalX) {
597 return sk_sp<GrFragmentProcessor>(
598 new FocalInside2PtConicalEffect(ctx, shader, matrix, tm, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000599 }
600
601 virtual ~FocalInside2PtConicalEffect() {}
602
mtklein36352bf2015-03-25 18:17:31 -0700603 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800604 return "Two-Point Conical Gradient Focal Inside";
605 }
606
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000607 SkScalar focal() const { return fFocalX; }
608
fmenozzi55d318d2016-08-09 08:05:57 -0700609 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000610
611private:
egdaniel57d3b032015-11-13 11:57:27 -0800612 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700613
egdaniel57d3b032015-11-13 11:57:27 -0800614 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700615
mtklein36352bf2015-03-25 18:17:31 -0700616 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700617 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000618 return (INHERITED::onIsEqual(sBase) &&
619 this->fFocalX == s.fFocalX);
620 }
621
622 FocalInside2PtConicalEffect(GrContext* ctx,
623 const SkTwoPointConicalGradient& shader,
624 const SkMatrix& matrix,
625 SkShader::TileMode tm,
626 SkScalar focalX)
bsalomon4a339522015-10-06 08:40:50 -0700627 : INHERITED(ctx, shader, matrix, tm), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800628 this->initClassID<FocalInside2PtConicalEffect>();
629 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000630
joshualittb0a8a372014-09-23 09:50:21 -0700631 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000632
633 SkScalar fFocalX;
634
635 typedef GrGradientEffect INHERITED;
636};
637
fmenozzi55d318d2016-08-09 08:05:57 -0700638class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
639 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000640public:
fmenozzi55d318d2016-08-09 08:05:57 -0700641 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
642 virtual ~GLSLFocalInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000643
wangyix7c157a92015-07-22 15:08:53 -0700644 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000645
jvanverthcfc18862015-04-28 08:48:20 -0700646 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000647
648protected:
egdaniel018fb622015-10-28 07:26:40 -0700649 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700650
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000651 UniformHandle fFocalUni;
652
653 const char* fVSVaryingName;
654 const char* fFSVaryingName;
655
656 // @{
657 /// Values last uploaded as uniforms
658
659 SkScalar fCachedFocal;
660
661 // @}
662
663private:
fmenozzi55d318d2016-08-09 08:05:57 -0700664 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000665
666};
667
egdaniel57d3b032015-11-13 11:57:27 -0800668void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
669 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700670 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800671}
672
egdaniel57d3b032015-11-13 11:57:27 -0800673GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700674 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000675}
676
joshualittb0a8a372014-09-23 09:50:21 -0700677GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000678
joshualitt01258472014-09-22 10:29:30 -0700679/*
680 * All Two point conical gradient test create functions may occasionally create edge case shaders
681 */
bungeman06ca8ec2016-06-09 08:01:03 -0700682sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700683 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000684 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000685 SkPoint center2;
686 SkScalar radius2;
687 do {
joshualitt0067ff52015-07-08 14:26:19 -0700688 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000689 // Below makes sure radius2 is larger enouch such that the focal point
690 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700691 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000692 SkPoint diff = center2 - center1;
693 SkScalar diffLen = diff.length();
694 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000695 // If the circles are identical the factory will give us an empty shader.
696 } while (radius1 == radius2 && center1 == center2);
697
698 SkColor colors[kMaxRandomGradientColors];
699 SkScalar stopsArray[kMaxRandomGradientColors];
700 SkScalar* stops = stopsArray;
701 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700702 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800703 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
704 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700705 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
706 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700707 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
708 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700709 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700710 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000711}
712
fmenozzi55d318d2016-08-09 08:05:57 -0700713FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
714 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700715 : fVSVaryingName(nullptr)
716 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000717 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000718
fmenozzi55d318d2016-08-09 08:05:57 -0700719void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700720 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800721 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
722 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800723 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800724 kFloat_GrSLType, kDefault_GrSLPrecision,
725 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000726 SkString tName("t");
727
728 // this is the distance along x-axis from the end center to focal point in
729 // transformed coordinates
egdaniel7ea439b2015-12-03 09:20:44 -0800730 GrGLSLShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000731
732 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800733 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
egdaniel4ca2e602015-11-18 08:01:26 -0800734 SkString coords2DString = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000735 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000736
737 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800738 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800739 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000740
egdaniel7ea439b2015-12-03 09:20:44 -0800741 this->emitColor(fragBuilder,
742 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800743 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800744 ge,
745 tName.c_str(),
746 args.fOutputColor,
747 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700748 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000749}
750
fmenozzi55d318d2016-08-09 08:05:57 -0700751void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
752 const GrGLSLProgramDataManager& pdman,
753 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700754 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700755 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000756 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000757
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000758 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700759 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000760 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000761 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000762}
763
fmenozzi55d318d2016-08-09 08:05:57 -0700764void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
765 const GrProcessor& processor,
766 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700767 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000768}
769
770//////////////////////////////////////////////////////////////////////////////
771// Circle Conical Gradients
772//////////////////////////////////////////////////////////////////////////////
773
774struct CircleConicalInfo {
775 SkPoint fCenterEnd;
776 SkScalar fA;
777 SkScalar fB;
778 SkScalar fC;
779};
780
781// Returns focal distance along x-axis in transformed coords
782static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
783 SkMatrix* invLMatrix, CircleConicalInfo* info) {
784 // Inverse of the current local matrix is passed in then,
785 // translate and scale such that start circle is on the origin and has radius 1
786 const SkPoint& centerStart = shader.getStartCenter();
787 const SkPoint& centerEnd = shader.getEndCenter();
788 SkScalar radiusStart = shader.getStartRadius();
789 SkScalar radiusEnd = shader.getEndRadius();
790
791 SkMatrix matrix;
792
793 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
794
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000795 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000796 matrix.postScale(invStartRad, invStartRad);
797
798 radiusEnd /= radiusStart;
799
800 SkPoint centerEndTrans;
801 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
802
803 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
804 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
805
806 // Check to see if start circle is inside end circle with edges touching.
807 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700808 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
809 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
810 // still accurate.
811 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000812 return kEdge_ConicalType;
813 }
814
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000815 SkScalar C = 1.f / A;
816 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000817
818 matrix.postScale(C, C);
819
820 invLMatrix->postConcat(matrix);
821
822 info->fCenterEnd = centerEndTrans;
823 info->fA = A;
824 info->fB = B;
825 info->fC = C;
826
827 // 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 +0000828 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000829 return kInside_ConicalType;
830 }
831 return kOutside_ConicalType;
832}
833
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000834class CircleInside2PtConicalEffect : public GrGradientEffect {
835public:
fmenozzi55d318d2016-08-09 08:05:57 -0700836 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000837
bungeman06ca8ec2016-06-09 08:01:03 -0700838 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
839 const SkTwoPointConicalGradient& shader,
840 const SkMatrix& matrix,
841 SkShader::TileMode tm,
842 const CircleConicalInfo& info) {
843 return sk_sp<GrFragmentProcessor>(
844 new CircleInside2PtConicalEffect(ctx, shader, matrix, tm, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000845 }
846
847 virtual ~CircleInside2PtConicalEffect() {}
848
mtklein36352bf2015-03-25 18:17:31 -0700849 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800850
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000851 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
852 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
853 SkScalar A() const { return fInfo.fA; }
854 SkScalar B() const { return fInfo.fB; }
855 SkScalar C() const { return fInfo.fC; }
856
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000857private:
egdaniel57d3b032015-11-13 11:57:27 -0800858 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700859
egdaniel57d3b032015-11-13 11:57:27 -0800860 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
861 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700862
mtklein36352bf2015-03-25 18:17:31 -0700863 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700864 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000865 return (INHERITED::onIsEqual(sBase) &&
866 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
867 this->fInfo.fA == s.fInfo.fA &&
868 this->fInfo.fB == s.fInfo.fB &&
869 this->fInfo.fC == s.fInfo.fC);
870 }
871
872 CircleInside2PtConicalEffect(GrContext* ctx,
873 const SkTwoPointConicalGradient& shader,
874 const SkMatrix& matrix,
875 SkShader::TileMode tm,
876 const CircleConicalInfo& info)
bsalomon4a339522015-10-06 08:40:50 -0700877 : INHERITED(ctx, shader, matrix, tm), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800878 this->initClassID<CircleInside2PtConicalEffect>();
879 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000880
joshualittb0a8a372014-09-23 09:50:21 -0700881 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000882
883 const CircleConicalInfo fInfo;
884
885 typedef GrGradientEffect INHERITED;
886};
887
fmenozzi55d318d2016-08-09 08:05:57 -0700888class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
889 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000890public:
fmenozzi55d318d2016-08-09 08:05:57 -0700891 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
892 virtual ~GLSLCircleInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000893
wangyix7c157a92015-07-22 15:08:53 -0700894 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000895
jvanverthcfc18862015-04-28 08:48:20 -0700896 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000897
898protected:
egdaniel018fb622015-10-28 07:26:40 -0700899 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700900
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000901 UniformHandle fCenterUni;
902 UniformHandle fParamUni;
903
904 const char* fVSVaryingName;
905 const char* fFSVaryingName;
906
907 // @{
908 /// Values last uploaded as uniforms
909
910 SkScalar fCachedCenterX;
911 SkScalar fCachedCenterY;
912 SkScalar fCachedA;
913 SkScalar fCachedB;
914 SkScalar fCachedC;
915
916 // @}
917
918private:
fmenozzi55d318d2016-08-09 08:05:57 -0700919 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000920
921};
922
egdaniel57d3b032015-11-13 11:57:27 -0800923void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
924 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700925 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800926}
927
egdaniel57d3b032015-11-13 11:57:27 -0800928GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700929 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000930}
931
joshualittb0a8a372014-09-23 09:50:21 -0700932GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000933
joshualitt01258472014-09-22 10:29:30 -0700934/*
935 * All Two point conical gradient test create functions may occasionally create edge case shaders
936 */
bungeman06ca8ec2016-06-09 08:01:03 -0700937sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700938 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
939 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000940 SkPoint center2;
941 SkScalar radius2;
942 do {
joshualitt0067ff52015-07-08 14:26:19 -0700943 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000944 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700945 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000946 SkPoint diff = center2 - center1;
947 SkScalar diffLen = diff.length();
948 radius2 = radius1 + diffLen + increase;
949 // If the circles are identical the factory will give us an empty shader.
950 } while (radius1 == radius2 && center1 == center2);
951
952 SkColor colors[kMaxRandomGradientColors];
953 SkScalar stopsArray[kMaxRandomGradientColors];
954 SkScalar* stops = stopsArray;
955 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700956 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800957 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
958 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700959 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
960 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700961 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
962 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700963 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700964 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000965}
966
fmenozzi55d318d2016-08-09 08:05:57 -0700967CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
968 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700969 : fVSVaryingName(nullptr)
970 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000971 , fCachedCenterX(SK_ScalarMax)
972 , fCachedCenterY(SK_ScalarMax)
973 , fCachedA(SK_ScalarMax)
974 , fCachedB(SK_ScalarMax)
975 , fCachedC(SK_ScalarMax) {}
976
fmenozzi55d318d2016-08-09 08:05:57 -0700977void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700978 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800979 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
980 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800981 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800982 kVec2f_GrSLType, kDefault_GrSLPrecision,
983 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800984 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800985 kVec3f_GrSLType, kDefault_GrSLPrecision,
986 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000987 SkString tName("t");
988
egdaniel7ea439b2015-12-03 09:20:44 -0800989 GrGLSLShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000990 // params.x = A
991 // params.y = B
992 // params.z = C
egdaniel7ea439b2015-12-03 09:20:44 -0800993 GrGLSLShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000994
995 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800996 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
egdaniel4ca2e602015-11-18 08:01:26 -0800997 SkString coords2DString = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000998 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000999
1000 // p = coords2D
1001 // e = center end
1002 // r = radius end
1003 // A = dot(e, e) - r^2 + 2 * r - 1
1004 // B = (r -1) / A
1005 // C = 1 / A
1006 // d = dot(e, p) + B
1007 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -08001008 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1009 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1010 params.c_str());
1011 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
1012 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001013
egdaniel7ea439b2015-12-03 09:20:44 -08001014 this->emitColor(fragBuilder,
1015 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -08001016 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001017 ge,
1018 tName.c_str(),
1019 args.fOutputColor,
1020 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001021 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001022}
1023
fmenozzi55d318d2016-08-09 08:05:57 -07001024void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
1025 const GrGLSLProgramDataManager& pdman,
1026 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001027 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001028 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001029 SkScalar centerX = data.centerX();
1030 SkScalar centerY = data.centerY();
1031 SkScalar A = data.A();
1032 SkScalar B = data.B();
1033 SkScalar C = data.C();
1034
1035 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1036 fCachedA != A || fCachedB != B || fCachedC != C) {
1037
kkinnunen7510b222014-07-30 00:04:16 -07001038 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1039 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001040
1041 fCachedCenterX = centerX;
1042 fCachedCenterY = centerY;
1043 fCachedA = A;
1044 fCachedB = B;
1045 fCachedC = C;
1046 }
1047}
1048
fmenozzi55d318d2016-08-09 08:05:57 -07001049void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1050 const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -07001051 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001052 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001053}
1054
1055//////////////////////////////////////////////////////////////////////////////
1056
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001057class CircleOutside2PtConicalEffect : public GrGradientEffect {
1058public:
fmenozzi55d318d2016-08-09 08:05:57 -07001059 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001060
bungeman06ca8ec2016-06-09 08:01:03 -07001061 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
1062 const SkTwoPointConicalGradient& shader,
1063 const SkMatrix& matrix,
1064 SkShader::TileMode tm,
1065 const CircleConicalInfo& info) {
1066 return sk_sp<GrFragmentProcessor>(
1067 new CircleOutside2PtConicalEffect(ctx, shader, matrix, tm, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001068 }
1069
1070 virtual ~CircleOutside2PtConicalEffect() {}
1071
mtklein36352bf2015-03-25 18:17:31 -07001072 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001073
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001074 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1075 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1076 SkScalar A() const { return fInfo.fA; }
1077 SkScalar B() const { return fInfo.fB; }
1078 SkScalar C() const { return fInfo.fC; }
1079 SkScalar tLimit() const { return fTLimit; }
1080 bool isFlipped() const { return fIsFlipped; }
1081
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001082private:
egdaniel57d3b032015-11-13 11:57:27 -08001083 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001084
egdaniel57d3b032015-11-13 11:57:27 -08001085 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001086
mtklein36352bf2015-03-25 18:17:31 -07001087 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001088 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001089 return (INHERITED::onIsEqual(sBase) &&
1090 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1091 this->fInfo.fA == s.fInfo.fA &&
1092 this->fInfo.fB == s.fInfo.fB &&
1093 this->fInfo.fC == s.fInfo.fC &&
1094 this->fTLimit == s.fTLimit &&
1095 this->fIsFlipped == s.fIsFlipped);
1096 }
1097
1098 CircleOutside2PtConicalEffect(GrContext* ctx,
1099 const SkTwoPointConicalGradient& shader,
1100 const SkMatrix& matrix,
1101 SkShader::TileMode tm,
1102 const CircleConicalInfo& info)
bsalomon4a339522015-10-06 08:40:50 -07001103 : INHERITED(ctx, shader, matrix, tm), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001104 this->initClassID<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001105 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001106 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001107 } else {
1108 fTLimit = SK_ScalarMin;
1109 }
1110
1111 fIsFlipped = shader.isFlippedGrad();
1112 }
1113
joshualittb0a8a372014-09-23 09:50:21 -07001114 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001115
1116 const CircleConicalInfo fInfo;
1117 SkScalar fTLimit;
1118 bool fIsFlipped;
1119
1120 typedef GrGradientEffect INHERITED;
1121};
1122
fmenozzi55d318d2016-08-09 08:05:57 -07001123class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1124 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001125public:
fmenozzi55d318d2016-08-09 08:05:57 -07001126 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
1127 virtual ~GLSLCircleOutside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001128
wangyix7c157a92015-07-22 15:08:53 -07001129 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001130
jvanverthcfc18862015-04-28 08:48:20 -07001131 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001132
1133protected:
egdaniel018fb622015-10-28 07:26:40 -07001134 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001135
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001136 UniformHandle fCenterUni;
1137 UniformHandle fParamUni;
1138
1139 const char* fVSVaryingName;
1140 const char* fFSVaryingName;
1141
1142 bool fIsFlipped;
1143
1144 // @{
1145 /// Values last uploaded as uniforms
1146
1147 SkScalar fCachedCenterX;
1148 SkScalar fCachedCenterY;
1149 SkScalar fCachedA;
1150 SkScalar fCachedB;
1151 SkScalar fCachedC;
1152 SkScalar fCachedTLimit;
1153
1154 // @}
1155
1156private:
fmenozzi55d318d2016-08-09 08:05:57 -07001157 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001158
1159};
1160
egdaniel57d3b032015-11-13 11:57:27 -08001161void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
1162 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001163 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001164}
1165
egdaniel57d3b032015-11-13 11:57:27 -08001166GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001167 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001168}
1169
joshualittb0a8a372014-09-23 09:50:21 -07001170GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001171
joshualitt01258472014-09-22 10:29:30 -07001172/*
1173 * All Two point conical gradient test create functions may occasionally create edge case shaders
1174 */
bungeman06ca8ec2016-06-09 08:01:03 -07001175sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001176 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1177 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001178 SkPoint center2;
1179 SkScalar radius2;
1180 SkScalar diffLen;
1181 do {
joshualitt0067ff52015-07-08 14:26:19 -07001182 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001183 // If the circles share a center than we can't be in the outside case
1184 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001185 SkPoint diff = center2 - center1;
1186 diffLen = diff.length();
1187 // Below makes sure that circle one is not contained within circle two
1188 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001189 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001190
1191 SkColor colors[kMaxRandomGradientColors];
1192 SkScalar stopsArray[kMaxRandomGradientColors];
1193 SkScalar* stops = stopsArray;
1194 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -07001195 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -08001196 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1197 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -07001198 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
1199 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -07001200 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
1201 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -07001202 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001203 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001204}
1205
fmenozzi55d318d2016-08-09 08:05:57 -07001206CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1207 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001208 : fVSVaryingName(nullptr)
1209 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001210 , fCachedCenterX(SK_ScalarMax)
1211 , fCachedCenterY(SK_ScalarMax)
1212 , fCachedA(SK_ScalarMax)
1213 , fCachedB(SK_ScalarMax)
1214 , fCachedC(SK_ScalarMax)
1215 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001216 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001217 fIsFlipped = data.isFlipped();
1218 }
1219
fmenozzi55d318d2016-08-09 08:05:57 -07001220void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001221 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001222 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1223 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -08001224 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001225 kVec2f_GrSLType, kDefault_GrSLPrecision,
1226 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001227 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001228 kVec4f_GrSLType, kDefault_GrSLPrecision,
1229 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001230 SkString tName("t");
1231
egdaniel7ea439b2015-12-03 09:20:44 -08001232 GrGLSLShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001233 // params.x = A
1234 // params.y = B
1235 // params.z = C
egdaniel7ea439b2015-12-03 09:20:44 -08001236 GrGLSLShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001237
1238 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001239 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
egdaniel4ca2e602015-11-18 08:01:26 -08001240 SkString coords2DString = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001241 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001242
1243 // output will default to transparent black (we simply won't write anything
1244 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001245 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 +00001246
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001247 // p = coords2D
1248 // e = center end
1249 // r = radius end
1250 // A = dot(e, e) - r^2 + 2 * r - 1
1251 // B = (r -1) / A
1252 // C = 1 / A
1253 // d = dot(e, p) + B
1254 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001255
egdaniel4ca2e602015-11-18 08:01:26 -08001256 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1257 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1258 params.c_str());
1259 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1260 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001261
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001262 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1263 // If so we must also flip sign on sqrt
1264 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001265 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001266 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001267 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001268 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001269
egdaniel7ea439b2015-12-03 09:20:44 -08001270 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1271 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001272 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001273 this->emitColor(fragBuilder,
1274 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -08001275 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001276 ge,
1277 tName.c_str(),
1278 args.fOutputColor,
1279 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001280 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001281 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001282}
1283
fmenozzi55d318d2016-08-09 08:05:57 -07001284void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
1285 const GrGLSLProgramDataManager& pdman,
egdaniel018fb622015-10-28 07:26:40 -07001286 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001287 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001288 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001289 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001290 SkScalar centerX = data.centerX();
1291 SkScalar centerY = data.centerY();
1292 SkScalar A = data.A();
1293 SkScalar B = data.B();
1294 SkScalar C = data.C();
1295 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001296
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001297 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1298 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001299
kkinnunen7510b222014-07-30 00:04:16 -07001300 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1301 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001302 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001303
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001304 fCachedCenterX = centerX;
1305 fCachedCenterY = centerY;
1306 fCachedA = A;
1307 fCachedB = B;
1308 fCachedC = C;
1309 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001310 }
1311}
1312
fmenozzi55d318d2016-08-09 08:05:57 -07001313void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1314 const GrProcessor& processor,
1315 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001316 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001317 key[0] = GenBaseGradientKey(processor);
1318 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001319}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001320
1321//////////////////////////////////////////////////////////////////////////////
1322
bungeman06ca8ec2016-06-09 08:01:03 -07001323sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(GrContext* ctx,
1324 const SkTwoPointConicalGradient& shader,
1325 SkShader::TileMode tm,
1326 const SkMatrix* localMatrix) {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001327 SkMatrix matrix;
1328 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001329 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001330 }
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001331 if (localMatrix) {
1332 SkMatrix inv;
1333 if (!localMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001334 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001335 }
1336 matrix.postConcat(inv);
1337 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001338
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001339 if (shader.getStartRadius() < kErrorTol) {
1340 SkScalar focalX;
1341 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1342 if (type == kInside_ConicalType) {
bungeman06ca8ec2016-06-09 08:01:03 -07001343 return FocalInside2PtConicalEffect::Make(ctx, shader, matrix, tm, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001344 } else if(type == kEdge_ConicalType) {
1345 set_matrix_edge_conical(shader, &matrix);
bungeman06ca8ec2016-06-09 08:01:03 -07001346 return Edge2PtConicalEffect::Make(ctx, shader, matrix, tm);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001347 } else {
bungeman06ca8ec2016-06-09 08:01:03 -07001348 return FocalOutside2PtConicalEffect::Make(ctx, shader, matrix, tm, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001349 }
1350 }
1351
1352 CircleConicalInfo info;
1353 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1354
1355 if (type == kInside_ConicalType) {
bungeman06ca8ec2016-06-09 08:01:03 -07001356 return CircleInside2PtConicalEffect::Make(ctx, shader, matrix, tm, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001357 } else if (type == kEdge_ConicalType) {
1358 set_matrix_edge_conical(shader, &matrix);
bungeman06ca8ec2016-06-09 08:01:03 -07001359 return Edge2PtConicalEffect::Make(ctx, shader, matrix, tm);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001360 } else {
bungeman06ca8ec2016-06-09 08:01:03 -07001361 return CircleOutside2PtConicalEffect::Make(ctx, shader, matrix, tm, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001362 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001363}
1364
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001365#endif