1d2ed622a2fc574288b312ec1ff94c77ed6e70476reed/*
2d2ed622a2fc574288b312ec1ff94c77ed6e70476reed * Copyright 2016 Google Inc.
3d2ed622a2fc574288b312ec1ff94c77ed6e70476reed *
4d2ed622a2fc574288b312ec1ff94c77ed6e70476reed * Use of this source code is governed by a BSD-style license that can be
5d2ed622a2fc574288b312ec1ff94c77ed6e70476reed * found in the LICENSE file.
6d2ed622a2fc574288b312ec1ff94c77ed6e70476reed */
7d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
8d2ed622a2fc574288b312ec1ff94c77ed6e70476reed#include "SkHalf.h"
9d2ed622a2fc574288b312ec1ff94c77ed6e70476reed#include "SkPM4fPriv.h"
10d2ed622a2fc574288b312ec1ff94c77ed6e70476reed#include "SkUtils.h"
11d2ed622a2fc574288b312ec1ff94c77ed6e70476reed#include "SkXfermode.h"
12d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
13d2ed622a2fc574288b312ec1ff94c77ed6e70476reedstatic void sk_memset64(uint64_t dst[], uint64_t value, int count) {
14d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    for (int i = 0; i < count; ++i) {
15d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        dst[i] = value;
16d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    }
17d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
18d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
19d2ed622a2fc574288b312ec1ff94c77ed6e70476reedenum DstType {
20d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    kU16_Dst,
21d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    kF16_Dst,
22d2ed622a2fc574288b312ec1ff94c77ed6e70476reed};
23d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
24d2ed622a2fc574288b312ec1ff94c77ed6e70476reedstatic Sk4f lerp_by_coverage(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) {
25d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f));
26d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
27d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
28129ed1cd6d792f3f6cf563aefa9756fc6308289dreedtemplate <DstType D> Sk4f unit_to_bias(const Sk4f& x4) {
29d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    return (D == kU16_Dst) ? x4 * Sk4f(65535) : x4;
30d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
31d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
32129ed1cd6d792f3f6cf563aefa9756fc6308289dreedtemplate <DstType D> Sk4f bias_to_unit(const Sk4f& x4) {
33129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    return (D == kU16_Dst) ? x4 * Sk4f(1.0f/65535) : x4;
34129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
35129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
36d2ed622a2fc574288b312ec1ff94c77ed6e70476reed// returns value already biased by 65535
37d2ed622a2fc574288b312ec1ff94c77ed6e70476reedstatic Sk4f load_from_u16(uint64_t value) {
38d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    return SkNx_cast<float>(Sk4h::Load(&value));
39d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
40d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
41d2ed622a2fc574288b312ec1ff94c77ed6e70476reed// takes floats already biased by 65535
42d2ed622a2fc574288b312ec1ff94c77ed6e70476reedstatic uint64_t store_to_u16(const Sk4f& x4) {
43d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    uint64_t value;
44d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    SkNx_cast<uint16_t>(x4 + Sk4f(0.5f)).store(&value);
45d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    return value;
46d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
47d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
48d2ed622a2fc574288b312ec1ff94c77ed6e70476reed// Returns dst in its "natural" bias (either unit-float or 16bit int)
49d2ed622a2fc574288b312ec1ff94c77ed6e70476reed//
50d2ed622a2fc574288b312ec1ff94c77ed6e70476reedtemplate <DstType D> Sk4f load_from_dst(uint64_t dst) {
51fff055cc5f9ca5015678f4f13a4f842084bd62d5mtklein    return (D == kU16_Dst) ? load_from_u16(dst) : SkHalfToFloat_01(dst);
52d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
53d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
54d2ed622a2fc574288b312ec1ff94c77ed6e70476reed// Assumes x4 is already in the "natural" bias (either unit-float or 16bit int)
55d2ed622a2fc574288b312ec1ff94c77ed6e70476reedtemplate <DstType D> uint64_t store_to_dst(const Sk4f& x4) {
56fff055cc5f9ca5015678f4f13a4f842084bd62d5mtklein    return (D == kU16_Dst) ? store_to_u16(x4) : SkFloatToHalf_01(x4);
57d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
58d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
594b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reedstatic inline Sk4f pm_to_rgba_order(const Sk4f& x) {
604b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed    if (SkPM4f::R == 0) {
614b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed        return x;   // we're already RGBA
624b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed    } else {
634b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed        // we're BGRA, so swap R and B
644b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed        return SkNx_shuffle<2, 1, 0, 3>(x);
654b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed    }
664b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed}
674b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed
68d2ed622a2fc574288b312ec1ff94c77ed6e70476reed///////////////////////////////////////////////////////////////////////////////////////////////////
69d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
708f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void xfer_u64_1(const SkXfermode* xfer, uint64_t dst[],
718f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                                     const SkPM4f* src, int count, const SkAlpha aa[]) {
728f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermodeProc4f proc = xfer->getProc4f();
73129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkPM4f d;
74129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (aa) {
75129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        for (int i = 0; i < count; ++i) {
76129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            Sk4f d4 = bias_to_unit<D>(load_from_dst<D>(dst[i]));
77129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            d4.store(d.fVec);
788f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(*src, d).fVec));
79129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            dst[i] = store_to_dst<D>(lerp_by_coverage(r4, d4, aa[i]));
80129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
81129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
82129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        for (int i = 0; i < count; ++i) {
83129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            bias_to_unit<D>(load_from_dst<D>(dst[i])).store(d.fVec);
848f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(*src, d).fVec));
85129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            dst[i] = store_to_dst<D>(r4);
86129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
87129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
88129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
89129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
908f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void xfer_u64_n(const SkXfermode* xfer, uint64_t dst[],
91129ed1cd6d792f3f6cf563aefa9756fc6308289dreed                                     const SkPM4f src[], int count, const SkAlpha aa[]) {
928f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkXfermodeProc4f proc = xfer->getProc4f();
93129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    SkPM4f d;
94129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    if (aa) {
95129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        for (int i = 0; i < count; ++i) {
96129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            Sk4f d4 = bias_to_unit<D>(load_from_dst<D>(dst[i]));
97129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            d4.store(d.fVec);
98129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(src[i], d).fVec));
99129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            dst[i] = store_to_dst<D>(lerp_by_coverage(r4, d4, aa[i]));
100129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
101129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    } else {
102129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        for (int i = 0; i < count; ++i) {
103129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            bias_to_unit<D>(load_from_dst<D>(dst[i])).store(d.fVec);
104129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(src[i], d).fVec));
105129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            dst[i] = store_to_dst<D>(r4);
106129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        }
107129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    }
108129ed1cd6d792f3f6cf563aefa9756fc6308289dreed}
109129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1108f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedconst SkXfermode::D64Proc gProcs_General[] = {
1118f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    xfer_u64_n<kU16_Dst>,   xfer_u64_n<kU16_Dst>,
1128f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    xfer_u64_1<kU16_Dst>,   xfer_u64_1<kU16_Dst>,
1138f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    xfer_u64_n<kF16_Dst>,   xfer_u64_n<kF16_Dst>,
1148f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    xfer_u64_1<kF16_Dst>,   xfer_u64_1<kF16_Dst>,
115129ed1cd6d792f3f6cf563aefa9756fc6308289dreed};
116129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
117129ed1cd6d792f3f6cf563aefa9756fc6308289dreed///////////////////////////////////////////////////////////////////////////////////////////////////
118129ed1cd6d792f3f6cf563aefa9756fc6308289dreed
1198f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void clear(const SkXfermode*, uint64_t dst[],
1208f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                                const SkPM4f*, int count, const SkAlpha aa[]) {
1218f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    if (aa) {
1228f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        for (int i = 0; i < count; ++i) {
1238f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            if (aa[i]) {
1248f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                const Sk4f d4 = load_from_dst<D>(dst[i]);
1258f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                dst[i] = store_to_dst<D>(d4 * Sk4f((255 - aa[i]) * 1.0f/255));
1268f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed            }
1278f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        }
1288f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    } else {
1298f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        sk_memset64(dst, 0, count);
1308f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    }
1318f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed}
1328f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
1338f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedconst SkXfermode::D64Proc gProcs_Clear[] = {
1348f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    clear<kU16_Dst>,    clear<kU16_Dst>,
1358f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    clear<kU16_Dst>,    clear<kU16_Dst>,
1368f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    clear<kF16_Dst>,    clear<kF16_Dst>,
1378f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    clear<kF16_Dst>,    clear<kF16_Dst>,
1388f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed};
1398f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
1408f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed///////////////////////////////////////////////////////////////////////////////////////////////////
1418f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
1428f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void src_1(const SkXfermode*, uint64_t dst[],
1438f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                                const SkPM4f* src, int count, const SkAlpha aa[]) {
1448f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src->fVec)));
145d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    if (aa) {
146d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        for (int i = 0; i < count; ++i) {
147d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            const Sk4f d4 = load_from_dst<D>(dst[i]);
148d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(lerp_by_coverage(s4, d4, aa[i]));
149d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        }
150d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    } else {
151d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        sk_memset64(dst, store_to_dst<D>(s4), count);
152d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    }
153d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
154d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
1558f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void src_n(const SkXfermode*, uint64_t dst[],
156d2ed622a2fc574288b312ec1ff94c77ed6e70476reed                                const SkPM4f src[], int count, const SkAlpha aa[]) {
157d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    if (aa) {
158d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        for (int i = 0; i < count; ++i) {
159129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src[i].fVec)));
160d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            const Sk4f d4 = load_from_dst<D>(dst[i]);
161d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(lerp_by_coverage(s4, d4, aa[i]));
162d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        }
163d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    } else {
164d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        for (int i = 0; i < count; ++i) {
165129ed1cd6d792f3f6cf563aefa9756fc6308289dreed            const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src[i].fVec)));
166d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(s4);
167d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        }
168d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    }
169d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
170d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
1718f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedconst SkXfermode::D64Proc gProcs_Src[] = {
1728f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    src_n<kU16_Dst>,    src_n<kU16_Dst>,
1738f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    src_1<kU16_Dst>,    src_1<kU16_Dst>,
1748f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    src_n<kF16_Dst>,    src_n<kF16_Dst>,
1758f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    src_1<kF16_Dst>,    src_1<kF16_Dst>,
176d2ed622a2fc574288b312ec1ff94c77ed6e70476reed};
177d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
178d2ed622a2fc574288b312ec1ff94c77ed6e70476reed///////////////////////////////////////////////////////////////////////////////////////////////////
179d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
1808f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedstatic void dst(const SkXfermode*, uint64_t*, const SkPM4f*, int count, const SkAlpha[]) {}
1818f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
1828f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedconst SkXfermode::D64Proc gProcs_Dst[] = {
1838f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    dst, dst, dst, dst, dst, dst, dst, dst,
1848f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed};
1858f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
1868f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed///////////////////////////////////////////////////////////////////////////////////////////////////
1878f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
1888f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void srcover_1(const SkXfermode*, uint64_t dst[],
1898f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed                                    const SkPM4f* src, int count, const SkAlpha aa[]) {
1908f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src->fVec));
191d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
192129ed1cd6d792f3f6cf563aefa9756fc6308289dreed    const Sk4f s4bias = unit_to_bias<D>(s4);
193d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    for (int i = 0; i < count; ++i) {
194d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        const Sk4f d4bias = load_from_dst<D>(dst[i]);
195d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        const Sk4f r4bias = s4bias + d4bias * dst_scale;
196d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        if (aa) {
197d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(lerp_by_coverage(r4bias, d4bias, aa[i]));
198d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        } else {
199d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(r4bias);
200d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        }
201d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    }
202d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
203d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
2048f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedtemplate <DstType D> void srcover_n(const SkXfermode*, uint64_t dst[],
205d2ed622a2fc574288b312ec1ff94c77ed6e70476reed                                    const SkPM4f src[], int count, const SkAlpha aa[]) {
206d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    for (int i = 0; i < count; ++i) {
2074b25cf0bc0ee91fdb9351bbdd284f23c0d9919b1reed        const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src[i].fVec));
208d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
209129ed1cd6d792f3f6cf563aefa9756fc6308289dreed        const Sk4f s4bias = unit_to_bias<D>(s4);
210d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        const Sk4f d4bias = load_from_dst<D>(dst[i]);
211d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        const Sk4f r4bias = s4bias + d4bias * dst_scale;
212d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        if (aa) {
213d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(lerp_by_coverage(r4bias, d4bias, aa[i]));
214d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        } else {
215d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            dst[i] = store_to_dst<D>(r4bias);
216d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        }
217d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    }
218d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
219d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
2208f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedconst SkXfermode::D64Proc gProcs_SrcOver[] = {
2218f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    srcover_n<kU16_Dst>,    src_n<kU16_Dst>,
2228f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    srcover_1<kU16_Dst>,    src_1<kU16_Dst>,
2238f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    srcover_n<kF16_Dst>,    src_n<kF16_Dst>,
2248f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    srcover_1<kF16_Dst>,    src_1<kF16_Dst>,
225d2ed622a2fc574288b312ec1ff94c77ed6e70476reed};
226d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
227d2ed622a2fc574288b312ec1ff94c77ed6e70476reed///////////////////////////////////////////////////////////////////////////////////////////////////
228d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
2298f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedstatic SkXfermode::D64Proc find_proc(SkXfermode::Mode mode, uint32_t flags) {
2308f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkASSERT(0 == (flags & ~7));
2318f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    flags &= 7;
232d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
233d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    switch (mode) {
2348f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        case SkXfermode::kClear_Mode:   return gProcs_Clear[flags];
2358f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        case SkXfermode::kSrc_Mode:     return gProcs_Src[flags];
2368f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        case SkXfermode::kDst_Mode:     return gProcs_Dst[flags];
2378f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed        case SkXfermode::kSrcOver_Mode: return gProcs_SrcOver[flags];
238d2ed622a2fc574288b312ec1ff94c77ed6e70476reed        default:
239d2ed622a2fc574288b312ec1ff94c77ed6e70476reed            break;
240d2ed622a2fc574288b312ec1ff94c77ed6e70476reed    }
2418f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    return gProcs_General[flags];
242d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
243d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
2448f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedSkXfermode::D64Proc SkXfermode::onGetD64Proc(uint32_t flags) const {
2458f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    SkASSERT(0 == (flags & ~7));
2468f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    flags &= 7;
2478f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
2488f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    Mode mode;
2498f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    return this->asMode(&mode) ? find_proc(mode, flags) : gProcs_General[flags];
250d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
251d2ed622a2fc574288b312ec1ff94c77ed6e70476reed
2528f7b0b2d809510d4af4e6ff6f731bac78eded6c4reedSkXfermode::D64Proc SkXfermode::GetD64Proc(SkXfermode* xfer, uint32_t flags) {
2538f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed    return xfer ? xfer->onGetD64Proc(flags) : find_proc(SkXfermode::kSrcOver_Mode, flags);
254d2ed622a2fc574288b312ec1ff94c77ed6e70476reed}
2558f7b0b2d809510d4af4e6ff6f731bac78eded6c4reed
256