aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/jumper/SkJumper_stages.cpp
diff options
context:
space:
mode:
authorGravatar Mike Klein <mtklein@chromium.org>2017-05-03 13:05:13 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-05-03 18:16:53 +0000
commit581e69865ef5425aa5c9dba173b346dff1ec5652 (patch)
tree455da6bb480b9c06b1f1bc71fbc6d36610771978 /src/jumper/SkJumper_stages.cpp
parent40226b46ad5fe7b7ee5098380fe8aef9f2318f45 (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.cpp30
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];