| 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; | 
| } | 
|  | 
| /////////////////////////////////////////////////////////////////////////////////////////////////// | 
|  |