LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkXfermode4f.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 248 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 36 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13