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
8// This controls the range of values added to color channels
9layout(key) in int rangeType;
10
11@make {
12    static std::unique_ptr<GrFragmentProcessor> Make(GrPixelConfig dstConfig) {
13        int rangeType;
14        switch (dstConfig) {
15            case kGray_8_GrPixelConfig:
16            case kGray_8_as_Lum_GrPixelConfig:
17            case kGray_8_as_Red_GrPixelConfig:
18            case kRGBA_8888_GrPixelConfig:
19            case kBGRA_8888_GrPixelConfig:
20            case kSRGBA_8888_GrPixelConfig:
21            case kSBGRA_8888_GrPixelConfig:
22                rangeType = 0;
23                break;
24            case kRGB_565_GrPixelConfig:
25                rangeType = 1;
26                break;
27            case kRGBA_4444_GrPixelConfig:
28                rangeType = 2;
29                break;
30            case kUnknown_GrPixelConfig:
31            case kAlpha_half_GrPixelConfig:
32            case kAlpha_half_as_Red_GrPixelConfig:
33            case kRGBA_8888_sint_GrPixelConfig:
34            case kRGBA_float_GrPixelConfig:
35            case kRG_float_GrPixelConfig:
36            case kRGBA_half_GrPixelConfig:
37            case kAlpha_8_GrPixelConfig:
38            case kAlpha_8_as_Alpha_GrPixelConfig:
39            case kAlpha_8_as_Red_GrPixelConfig:
40                return nullptr;
41        }
42        return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(rangeType));
43    }
44}
45
46void main() {
47    half value;
48    half range;
49    @switch (rangeType) {
50        case 0:
51            range = 1.0 / 255.0;
52            break;
53        case 1:
54            range = 1.0 / 63.0;
55            break;
56        default:
57            // Experimentally this looks better than the expected value of 1/15.
58            range = 1.0 / 15.0;
59            break;
60    }
61    @if (sk_Caps.integerSupport) {
62        // This ordered-dither code is lifted from the cpu backend.
63        uint x = uint(sk_FragCoord.x);
64        uint y = uint(sk_FragCoord.y);
65        uint m = (y & 1) << 5 | (x & 1) << 4 |
66                 (y & 2) << 2 | (x & 2) << 1 |
67                 (y & 4) >> 1 | (x & 4) >> 2;
68        value = half(m) * 1.0 / 64.0 - 63.0 / 128.0;
69    } else {
70        // Simulate the integer effect used above using step/mod. For speed, simulates a 4x4
71        // dither pattern rather than an 8x8 one.
72        half4 modValues = mod(sk_FragCoord.xyxy, half4(2.0, 2.0, 4.0, 4.0));
73        half4 stepValues = step(modValues, half4(1.0, 1.0, 2.0, 2.0));
74        value = dot(stepValues, half4(8.0 / 16.0, 4.0 / 16.0, 2.0 / 16.0, 1.0 / 16.0)) - 15.0 / 32.0;
75    }
76    // For each color channel, add the random offset to the channel value and then clamp
77    // between 0 and alpha to keep the color premultiplied.
78    sk_OutColor = half4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a);
79}
80
81@test(testData) {
82    float range = testData->fRandom->nextRangeF(0.001f, 0.05f);
83    return std::unique_ptr<GrFragmentProcessor>(new GrDitherEffect(range));
84}
85