diff options
author | 2015-08-26 12:35:14 -0700 | |
---|---|---|
committer | 2015-08-26 12:35:14 -0700 | |
commit | 5015176adf046ef906a2313b6e6b64b72cc84898 (patch) | |
tree | 9900cf1febd39bec5c6dec6dc4f99f730870b6d1 /src/opts | |
parent | e46cf96ef5781ac40852bbf4f489bc47e2a2485e (diff) |
trifurcate blit_mask_d32_a8 into _black, _opaque, _general.
We used to split the NEON code this way, and just had one path for SSE.
It's unclear to me testing locally if there's any major win here, but there's at least a small one.
No pixel diffs or even any math changes, just folding constants through.
BUG=skia:4117
Review URL: https://codereview.chromium.org/1304373006
Diffstat (limited to 'src/opts')
-rw-r--r-- | src/opts/SkBlitMask_opts.h | 57 |
1 files changed, 53 insertions, 4 deletions
diff --git a/src/opts/SkBlitMask_opts.h b/src/opts/SkBlitMask_opts.h index 9129560ef4..d66323a8b0 100644 --- a/src/opts/SkBlitMask_opts.h +++ b/src/opts/SkBlitMask_opts.h @@ -12,11 +12,10 @@ namespace SK_OPTS_NS { -static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, - const SkAlpha* mask, size_t maskRB, - SkColor color, int w, int h) { +static void blit_mask_d32_a8_general(SkPMColor* dst, size_t dstRB, + const SkAlpha* mask, size_t maskRB, + SkColor color, int w, int h) { auto s = Sk4px::DupPMColor(SkPreMultiplyColor(color)); - auto fn = [&](const Sk4px& d, const Sk4px& aa) { // = (s + d(1-sa))aa + d(1-aa) // = s*aa + d(1-sa*aa) @@ -24,7 +23,26 @@ static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, right = d.approxMulDiv255(left.alphas().inv()); return left + right; // This does not overflow (exhaustively checked). }; + while (h --> 0) { + Sk4px::MapDstAlpha(w, dst, mask, fn); + dst += dstRB / sizeof(*dst); + mask += maskRB / sizeof(*mask); + } +} +// As above, but made slightly simpler by requiring that color is opaque. +static void blit_mask_d32_a8_opaque(SkPMColor* dst, size_t dstRB, + const SkAlpha* mask, size_t maskRB, + SkColor color, int w, int h) { + SkASSERT(SkColorGetA(color) == 0xFF); + auto s = Sk4px::DupPMColor(SkPreMultiplyColor(color)); + auto fn = [&](const Sk4px& d, const Sk4px& aa) { + // = (s + d(1-sa))aa + d(1-aa) + // = s*aa + d(1-sa*aa) + // ~~~> + // = s*aa + d(1-aa) + return s.approxMulDiv255(aa) + d.approxMulDiv255(aa.inv()); + }; while (h --> 0) { Sk4px::MapDstAlpha(w, dst, mask, fn); dst += dstRB / sizeof(*dst); @@ -32,6 +50,37 @@ static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, } } +// Same as _opaque, but assumes color == SK_ColorBLACK, a very common and even simpler case. +static void blit_mask_d32_a8_black(SkPMColor* dst, size_t dstRB, + const SkAlpha* mask, size_t maskRB, + int w, int h) { + auto fn = [](const Sk4px& d, const Sk4px& aa) { + // = (s + d(1-sa))aa + d(1-aa) + // = s*aa + d(1-sa*aa) + // ~~~> + // a = 1*aa + d(1-1*aa) = aa + d(1-aa) + // c = 0*aa + d(1-1*aa) = d(1-aa) + return aa.zeroColors() + d.approxMulDiv255(aa.inv()); + }; + while (h --> 0) { + Sk4px::MapDstAlpha(w, dst, mask, fn); + dst += dstRB / sizeof(*dst); + mask += maskRB / sizeof(*mask); + } +} + +static void blit_mask_d32_a8(SkPMColor* dst, size_t dstRB, + const SkAlpha* mask, size_t maskRB, + SkColor color, int w, int h) { + if (color == SK_ColorBLACK) { + blit_mask_d32_a8_black(dst, dstRB, mask, maskRB, w, h); + } else if (SkColorGetA(color) == 0xFF) { + blit_mask_d32_a8_opaque(dst, dstRB, mask, maskRB, color, w, h); + } else { + blit_mask_d32_a8_general(dst, dstRB, mask, maskRB, color, w, h); + } +} + } // SK_OPTS_NS #endif//SkBlitMask_opts_DEFINED |