blob: 937efae2649e27e125b7f346a86e09ed602f50cb [file] [log] [blame]
Brian Salomon0c15ae82017-07-19 15:39:56 +00001// This controls the range of values added to color channels
2layout(key) in int rangeType;
Brian Salomonf2290cb2017-07-18 21:13:04 +00003
Brian Salomon0c15ae82017-07-19 15:39:56 +00004@make {
5 static sk_sp<GrFragmentProcessor> Make(GrPixelConfig dstConfig) {
6 int rangeType;
7 switch (dstConfig) {
8 case kGray_8_GrPixelConfig:
9 case kRGBA_8888_GrPixelConfig:
10 case kBGRA_8888_GrPixelConfig:
11 case kSRGBA_8888_GrPixelConfig:
12 case kSBGRA_8888_GrPixelConfig:
13 rangeType = 0;
14 break;
15 case kRGB_565_GrPixelConfig:
16 rangeType = 1;
17 break;
18 case kRGBA_4444_GrPixelConfig:
19 rangeType = 2;
20 break;
21 case kUnknown_GrPixelConfig:
22 case kAlpha_half_GrPixelConfig:
23 case kRGBA_8888_sint_GrPixelConfig:
24 case kRGBA_float_GrPixelConfig:
25 case kRG_float_GrPixelConfig:
26 case kRGBA_half_GrPixelConfig:
27 case kAlpha_8_GrPixelConfig:
28 return nullptr;
29 }
30 return sk_sp<GrFragmentProcessor>(new GrDitherEffect(rangeType));
31 }
32}
33
34void main() {
35 float value;
36 float range;
37 @switch (rangeType) {
38 case 0:
39 range = 1.0 / 255.0;
40 break;
41 case 1:
42 range = 1.0 / 63.0;
43 break;
44 default:
45 // Experimentally this looks better than the expected value of 1/15.
46 range = 0.125 / 15.0;
47 break;
48 }
49 @if (sk_Caps.integerSupport) {
50 // This ordered-dither code is lifted from the cpu backend.
51 int x = int(sk_FragCoord.x);
52 int y = int(sk_FragCoord.y);
53 uint m = (y & 1) << 5 | (x & 1) << 4 |
54 (y & 2) << 2 | (x & 2) << 1 |
55 (y & 4) >> 1 | (x & 4) >> 2;
56 value = float(m) * 1.0 / 64.0 - 63.0 / 128.0;
57 } else {
58 // Generate a random number based on the fragment position. For this
59 // random number generator, we use the "GLSL rand" function
60 // that seems to be floating around on the internet. It works under
61 // the assumption that sin(<big number>) oscillates with high frequency
62 // and sampling it will generate "randomness". Since we're using this
63 // for rendering and not cryptography it should be OK.
64 value = fract(sin(dot(sk_FragCoord.xy, vec2(12.9898, 78.233))) * 43758.5453) - .5;
65 }
66 // For each color channel, add the random offset to the channel value and then clamp
67 // between 0 and alpha to keep the color premultiplied.
68 sk_OutColor = vec4(clamp(sk_InColor.rgb + value * range, 0, sk_InColor.a), sk_InColor.a);
Ethan Nicholas762466e2017-06-29 10:03:38 -040069}
70
71@test(testData) {
Brian Salomon0c15ae82017-07-19 15:39:56 +000072 float range = testData->fRandom->nextRangeF(0.001f, 0.05f);
73 return sk_sp<GrFragmentProcessor>(new GrDitherEffect(range));
74}