| Index: src/core/SkXfermode4f.cpp
|
| diff --git a/src/core/SkXfermode4f.cpp b/src/core/SkXfermode4f.cpp
|
| index b7f291371b38176c75b0fe520e0cb11caafad7a3..1f080246a28d37ad68dd979ca703d1750e9ed934 100644
|
| --- a/src/core/SkXfermode4f.cpp
|
| +++ b/src/core/SkXfermode4f.cpp
|
| @@ -45,76 +45,53 @@ static Sk4f linear_unit_to_srgb_255f(const Sk4f& l4) {
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| -static Sk4f scale_255_round(const SkPM4f& pm4) {
|
| - return Sk4f::Load(pm4.fVec) * Sk4f(255) + Sk4f(0.5f);
|
| -}
|
| -
|
| -static void pm4f_to_linear_32(SkPMColor dst[], const SkPM4f src[], int count) {
|
| - while (count >= 4) {
|
| - src[0].assertIsUnit();
|
| - src[1].assertIsUnit();
|
| - src[2].assertIsUnit();
|
| - src[3].assertIsUnit();
|
| - Sk4f_ToBytes((uint8_t*)dst,
|
| - scale_255_round(src[0]), scale_255_round(src[1]),
|
| - scale_255_round(src[2]), scale_255_round(src[3]));
|
| - src += 4;
|
| - dst += 4;
|
| - count -= 4;
|
| - }
|
| - for (int i = 0; i < count; ++i) {
|
| - src[i].assertIsUnit();
|
| - SkNx_cast<uint8_t>(scale_255_round(src[i])).store((uint8_t*)&dst[i]);
|
| - }
|
| -}
|
| -
|
| -///////////////////////////////////////////////////////////////////////////////////////////////////
|
| -// These are our fallback impl for the SkPM4f procs...
|
| -//
|
| -// They just convert the src color(s) into a linear SkPMColor value(s), and then
|
| -// call the existing virtual xfer32. This clear throws away data (converting floats to bytes)
|
| -// in the src, and ignores the sRGB flag, but should draw about the same as if the caller
|
| -// had passed in SkPMColor values directly.
|
| -//
|
| -
|
| -void xfer_pm4_proc_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f& src,
|
| - int count, const SkAlpha aa[]) {
|
| - uint32_t pm;
|
| - pm4f_to_linear_32(&pm, &src, 1);
|
| -
|
| - const int N = 128;
|
| - SkPMColor tmp[N];
|
| - sk_memset32(tmp, pm, SkMin32(count, N));
|
| - while (count > 0) {
|
| - const int n = SkMin32(count, N);
|
| - state.fXfer->xfer32(dst, tmp, n, aa);
|
| -
|
| - dst += n;
|
| - if (aa) {
|
| - aa += n;
|
| +template <DstType D> void general_1(const SkXfermode::PM4fState& state, uint32_t dst[],
|
| + const SkPM4f& src, int count, const SkAlpha aa[]) {
|
| + SkXfermodeProc4f proc = state.fXfer->getProc4f();
|
| + SkPM4f d;
|
| + if (aa) {
|
| + for (int i = 0; i < count; ++i) {
|
| + Sk4f d4 = load_dst<D>(dst[i]);
|
| + d4.store(d.fVec);
|
| + Sk4f r4 = Sk4f::Load(proc(src, d).fVec);
|
| + dst[i] = store_dst<D>(lerp(r4, d4, aa[i]));
|
| + }
|
| + } else {
|
| + for (int i = 0; i < count; ++i) {
|
| + load_dst<D>(dst[i]).store(d.fVec);
|
| + Sk4f r4 = Sk4f::Load(proc(src, d).fVec);
|
| + dst[i] = store_dst<D>(r4);
|
| }
|
| - count -= n;
|
| }
|
| }
|
|
|
| -void xfer_pm4_proc_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f src[],
|
| - int count, const SkAlpha aa[]) {
|
| - const int N = 128;
|
| - SkPMColor tmp[N];
|
| - while (count > 0) {
|
| - const int n = SkMin32(count, N);
|
| - pm4f_to_linear_32(tmp, src, n);
|
| - state.fXfer->xfer32(dst, tmp, n, aa);
|
| -
|
| - src += n;
|
| - dst += n;
|
| - if (aa) {
|
| - aa += n;
|
| +template <DstType D> void general_n(const SkXfermode::PM4fState& state, uint32_t dst[],
|
| + const SkPM4f src[], int count, const SkAlpha aa[]) {
|
| + SkXfermodeProc4f proc = state.fXfer->getProc4f();
|
| + SkPM4f d;
|
| + if (aa) {
|
| + for (int i = 0; i < count; ++i) {
|
| + Sk4f d4 = load_dst<D>(dst[i]);
|
| + d4.store(d.fVec);
|
| + Sk4f r4 = Sk4f::Load(proc(src[i], d).fVec);
|
| + dst[i] = store_dst<D>(lerp(r4, d4, aa[i]));
|
| + }
|
| + } else {
|
| + for (int i = 0; i < count; ++i) {
|
| + load_dst<D>(dst[i]).store(d.fVec);
|
| + Sk4f r4 = Sk4f::Load(proc(src[i], d).fVec);
|
| + dst[i] = store_dst<D>(r4);
|
| }
|
| - count -= n;
|
| }
|
| }
|
|
|
| +const XferProcPair gProcs_General[] = {
|
| + { general_1<kLinear_Dst>, general_n<kLinear_Dst> }, // linear alpha
|
| + { general_1<kLinear_Dst>, general_n<kLinear_Dst> }, // linear opaque
|
| + { general_1<kSRGB_Dst>, general_n<kSRGB_Dst> }, // srgb alpha
|
| + { general_1<kSRGB_Dst>, general_n<kSRGB_Dst> }, // srgb opaque
|
| +};
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
| static void clear_linear_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[],
|
| @@ -402,7 +379,7 @@ static XferProcPair find_procs(SkXfermode::Mode mode, uint32_t flags) {
|
| default:
|
| break;
|
| }
|
| - return { xfer_pm4_proc_1, xfer_pm4_proc_n };
|
| + return gProcs_General[flags];
|
| }
|
|
|
| SkXfermode::PM4fProc1 SkXfermode::GetPM4fProc1(Mode mode, uint32_t flags) {
|
| @@ -414,13 +391,19 @@ SkXfermode::PM4fProcN SkXfermode::GetPM4fProcN(Mode mode, uint32_t flags) {
|
| }
|
|
|
| SkXfermode::PM4fProc1 SkXfermode::getPM4fProc1(uint32_t flags) const {
|
| + SkASSERT(0 == (flags & ~3));
|
| + flags &= 3;
|
| +
|
| Mode mode;
|
| - return this->asMode(&mode) ? GetPM4fProc1(mode, flags) : xfer_pm4_proc_1;
|
| + return this->asMode(&mode) ? GetPM4fProc1(mode, flags) : gProcs_General[flags].fP1;
|
| }
|
|
|
| SkXfermode::PM4fProcN SkXfermode::getPM4fProcN(uint32_t flags) const {
|
| + SkASSERT(0 == (flags & ~3));
|
| + flags &= 3;
|
| +
|
| Mode mode;
|
| - return this->asMode(&mode) ? GetPM4fProcN(mode, flags) : xfer_pm4_proc_n;
|
| + return this->asMode(&mode) ? GetPM4fProcN(mode, flags) : gProcs_General[flags].fPN;
|
| }
|
|
|
| ///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|