// 1, 2, or 4 SkPMColors with 16-bit components. // This is most useful as the result of a multiply, e.g. from mulWiden(). class Wide { public:
Wide(const skvx::Vec<16, uint16_t>& v) : fV(v) {}
// The only 8-bit multiply we use is 8-bit x 8-bit -> 16-bit. Might as well make it pithy.
Wide operator * (const Sk4px& o) const { return this->mulWiden(o.fV); }
// Generally faster than (*this * o).div255(). // May be incorrect by +-1, but is always exactly correct when *this or o is 0 or 255.
Sk4px approxMulDiv255(const Sk4px& o) const { return Sk4px(approx_scale(fV, o.fV));
}
// A generic driver that maps fn over a src array into a dst array. // fn should take an Sk4px (4 src pixels) and return an Sk4px (4 dst pixels). template <typename Fn>
[[maybe_unused]] staticvoid MapSrc(int n, SkPMColor* dst, const SkPMColor* src, const Fn& fn) {
SkASSERT(dst);
SkASSERT(src); // This looks a bit odd, but it helps loop-invariant hoisting across different calls to fn. // Basically, we need to make sure we keep things inside a single loop. while (n > 0) { if (n >= 8) {
Sk4px dst0 = fn(Load4(src+0)),
dst4 = fn(Load4(src+4));
dst0.store4(dst+0);
dst4.store4(dst+4);
dst += 8; src += 8; n -= 8; continue; // Keep our stride at 8 pixels as long as possible.
}
SkASSERT(n <= 7); if (n >= 4) {
fn(Load4(src)).store4(dst);
dst += 4; src += 4; n -= 4;
} if (n >= 2) {
fn(Load2(src)).store2(dst);
dst += 2; src += 2; n -= 2;
} if (n >= 1) {
fn(Load1(src)).store1(dst);
} break;
}
}
// As above, but with dst4' = fn(dst4, src4). template <typename Fn>
[[maybe_unused]] staticvoid MapDstSrc(int n, SkPMColor* dst, const SkPMColor* src, const Fn& fn) {
SkASSERT(dst);
SkASSERT(src); while (n > 0) { if (n >= 8) {
Sk4px dst0 = fn(Load4(dst+0), Load4(src+0)),
dst4 = fn(Load4(dst+4), Load4(src+4));
dst0.store4(dst+0);
dst4.store4(dst+4);
dst += 8; src += 8; n -= 8; continue; // Keep our stride at 8 pixels as long as possible.
}
SkASSERT(n <= 7); if (n >= 4) {
fn(Load4(dst), Load4(src)).store4(dst);
dst += 4; src += 4; n -= 4;
} if (n >= 2) {
fn(Load2(dst), Load2(src)).store2(dst);
dst += 2; src += 2; n -= 2;
} if (n >= 1) {
fn(Load1(dst), Load1(src)).store1(dst);
} break;
}
}
// As above, but with dst4' = fn(dst4, alpha4). template <typename Fn>
[[maybe_unused]] staticvoid MapDstAlpha(int n, SkPMColor* dst, const SkAlpha* a, const Fn& fn) {
SkASSERT(dst);
SkASSERT(a); while (n > 0) { if (n >= 8) {
Sk4px dst0 = fn(Load4(dst+0), Load4Alphas(a+0)),
dst4 = fn(Load4(dst+4), Load4Alphas(a+4));
dst0.store4(dst+0);
dst4.store4(dst+4);
dst += 8; a += 8; n -= 8; continue; // Keep our stride at 8 pixels as long as possible.
}
SkASSERT(n <= 7); if (n >= 4) {
fn(Load4(dst), Load4Alphas(a)).store4(dst);
dst += 4; a += 4; n -= 4;
} if (n >= 2) {
fn(Load2(dst), Load2Alphas(a)).store2(dst);
dst += 2; a += 2; n -= 2;
} if (n >= 1) {
fn(Load1(dst), skvx::byte16(*a)).store1(dst);
} break;
}
}
// As above, but with dst4' = fn(dst4, src4, alpha4). template <typename Fn>
[[maybe_unused]] staticvoid MapDstSrcAlpha(int n, SkPMColor* dst, const SkPMColor* src, const SkAlpha* a, const Fn& fn) {
SkASSERT(dst);
SkASSERT(src);
SkASSERT(a); while (n > 0) { if (n >= 8) {
Sk4px dst0 = fn(Load4(dst+0), Load4(src+0), Load4Alphas(a+0)),
dst4 = fn(Load4(dst+4), Load4(src+4), Load4Alphas(a+4));
dst0.store4(dst+0);
dst4.store4(dst+4);
dst += 8; src += 8; a += 8; n -= 8; continue; // Keep our stride at 8 pixels as long as possible.
}
SkASSERT(n <= 7); if (n >= 4) {
fn(Load4(dst), Load4(src), Load4Alphas(a)).store4(dst);
dst += 4; src += 4; a += 4; n -= 4;
} if (n >= 2) {
fn(Load2(dst), Load2(src), Load2Alphas(a)).store2(dst);
dst += 2; src += 2; a += 2; n -= 2;
} if (n >= 1) {
fn(Load1(dst), Load1(src), skvx::byte16(*a)).store1(dst);
} break;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.