1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
in uniform sampler2D mask;
in uniform half innerThreshold;
in uniform half outerThreshold;
@class {
inline OptimizationFlags optFlags(float outerThreshold);
}
@constructorParams {
const SkIRect& bounds
}
@make {
static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> mask,
float innerThreshold,
float outerThreshold,
const SkIRect& bounds) {
return std::unique_ptr<GrFragmentProcessor>(new GrAlphaThresholdFragmentProcessor(
mask, innerThreshold, outerThreshold, bounds));
}
}
@coordTransform(mask) {
SkMatrix::MakeTrans(SkIntToScalar(-bounds.x()), SkIntToScalar(-bounds.y()))
}
@cpp {
inline GrFragmentProcessor::OptimizationFlags GrAlphaThresholdFragmentProcessor::optFlags(
float outerThreshold) {
if (outerThreshold >= 1.0) {
return kPreservesOpaqueInput_OptimizationFlag |
kCompatibleWithCoverageAsAlpha_OptimizationFlag;
} else {
return kCompatibleWithCoverageAsAlpha_OptimizationFlag;
}
}
}
void main() {
half4 color = sk_InColor;
half4 mask_color = texture(mask, sk_TransformedCoords2D[0]);
if (mask_color.a < 0.5) {
if (color.a > outerThreshold) {
half scale = outerThreshold / color.a;
color.rgb *= scale;
color.a = outerThreshold;
}
} else if (color.a < innerThreshold) {
half scale = innerThreshold / max(0.001, color.a);
color.rgb *= scale;
color.a = innerThreshold;
}
sk_OutColor = color;
}
@test(testData) {
sk_sp<GrTextureProxy> maskProxy = testData->textureProxy(GrProcessorUnitTest::kAlphaTextureIdx);
// Make the inner and outer thresholds be in (0, 1) exclusive and be sorted correctly.
float innerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
float outerThresh = testData->fRandom->nextUScalar1() * .99f + 0.005f;
const int kMaxWidth = 1000;
const int kMaxHeight = 1000;
uint32_t width = testData->fRandom->nextULessThan(kMaxWidth);
uint32_t height = testData->fRandom->nextULessThan(kMaxHeight);
uint32_t x = testData->fRandom->nextULessThan(kMaxWidth - width);
uint32_t y = testData->fRandom->nextULessThan(kMaxHeight - height);
SkIRect bounds = SkIRect::MakeXYWH(x, y, width, height);
return GrAlphaThresholdFragmentProcessor::Make(std::move(maskProxy), innerThresh, outerThresh,
bounds);
}
|