/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ layout(key) in GrClipEdgeType edgeType; layout(ctype=SkRect) in float4 rect; layout(ctype=SkRect) float4 prevRect = float4(-1); uniform float4 rectUniform; @optimizationFlags { kCompatibleWithCoverageAsAlpha_OptimizationFlag } void main() { half alpha; @switch (edgeType) { case GrClipEdgeType::kFillBW: // fall through case GrClipEdgeType::kInverseFillBW: // non-AA alpha = all(greaterThan(float4(sk_FragCoord.xy, rectUniform.zw), float4(rectUniform.xy, sk_FragCoord.xy))) ? 1 : 0; break; default: // The amount of coverage removed in x and y by the edges is computed as a pair of // negative numbers, xSub and ySub. half xSub, ySub; xSub = min(sk_FragCoord.x - rectUniform.x, 0.0); xSub += min(rectUniform.z - sk_FragCoord.x, 0.0); ySub = min(sk_FragCoord.y - rectUniform.y, 0.0); ySub += min(rectUniform.w - sk_FragCoord.y, 0.0); // Now compute coverage in x and y and multiply them to get the fraction of the pixel // covered. alpha = (1.0 + max(xSub, -1.0)) * (1.0 + max(ySub, -1.0)); } @if (edgeType == GrClipEdgeType::kInverseFillBW || edgeType == GrClipEdgeType::kInverseFillAA) { alpha = 1.0 - alpha; } sk_OutColor = sk_InColor * alpha; } @setData(pdman) { const SkRect& newRect = GrProcessorEdgeTypeIsAA(edgeType) ? rect.makeInset(.5f, .5f) : rect; if (newRect != prevRect) { pdman.set4f(rectUniform, newRect.fLeft, newRect.fTop, newRect.fRight, newRect.fBottom); prevRect = newRect; } } @test(d) { SkRect rect = SkRect::MakeLTRB(d->fRandom->nextSScalar1(), d->fRandom->nextSScalar1(), d->fRandom->nextSScalar1(), d->fRandom->nextSScalar1()); std::unique_ptr fp; do { GrClipEdgeType edgeType = static_cast( d->fRandom->nextULessThan(kGrClipEdgeTypeCnt)); fp = GrAARectEffect::Make(edgeType, rect); } while (nullptr == fp); return fp; }