1/* 2 * Copyright 2018 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 */ 7 8in half4x4 gradientMatrix; 9 10layout(tracked) in uniform half bias; 11layout(tracked) in uniform half scale; 12 13@coordTransform { 14 gradientMatrix 15} 16 17void main() { 18 // On some devices they incorrectly implement atan2(y,x) as atan(y/x). In actuality it is 19 // atan2(y,x) = 2 * atan(y / (sqrt(x^2 + y^2) + x)). So to work around this we pass in (sqrt(x^2 20 // + y^2) + x) as the second parameter to atan2 in these cases. We let the device handle the 21 // undefined behavior of the second paramenter being 0 instead of doing the divide ourselves and 22 // using atan instead. 23 half angle; 24 if (sk_Caps.atan2ImplementedAsAtanYOverX) { 25 angle = 2 * atan(-sk_TransformedCoords2D[0].y, 26 length(sk_TransformedCoords2D[0]) - sk_TransformedCoords2D[0].x); 27 } else { 28 angle = atan(-sk_TransformedCoords2D[0].y, -sk_TransformedCoords2D[0].x); 29 } 30 31 // 0.1591549430918 is 1/(2*pi), used since atan returns values [-pi, pi] 32 half t = (angle * 0.1591549430918 + 0.5 + bias) * scale; 33 sk_OutColor = half4(t, 1, 0, 0); // y = 1 for always valid 34} 35 36////////////////////////////////////////////////////////////////////////////// 37 38@header { 39 #include "SkSweepGradient.h" 40 #include "GrGradientShader.h" 41} 42 43// The sweep gradient never rejects a pixel so it doesn't change opacity 44@optimizationFlags { 45 kPreservesOpaqueInput_OptimizationFlag 46} 47 48@make { 49 static std::unique_ptr<GrFragmentProcessor> Make(const SkSweepGradient& gradient, 50 const GrFPArgs& args); 51} 52 53@cppEnd { 54 std::unique_ptr<GrFragmentProcessor> GrSweepGradientLayout::Make( 55 const SkSweepGradient& grad, const GrFPArgs& args) { 56 SkMatrix matrix; 57 if (!grad.totalLocalMatrix(args.fPreLocalMatrix, args.fPostLocalMatrix)->invert(&matrix)) { 58 return nullptr; 59 } 60 matrix.postConcat(grad.getGradientMatrix()); 61 return std::unique_ptr<GrFragmentProcessor>(new GrSweepGradientLayout( 62 matrix, grad.getTBias(), grad.getTScale())); 63 } 64} 65 66////////////////////////////////////////////////////////////////////////////// 67 68@test(d) { 69 SkScalar scale = GrGradientShader::RandomParams::kGradientScale; 70 SkPoint center = {d->fRandom->nextRangeScalar(0.0f, scale), 71 d->fRandom->nextRangeScalar(0.0f, scale)}; 72 73 GrGradientShader::RandomParams params(d->fRandom); 74 auto shader = params.fUseColors4f ? 75 SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors4f, params.fColorSpace, 76 params.fStops, params.fColorCount) : 77 SkGradientShader::MakeSweep(center.fX, center.fY, params.fColors, 78 params.fStops, params.fColorCount); 79 GrTest::TestAsFPArgs asFPArgs(d); 80 std::unique_ptr<GrFragmentProcessor> fp = as_SB(shader)->asFragmentProcessor(asFPArgs.args()); 81 GrAlwaysAssert(fp); 82 return fp; 83} 84