Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2016 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkPM4fPriv.h"
      9 #include "SkUtils.h"
     10 #include "SkXfermodePriv.h"
     11 #include "Sk4x4f.h"
     12 
     13 static SkPM4f rgba_to_pmcolor_order(const SkPM4f& x) {
     14 #ifdef SK_PMCOLOR_IS_BGRA
     15     return {{ x.fVec[2], x.fVec[1], x.fVec[0], x.fVec[3] }};
     16 #else
     17     return x;
     18 #endif
     19 }
     20 
     21 enum DstType {
     22     kLinear_Dst,
     23     kSRGB_Dst,
     24 };
     25 
     26 static Sk4f scale_by_coverage(const Sk4f& x4, uint8_t coverage) {
     27     return x4 * Sk4f(coverage * (1/255.0f));
     28 }
     29 
     30 static Sk4f lerp(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) {
     31     return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f));
     32 }
     33 
     34 template <DstType D> Sk4f load_dst(SkPMColor dstC) {
     35     return (D == kSRGB_Dst) ? Sk4f_fromS32(dstC) : Sk4f_fromL32(dstC);
     36 }
     37 
     38 template <DstType D> uint32_t store_dst(const Sk4f& x4) {
     39     return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4);
     40 }
     41 
     42 static Sk4x4f load_4_srgb(const void* vptr) {
     43     auto ptr = (const uint32_t*)vptr;
     44 
     45     Sk4x4f rgba;
     46 
     47     rgba.r = { sk_linear_from_srgb[(ptr[0] >>  0) & 0xff],
     48                sk_linear_from_srgb[(ptr[1] >>  0) & 0xff],
     49                sk_linear_from_srgb[(ptr[2] >>  0) & 0xff],
     50                sk_linear_from_srgb[(ptr[3] >>  0) & 0xff] };
     51 
     52     rgba.g = { sk_linear_from_srgb[(ptr[0] >>  8) & 0xff],
     53                sk_linear_from_srgb[(ptr[1] >>  8) & 0xff],
     54                sk_linear_from_srgb[(ptr[2] >>  8) & 0xff],
     55                sk_linear_from_srgb[(ptr[3] >>  8) & 0xff] };
     56 
     57     rgba.b = { sk_linear_from_srgb[(ptr[0] >> 16) & 0xff],
     58                sk_linear_from_srgb[(ptr[1] >> 16) & 0xff],
     59                sk_linear_from_srgb[(ptr[2] >> 16) & 0xff],
     60                sk_linear_from_srgb[(ptr[3] >> 16) & 0xff] };
     61 
     62     rgba.a = SkNx_cast<float>((Sk4i::Load(ptr) >> 24) & 0xff) * (1/255.0f);
     63 
     64     return rgba;
     65 }
     66 
     67 static void store_4_srgb(void* ptr, const Sk4x4f& p) {
     68     ( sk_linear_to_srgb(p.r) <<  0
     69     | sk_linear_to_srgb(p.g) <<  8
     70     | sk_linear_to_srgb(p.b) << 16
     71     | Sk4f_round(255.0f*p.a) << 24).store(ptr);
     72 }
     73 
     74 ///////////////////////////////////////////////////////////////////////////////////////////////////
     75 
     76 template <DstType D> void general_1(SkBlendMode mode, uint32_t dst[],
     77                                     const SkPM4f* src, int count, const SkAlpha aa[]) {
     78     const SkPM4f s = rgba_to_pmcolor_order(*src);
     79     SkXfermodeProc4f proc = SkXfermode::GetProc4f(mode);
     80     SkPM4f d;
     81     if (aa) {
     82         for (int i = 0; i < count; ++i) {
     83             Sk4f d4 = load_dst<D>(dst[i]);
     84             d4.store(d.fVec);
     85             Sk4f r4 = Sk4f::Load(proc(s, d).fVec);
     86             dst[i] = store_dst<D>(lerp(r4, d4, aa[i]));
     87         }
     88     } else {
     89         for (int i = 0; i < count; ++i) {
     90             load_dst<D>(dst[i]).store(d.fVec);
     91             Sk4f r4 = Sk4f::Load(proc(s, d).fVec);
     92             dst[i] = store_dst<D>(r4);
     93         }
     94     }
     95 }
     96 
     97 template <DstType D> void general_n(SkBlendMode mode, uint32_t dst[],
     98                                     const SkPM4f src[], int count, const SkAlpha aa[]) {
     99     SkXfermodeProc4f proc = SkXfermode::GetProc4f(mode);
    100     SkPM4f d;
    101     if (aa) {
    102         for (int i = 0; i < count; ++i) {
    103             Sk4f d4 = load_dst<D>(dst[i]);
    104             d4.store(d.fVec);
    105             Sk4f r4 = Sk4f::Load(proc(rgba_to_pmcolor_order(src[i]), d).fVec);
    106             dst[i] = store_dst<D>(lerp(r4, d4, aa[i]));
    107         }
    108     } else {
    109         for (int i = 0; i < count; ++i) {
    110             load_dst<D>(dst[i]).store(d.fVec);
    111             Sk4f r4 = Sk4f::Load(proc(rgba_to_pmcolor_order(src[i]), d).fVec);
    112             dst[i] = store_dst<D>(r4);
    113         }
    114     }
    115 }
    116 
    117 const SkXfermode::D32Proc gProcs_General[] = {
    118     general_n<kLinear_Dst>, general_n<kLinear_Dst>,
    119     general_1<kLinear_Dst>, general_1<kLinear_Dst>,
    120     general_n<kSRGB_Dst>,   general_n<kSRGB_Dst>,
    121     general_1<kSRGB_Dst>,   general_1<kSRGB_Dst>,
    122 };
    123 
    124 ///////////////////////////////////////////////////////////////////////////////////////////////////
    125 
    126 static void clear_linear(SkBlendMode, uint32_t dst[], const SkPM4f[], int count,
    127                          const SkAlpha aa[]) {
    128     if (aa) {
    129         for (int i = 0; i < count; ++i) {
    130             unsigned a = aa[i];
    131             if (a) {
    132                 SkPMColor dstC = dst[i];
    133                 SkPMColor C = 0;
    134                 if (0xFF != a) {
    135                     C = SkFourByteInterp(C, dstC, a);
    136                 }
    137                 dst[i] = C;
    138             }
    139         }
    140     } else {
    141         sk_memset32(dst, 0, count);
    142     }
    143 }
    144 
    145 static void clear_srgb(SkBlendMode, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) {
    146     if (aa) {
    147         for (int i = 0; i < count; ++i) {
    148             if (aa[i]) {
    149                 Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - aa[i]) * (1/255.0f));
    150                 dst[i] = Sk4f_toS32(d);
    151             }
    152         }
    153     } else {
    154         sk_memset32(dst, 0, count);
    155     }
    156 }
    157 
    158 const SkXfermode::D32Proc gProcs_Clear[] = {
    159     clear_linear,   clear_linear,
    160     clear_linear,   clear_linear,
    161     clear_srgb,     clear_srgb,
    162     clear_srgb,     clear_srgb,
    163 };
    164 
    165 ///////////////////////////////////////////////////////////////////////////////////////////////////
    166 
    167 template <DstType D> void src_n(SkBlendMode, uint32_t dst[], const SkPM4f src[], int count,
    168                                 const SkAlpha aa[]) {
    169     for (int i = 0; i < count; ++i) {
    170         unsigned a = 0xFF;
    171         if (aa) {
    172             a = aa[i];
    173             if (0 == a) {
    174                 continue;
    175             }
    176         }
    177         Sk4f r4 = src[i].to4f_pmorder();
    178         if (a != 0xFF) {
    179             Sk4f d4 = load_dst<D>(dst[i]);
    180             r4 = lerp(r4, d4, a);
    181         }
    182         dst[i] = store_dst<D>(r4);
    183     }
    184 }
    185 
    186 static Sk4f lerp(const Sk4f& src, const Sk4f& dst, const Sk4f& src_scale) {
    187     return dst + (src - dst) * src_scale;
    188 }
    189 
    190 template <DstType D> void src_1(SkBlendMode, uint32_t dst[], const SkPM4f* src, int count,
    191                                 const SkAlpha aa[]) {
    192     const Sk4f s4 = src->to4f_pmorder();
    193 
    194     if (aa) {
    195         SkPMColor srcColor = store_dst<D>(s4);
    196         while (count-- > 0) {
    197             SkAlpha cover = *aa++;
    198             switch (cover) {
    199                 case 0xFF: {
    200                     *dst++ = srcColor;
    201                     break;
    202                 }
    203                 case 0x00: {
    204                     dst++;
    205                     break;
    206                 }
    207                 default: {
    208                     Sk4f d4 = load_dst<D>(*dst);
    209                     *dst++ = store_dst<D>(lerp(s4, d4, cover));
    210                 }
    211             }
    212         }
    213     } else {
    214         sk_memset32(dst, store_dst<D>(s4), count);
    215     }
    216 }
    217 
    218 const SkXfermode::D32Proc gProcs_Src[] = {
    219     src_n<kLinear_Dst>, src_n<kLinear_Dst>,
    220     src_1<kLinear_Dst>, src_1<kLinear_Dst>,
    221     src_n<kSRGB_Dst>,   src_n<kSRGB_Dst>,
    222     src_1<kSRGB_Dst>,   src_1<kSRGB_Dst>,
    223 };
    224 
    225 ///////////////////////////////////////////////////////////////////////////////////////////////////
    226 
    227 static void dst(SkBlendMode, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) {}
    228 
    229 const SkXfermode::D32Proc gProcs_Dst[] = {
    230     dst, dst, dst, dst, dst, dst, dst, dst,
    231 };
    232 
    233 ///////////////////////////////////////////////////////////////////////////////////////////////////
    234 
    235 
    236 template <DstType D> void srcover_n(SkBlendMode, uint32_t dst[], const SkPM4f src[], int count,
    237                                     const SkAlpha aa[]) {
    238     if (aa) {
    239         for (int i = 0; i < count; ++i) {
    240             unsigned a = aa[i];
    241             if (0 == a) {
    242                 continue;
    243             }
    244             Sk4f s4 = src[i].to4f_pmorder();
    245             Sk4f d4 = load_dst<D>(dst[i]);
    246             if (a != 0xFF) {
    247                 s4 = scale_by_coverage(s4, a);
    248             }
    249             Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
    250             dst[i] = store_dst<D>(r4);
    251         }
    252     } else {
    253         while (count >= 4 && D == kSRGB_Dst) {
    254             auto d = load_4_srgb(dst);
    255             auto s = Sk4x4f::Transpose(src->fVec);
    256         #if defined(SK_PMCOLOR_IS_BGRA)
    257             SkTSwap(s.r, s.b);
    258         #endif
    259             auto invSA = 1.0f - s.a;
    260             auto r = s.r + d.r * invSA,
    261                  g = s.g + d.g * invSA,
    262                  b = s.b + d.b * invSA,
    263                  a = s.a + d.a * invSA;
    264             store_4_srgb(dst, Sk4x4f{r,g,b,a});
    265             count -= 4;
    266             dst += 4;
    267             src += 4;
    268         }
    269         for (int i = 0; i < count; ++i) {
    270             Sk4f s4 = src[i].to4f_pmorder();
    271             Sk4f d4 = load_dst<D>(dst[i]);
    272             Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
    273             dst[i] = store_dst<D>(r4);
    274         }
    275     }
    276 }
    277 
    278 static void srcover_linear_dst_1(SkBlendMode, uint32_t dst[], const SkPM4f* src, int count,
    279                                  const SkAlpha aa[]) {
    280     const Sk4f s4 = src->to4f_pmorder();
    281     const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
    282 
    283     if (aa) {
    284         for (int i = 0; i < count; ++i) {
    285             unsigned a = aa[i];
    286             if (0 == a) {
    287                 continue;
    288             }
    289             Sk4f d4 = Sk4f_fromL32(dst[i]);
    290             Sk4f r4;
    291             if (a != 0xFF) {
    292                 Sk4f s4_aa = scale_by_coverage(s4, a);
    293                 r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa));
    294             } else {
    295                 r4 = s4 + d4 * dst_scale;
    296             }
    297             dst[i] = Sk4f_toL32(r4);
    298         }
    299     } else {
    300         for (int i = 0; i < count; ++i) {
    301             Sk4f d4 = Sk4f_fromL32(dst[i]);
    302             dst[i] = Sk4f_toL32(s4 + d4 * dst_scale);
    303         }
    304     }
    305 }
    306 
    307 static void srcover_srgb_dst_1(SkBlendMode, uint32_t dst[], const SkPM4f* src, int count,
    308                                const SkAlpha aa[]) {
    309     Sk4f s4 = src->to4f_pmorder();
    310     Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
    311 
    312     if (aa) {
    313         for (int i = 0; i < count; ++i) {
    314             unsigned a = aa[i];
    315             if (0 == a) {
    316                 continue;
    317             }
    318 
    319             Sk4f d4 = Sk4f_fromS32(dst[i]);
    320             Sk4f r4;
    321             if (a != 0xFF) {
    322                 const Sk4f s4_aa = scale_by_coverage(s4, a);
    323                 r4 = s4_aa + d4 * Sk4f(1 - get_alpha(s4_aa));
    324             } else {
    325                 r4 = s4 + d4 * dst_scale;
    326             }
    327             dst[i] = Sk4f_toS32(r4);
    328         }
    329     } else {
    330         while (count >= 4) {
    331             auto d = load_4_srgb(dst);
    332             auto s = Sk4x4f{{ src->r() }, { src->g() }, { src->b() }, { src->a() }};
    333         #if defined(SK_PMCOLOR_IS_BGRA)
    334             SkTSwap(s.r, s.b);
    335         #endif
    336             auto invSA = 1.0f - s.a;
    337             auto r = s.r + d.r * invSA,
    338                  g = s.g + d.g * invSA,
    339                  b = s.b + d.b * invSA,
    340                  a = s.a + d.a * invSA;
    341             store_4_srgb(dst, Sk4x4f{r,g,b,a});
    342             count -= 4;
    343             dst += 4;
    344         }
    345         for (int i = 0; i < count; ++i) {
    346             Sk4f d4 = Sk4f_fromS32(dst[i]);
    347             dst[i] = Sk4f_toS32(s4 + d4 * dst_scale);
    348         }
    349     }
    350 }
    351 
    352 const SkXfermode::D32Proc gProcs_SrcOver[] = {
    353     srcover_n<kLinear_Dst>, src_n<kLinear_Dst>,
    354     srcover_linear_dst_1,   src_1<kLinear_Dst>,
    355 
    356     srcover_n<kSRGB_Dst>,   src_n<kSRGB_Dst>,
    357     srcover_srgb_dst_1,     src_1<kSRGB_Dst>,
    358 };
    359 
    360 ///////////////////////////////////////////////////////////////////////////////////////////////////
    361 
    362 SkXfermode::D32Proc SkXfermode::GetD32Proc(SkBlendMode mode, uint32_t flags) {
    363     SkASSERT(0 == (flags & ~7));
    364     flags &= 7;
    365 
    366     switch (mode) {
    367         case SkBlendMode::kClear:   return gProcs_Clear[flags];
    368         case SkBlendMode::kSrc:     return gProcs_Src[flags];
    369         case SkBlendMode::kDst:     return gProcs_Dst[flags];
    370         case SkBlendMode::kSrcOver: return gProcs_SrcOver[flags];
    371         default:
    372             break;
    373     }
    374     return gProcs_General[flags];
    375 }
    376 
    377 ///////////////////////////////////////////////////////////////////////////////////////////////////
    378 #include "SkColorPriv.h"
    379 
    380 static Sk4f lcd16_to_unit_4f(uint16_t rgb) {
    381 #ifdef SK_PMCOLOR_IS_RGBA
    382     Sk4i rgbi = Sk4i(SkGetPackedR16(rgb), SkGetPackedG16(rgb), SkGetPackedB16(rgb), 0);
    383 #else
    384     Sk4i rgbi = Sk4i(SkGetPackedB16(rgb), SkGetPackedG16(rgb), SkGetPackedR16(rgb), 0);
    385 #endif
    386     return SkNx_cast<float>(rgbi) * Sk4f(1.0f/31, 1.0f/63, 1.0f/31, 0);
    387 }
    388 
    389 template <DstType D>
    390 void src_1_lcd(uint32_t dst[], const SkPM4f* src, int count, const uint16_t lcd[]) {
    391     const Sk4f s4 = src->to4f_pmorder();
    392 
    393     for (int i = 0; i < count; ++i) {
    394         uint16_t rgb = lcd[i];
    395         if (0 == rgb) {
    396             continue;
    397         }
    398         Sk4f d4 = load_dst<D>(dst[i]);
    399         dst[i] = store_dst<D>(lerp(s4, d4, lcd16_to_unit_4f(rgb))) | (SK_A32_MASK << SK_A32_SHIFT);
    400     }
    401 }
    402 
    403 template <DstType D>
    404 void src_n_lcd(uint32_t dst[], const SkPM4f src[], int count, const uint16_t lcd[]) {
    405     for (int i = 0; i < count; ++i) {
    406         uint16_t rgb = lcd[i];
    407         if (0 == rgb) {
    408             continue;
    409         }
    410         Sk4f s4 = src[i].to4f_pmorder();
    411         Sk4f d4 = load_dst<D>(dst[i]);
    412         dst[i] = store_dst<D>(lerp(s4, d4, lcd16_to_unit_4f(rgb))) | (SK_A32_MASK << SK_A32_SHIFT);
    413     }
    414 }
    415 
    416 template <DstType D>
    417 void srcover_1_lcd(uint32_t dst[], const SkPM4f* src, int count, const uint16_t lcd[]) {
    418     const Sk4f s4 = src->to4f_pmorder();
    419     Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
    420 
    421     for (int i = 0; i < count; ++i) {
    422         uint16_t rgb = lcd[i];
    423         if (0 == rgb) {
    424             continue;
    425         }
    426         Sk4f d4 = load_dst<D>(dst[i]);
    427         Sk4f r4 = s4 + d4 * dst_scale;
    428         r4 = lerp(r4, d4, lcd16_to_unit_4f(rgb));
    429         dst[i] = store_dst<D>(r4) | (SK_A32_MASK << SK_A32_SHIFT);
    430     }
    431 }
    432 
    433 template <DstType D>
    434 void srcover_n_lcd(uint32_t dst[], const SkPM4f src[], int count, const uint16_t lcd[]) {
    435     for (int i = 0; i < count; ++i) {
    436         uint16_t rgb = lcd[i];
    437         if (0 == rgb) {
    438             continue;
    439         }
    440         Sk4f s4 = src[i].to4f_pmorder();
    441         Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
    442         Sk4f d4 = load_dst<D>(dst[i]);
    443         Sk4f r4 = s4 + d4 * dst_scale;
    444         r4 = lerp(r4, d4, lcd16_to_unit_4f(rgb));
    445         dst[i] = store_dst<D>(r4) | (SK_A32_MASK << SK_A32_SHIFT);
    446     }
    447 }
    448 
    449 SkXfermode::LCD32Proc SkXfermode::GetLCD32Proc(uint32_t flags) {
    450     SkASSERT((flags & ~7) == 0);
    451     flags &= 7;
    452 
    453     const LCD32Proc procs[] = {
    454         srcover_n_lcd<kLinear_Dst>, src_n_lcd<kLinear_Dst>,
    455         srcover_1_lcd<kLinear_Dst>, src_1_lcd<kLinear_Dst>,
    456 
    457         srcover_n_lcd<kSRGB_Dst>,   src_n_lcd<kSRGB_Dst>,
    458         srcover_1_lcd<kSRGB_Dst>,   src_1_lcd<kSRGB_Dst>,
    459     };
    460     return procs[flags];
    461 }
    462