aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/opts
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2015-08-26 12:35:14 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-08-26 12:35:14 -0700
commit5015176adf046ef906a2313b6e6b64b72cc84898 (patch)
tree9900cf1febd39bec5c6dec6dc4f99f730870b6d1 /src/opts
parente46cf96ef5781ac40852bbf4f489bc47e2a2485e (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.h57
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