diff options
author | 2017-05-03 13:05:13 -0400 | |
---|---|---|
committer | 2017-05-03 18:16:53 +0000 | |
commit | 581e69865ef5425aa5c9dba173b346dff1ec5652 (patch) | |
tree | 455da6bb480b9c06b1f1bc71fbc6d36610771978 /src/jumper/SkJumper_stages.cpp | |
parent | 40226b46ad5fe7b7ee5098380fe8aef9f2318f45 (diff) |
dither stage
I think we can dither generically as a pipeline stage.
I'm not married to where the dither happens, or the implementation,
which is mostly cribbed from
https://en.wikipedia.org/wiki/Ordered_dithering.
BUG=skia:3302,skia:6224
Change-Id: If7f6b22a523ca0b34cb03c0aa97b6734c34e0133
Reviewed-on: https://skia-review.googlesource.com/15161
Commit-Queue: Mike Klein <mtklein@chromium.org>
Reviewed-by: Florin Malita <fmalita@chromium.org>
Reviewed-by: Herb Derby <herb@google.com>
Diffstat (limited to 'src/jumper/SkJumper_stages.cpp')
-rw-r--r-- | src/jumper/SkJumper_stages.cpp | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/src/jumper/SkJumper_stages.cpp b/src/jumper/SkJumper_stages.cpp index 83c806026f..b93b5a01fd 100644 --- a/src/jumper/SkJumper_stages.cpp +++ b/src/jumper/SkJumper_stages.cpp @@ -293,6 +293,36 @@ STAGE(seed_shader) { dr = dg = db = da = 0; } +STAGE(dither) { + auto c = (const SkJumper_DitherCtx*)ctx; + + // Get [(x,y), (x+1,y), (x+2,y), ...] loaded up in integer vectors. + U32 X = trunc_((int)x + unaligned_load<F>(k->iota)), // Going through float is kind of lazy.. + Y = (uint32_t)*c->y; + + // We're doing 8x8 ordered dithering, see https://en.wikipedia.org/wiki/Ordered_dithering. + // In this case n=8 and we're using the matrix that looks like 1/64 x [ 0 48 12 60 ... ]. + + // We only need X and X^Y from here on, so it's easier to just think of that as "Y". + Y ^= X; + + // We'll mix the bottom 3 bits of each of X and Y to make 6 bits, + // for 2^6 == 64 == 8x8 matrix values. If X=abc and Y=def, we make fcebda. + U32 M = (Y & 1) << 5 | (X & 1) << 4 + | (Y & 2) << 2 | (X & 2) << 1 + | (Y & 4) >> 1 | (X & 4) >> 2; + + // Scale that dither to [0,1], then [-0.5,+0.5]. + // I chose to scale by 1/63.0f here to make this exactly [0,1]. + // I suspect the divide by 64 in the article was written with fast integer math in mind. + F dither = cast(M) * (1/63.0f) - 0.5f; + + // Fold in an extra alpha to dither as if applied to the unpremul values of r,g,b. + r += c->rate*dither*a; + g += c->rate*dither*a; + b += c->rate*dither*a; +} + STAGE(constant_color) { auto rgba = (const float*)ctx; r = rgba[0]; |