SkXfermode.cpp revision c3118739277beb7678973d47e3d71bb863929bce
1116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2006 The Android Open Source Project 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Use of this source code is governed by a BSD-style license that can be 6116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * found in the LICENSE file. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 10116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "SkXfermode.h" 110529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "SkXfermode_proccoeff.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkColorPriv.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkMathPriv.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkOnce.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkReadBuffer.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkString.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkUtilsArm.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkWriteBuffer.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkXfermode_opts_SSE2.h" 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !SK_ARM_NEON_IS_NONE 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkXfermode_opts_arm_neon.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// idea for higher precision blends in xfer procs (and slightly faster) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// see DstATop as a probable caller 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(a <= 255); 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(b <= 255); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(c <= 255); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(d <= 255); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned result = (prod + (prod >> 8)) >> 8; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(result <= 255); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline unsigned saturated_add(unsigned a, unsigned b) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(a <= 255); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkASSERT(b <= 255); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned sum = a + b; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum > 255) { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = 255; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sum; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int clamp_signed_byte(int n) { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (n < 0) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = 0; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (n > 255) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) n = 255; 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return n; 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int clamp_div255round(int prod) { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (prod <= 0) { 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (prod >= 255*255) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 255; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkDiv255Round(prod); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kClear_Mode, //!< [0, 0] 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { 78c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return 0; 79c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kSrc_Mode, //!< [Sa, Sc] 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return src; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kDst_Mode, //!< [Da, Dc] 87c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { 88c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return dst; 89c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 90c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch// kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] 92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochstatic SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) { 93c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if 0 94c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // this is the old, more-correct way, but it doesn't guarantee that dst==255 95c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // will always stay opaque 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is slightly faster, but more importantly guarantees that dst==255 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will always stay opaque 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src)); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc] 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) { 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is the reverse of srcover, just flipping src and dst 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // see srcover's comment about the 256 for opaqueness guarantees 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst)); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kSrcIn_Mode, //!< [Sa * Da, Sc * Da] 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) { 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src))); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst))); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) { 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned sa = SkGetPackedA32(src); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned da = SkGetPackedA32(dst); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned isa = 255 - sa; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(da, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(da, SkGetPackedR32(src)) + 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(da, SkGetPackedG32(src)) + 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(da, SkGetPackedB32(src)) + 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned sa = SkGetPackedA32(src); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned da = SkGetPackedA32(dst); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned ida = 255 - da; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(sa, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(sa, SkGetPackedR32(dst)), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(sa, SkGetPackedG32(dst)), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(sa, SkGetPackedB32(dst))); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned sa = SkGetPackedA32(src); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned da = SkGetPackedA32(dst); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned isa = 255 - sa; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned ida = 255 - da; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/////////////////////////////////////////////////////////////////////////////// 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kPlus_Mode 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(a, r, g, b); 186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// kModulate_Mode 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) { 190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(a, r, g, b); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static inline int srcover_byte(int a, int b) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return a + b - SkAlphaMulAlpha(a, b); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kMultiply_Mode 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// B(Cb, Cs) = Cb x Cs 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// multiply uses its own version of blendfunc_byte because sa and da are not needed 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) { 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc); 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sa = SkGetPackedA32(src); 210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int da = SkGetPackedA32(dst); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a = srcover_byte(sa, da); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SkPackARGB32(a, r, g, b); 216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kScreen_Mode 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); 221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); 2230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); 2240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return SkPackARGB32(a, r, g, b); 2250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kOverlay_Mode 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int overlay_byte(int sc, int dc, int sa, int da) { 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int tmp = sc * (255 - da) + dc * (255 - sa); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (2 * dc <= da) { 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = 2 * sc * dc; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = sa * da - 2 * (da - dc) * (sa - sc); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return clamp_div255round(rc + tmp); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sa = SkGetPackedA32(src); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int da = SkGetPackedA32(dst); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a = srcover_byte(sa, da); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(a, r, g, b); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kDarken_Mode 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int darken_byte(int sc, int dc, int sa, int da) { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sd = sc * da; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ds = dc * sa; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sd < ds) { 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // srcover 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return sc + dc - SkDiv255Round(ds); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dstover 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dc + sc - SkDiv255Round(sd); 25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sa = SkGetPackedA32(src); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int da = SkGetPackedA32(dst); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a = srcover_byte(sa, da); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(a, r, g, b); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kLighten_Mode 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static inline int lighten_byte(int sc, int dc, int sa, int da) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sd = sc * da; 273c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch int ds = dc * sa; 274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch if (sd > ds) { 275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // srcover 276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return sc + dc - SkDiv255Round(ds); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dstover 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return dc + sc - SkDiv255Round(sd); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sa = SkGetPackedA32(src); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int da = SkGetPackedA32(dst); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a = srcover_byte(sa, da); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkPackARGB32(a, r, g, b); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2920529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch// kColorDodge_Mode 293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic inline int colordodge_byte(int sc, int dc, int sa, int da) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int diff = sa - sc; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rc; 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == dc) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SkAlphaMulAlpha(sc, 255 - da); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (0 == diff) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = sa * da + sc * (255 - da) + dc * (255 - sa); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) diff = dc * sa / diff; 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return clamp_div255round(rc); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int sa = SkGetPackedA32(src); 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int da = SkGetPackedA32(dst); 309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int a = srcover_byte(sa, da); 310116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 311116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 312116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 313116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SkPackARGB32(a, r, g, b); 314116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 315116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 316116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// kColorBurn_Mode 317116680a4aac90f2aa7413d9095a592090648e557Ben Murdochstatic inline int colorburn_byte(int sc, int dc, int sa, int da) { 318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rc; 319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (dc == da) { 320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rc = sa * da + sc * (255 - da) + dc * (255 - sa); 321116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (0 == sc) { 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return SkAlphaMulAlpha(dc, 255 - sa); 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int tmp = (da - dc) * sa / sc; 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch rc = sa * (da - ((da < tmp) ? da : tmp)) 326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch + sc * (255 - da) + dc * (255 - sa); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return clamp_div255round(rc); 329} 330static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { 331 int sa = SkGetPackedA32(src); 332 int da = SkGetPackedA32(dst); 333 int a = srcover_byte(sa, da); 334 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 335 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 336 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 337 return SkPackARGB32(a, r, g, b); 338} 339 340// kHardLight_Mode 341static inline int hardlight_byte(int sc, int dc, int sa, int da) { 342 int rc; 343 if (2 * sc <= sa) { 344 rc = 2 * sc * dc; 345 } else { 346 rc = sa * da - 2 * (da - dc) * (sa - sc); 347 } 348 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 349} 350static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { 351 int sa = SkGetPackedA32(src); 352 int da = SkGetPackedA32(dst); 353 int a = srcover_byte(sa, da); 354 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 355 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 356 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 357 return SkPackARGB32(a, r, g, b); 358} 359 360// returns 255 * sqrt(n/255) 361static U8CPU sqrt_unit_byte(U8CPU n) { 362 return SkSqrtBits(n, 15+4); 363} 364 365// kSoftLight_Mode 366static inline int softlight_byte(int sc, int dc, int sa, int da) { 367 int m = da ? dc * 256 / da : 0; 368 int rc; 369 if (2 * sc <= sa) { 370 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); 371 } else if (4 * dc <= da) { 372 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; 373 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 374 } else { 375 int tmp = sqrt_unit_byte(m) - m; 376 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 377 } 378 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 379} 380static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { 381 int sa = SkGetPackedA32(src); 382 int da = SkGetPackedA32(dst); 383 int a = srcover_byte(sa, da); 384 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 385 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 386 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 387 return SkPackARGB32(a, r, g, b); 388} 389 390// kDifference_Mode 391static inline int difference_byte(int sc, int dc, int sa, int da) { 392 int tmp = SkMin32(sc * da, dc * sa); 393 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); 394} 395static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { 396 int sa = SkGetPackedA32(src); 397 int da = SkGetPackedA32(dst); 398 int a = srcover_byte(sa, da); 399 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 400 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 401 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 402 return SkPackARGB32(a, r, g, b); 403} 404 405// kExclusion_Mode 406static inline int exclusion_byte(int sc, int dc, int, int) { 407 // this equations is wacky, wait for SVG to confirm it 408 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); 409 410 // The above equation can be simplified as follows 411 int r = 255*(sc + dc) - 2 * sc * dc; 412 return clamp_div255round(r); 413} 414static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { 415 int sa = SkGetPackedA32(src); 416 int da = SkGetPackedA32(dst); 417 int a = srcover_byte(sa, da); 418 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 419 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 420 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 421 return SkPackARGB32(a, r, g, b); 422} 423 424// The CSS compositing spec introduces the following formulas: 425// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable) 426// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709 427// while PDF and CG uses the one from Rec. Rec. 601 428// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm 429static inline int Lum(int r, int g, int b) 430{ 431 return SkDiv255Round(r * 77 + g * 150 + b * 28); 432} 433 434static inline int min2(int a, int b) { return a < b ? a : b; } 435static inline int max2(int a, int b) { return a > b ? a : b; } 436#define minimum(a, b, c) min2(min2(a, b), c) 437#define maximum(a, b, c) max2(max2(a, b), c) 438 439static inline int Sat(int r, int g, int b) { 440 return maximum(r, g, b) - minimum(r, g, b); 441} 442 443static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) { 444 if(*Cmax > *Cmin) { 445 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin); 446 *Cmax = s; 447 } else { 448 *Cmax = 0; 449 *Cmid = 0; 450 } 451 452 *Cmin = 0; 453} 454 455static inline void SetSat(int* r, int* g, int* b, int s) { 456 if(*r <= *g) { 457 if(*g <= *b) { 458 setSaturationComponents(r, g, b, s); 459 } else if(*r <= *b) { 460 setSaturationComponents(r, b, g, s); 461 } else { 462 setSaturationComponents(b, r, g, s); 463 } 464 } else if(*r <= *b) { 465 setSaturationComponents(g, r, b, s); 466 } else if(*g <= *b) { 467 setSaturationComponents(g, b, r, s); 468 } else { 469 setSaturationComponents(b, g, r, s); 470 } 471} 472 473static inline void clipColor(int* r, int* g, int* b, int a) { 474 int L = Lum(*r, *g, *b); 475 int n = minimum(*r, *g, *b); 476 int x = maximum(*r, *g, *b); 477 int denom; 478 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero 479 *r = L + SkMulDiv(*r - L, L, denom); 480 *g = L + SkMulDiv(*g - L, L, denom); 481 *b = L + SkMulDiv(*b - L, L, denom); 482 } 483 484 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero 485 int numer = a - L; 486 *r = L + SkMulDiv(*r - L, numer, denom); 487 *g = L + SkMulDiv(*g - L, numer, denom); 488 *b = L + SkMulDiv(*b - L, numer, denom); 489 } 490} 491 492static inline void SetLum(int* r, int* g, int* b, int a, int l) { 493 int d = l - Lum(*r, *g, *b); 494 *r += d; 495 *g += d; 496 *b += d; 497 498 clipColor(r, g, b, a); 499} 500 501// non-separable blend modes are done in non-premultiplied alpha 502#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ 503 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval) 504 505// kHue_Mode 506// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)) 507// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color. 508static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { 509 int sr = SkGetPackedR32(src); 510 int sg = SkGetPackedG32(src); 511 int sb = SkGetPackedB32(src); 512 int sa = SkGetPackedA32(src); 513 514 int dr = SkGetPackedR32(dst); 515 int dg = SkGetPackedG32(dst); 516 int db = SkGetPackedB32(dst); 517 int da = SkGetPackedA32(dst); 518 int Sr, Sg, Sb; 519 520 if(sa && da) { 521 Sr = sr * sa; 522 Sg = sg * sa; 523 Sb = sb * sa; 524 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa); 525 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); 526 } else { 527 Sr = 0; 528 Sg = 0; 529 Sb = 0; 530 } 531 532 int a = srcover_byte(sa, da); 533 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); 534 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); 535 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); 536 return SkPackARGB32(a, r, g, b); 537} 538 539// kSaturation_Mode 540// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)) 541// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color. 542static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { 543 int sr = SkGetPackedR32(src); 544 int sg = SkGetPackedG32(src); 545 int sb = SkGetPackedB32(src); 546 int sa = SkGetPackedA32(src); 547 548 int dr = SkGetPackedR32(dst); 549 int dg = SkGetPackedG32(dst); 550 int db = SkGetPackedB32(dst); 551 int da = SkGetPackedA32(dst); 552 int Dr, Dg, Db; 553 554 if(sa && da) { 555 Dr = dr * sa; 556 Dg = dg * sa; 557 Db = db * sa; 558 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da); 559 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa); 560 } else { 561 Dr = 0; 562 Dg = 0; 563 Db = 0; 564 } 565 566 int a = srcover_byte(sa, da); 567 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); 568 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); 569 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); 570 return SkPackARGB32(a, r, g, b); 571} 572 573// kColor_Mode 574// B(Cb, Cs) = SetLum(Cs, Lum(Cb)) 575// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color. 576static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { 577 int sr = SkGetPackedR32(src); 578 int sg = SkGetPackedG32(src); 579 int sb = SkGetPackedB32(src); 580 int sa = SkGetPackedA32(src); 581 582 int dr = SkGetPackedR32(dst); 583 int dg = SkGetPackedG32(dst); 584 int db = SkGetPackedB32(dst); 585 int da = SkGetPackedA32(dst); 586 int Sr, Sg, Sb; 587 588 if(sa && da) { 589 Sr = sr * da; 590 Sg = sg * da; 591 Sb = sb * da; 592 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); 593 } else { 594 Sr = 0; 595 Sg = 0; 596 Sb = 0; 597 } 598 599 int a = srcover_byte(sa, da); 600 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); 601 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); 602 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); 603 return SkPackARGB32(a, r, g, b); 604} 605 606// kLuminosity_Mode 607// B(Cb, Cs) = SetLum(Cb, Lum(Cs)) 608// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color. 609static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { 610 int sr = SkGetPackedR32(src); 611 int sg = SkGetPackedG32(src); 612 int sb = SkGetPackedB32(src); 613 int sa = SkGetPackedA32(src); 614 615 int dr = SkGetPackedR32(dst); 616 int dg = SkGetPackedG32(dst); 617 int db = SkGetPackedB32(dst); 618 int da = SkGetPackedA32(dst); 619 int Dr, Dg, Db; 620 621 if(sa && da) { 622 Dr = dr * sa; 623 Dg = dg * sa; 624 Db = db * sa; 625 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da); 626 } else { 627 Dr = 0; 628 Dg = 0; 629 Db = 0; 630 } 631 632 int a = srcover_byte(sa, da); 633 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); 634 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); 635 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); 636 return SkPackARGB32(a, r, g, b); 637} 638 639const ProcCoeff gProcCoeffs[] = { 640 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, 641 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, 642 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, 643 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, 644 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, 645 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, 646 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, 647 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, 648 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, 649 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, 650 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, 651 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, 652 653 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, 654 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, 655 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, 656 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 657 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 658 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 659 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 660 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 661 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 662 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 663 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 664 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 665 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 666 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 667 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 668 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 669 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 670}; 671 672/////////////////////////////////////////////////////////////////////////////// 673 674bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const { 675 return false; 676} 677 678bool SkXfermode::asMode(Mode* mode) const { 679 return false; 680} 681 682bool SkXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const { 683 return false; 684} 685 686bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode, 687 GrEffectRef** effect, 688 Coeff* src, 689 Coeff* dst, 690 GrTexture* background) { 691 if (NULL == xfermode) { 692 return ModeAsCoeff(kSrcOver_Mode, src, dst); 693 } else if (xfermode->asCoeff(src, dst)) { 694 return true; 695 } else { 696 return xfermode->asNewEffect(effect, background); 697 } 698} 699 700SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{ 701 // no-op. subclasses should override this 702 return dst; 703} 704 705void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 706 const SkPMColor* SK_RESTRICT src, int count, 707 const SkAlpha* SK_RESTRICT aa) const { 708 SkASSERT(dst && src && count >= 0); 709 710 if (NULL == aa) { 711 for (int i = count - 1; i >= 0; --i) { 712 dst[i] = this->xferColor(src[i], dst[i]); 713 } 714 } else { 715 for (int i = count - 1; i >= 0; --i) { 716 unsigned a = aa[i]; 717 if (0 != a) { 718 SkPMColor dstC = dst[i]; 719 SkPMColor C = this->xferColor(src[i], dstC); 720 if (0xFF != a) { 721 C = SkFourByteInterp(C, dstC, a); 722 } 723 dst[i] = C; 724 } 725 } 726 } 727} 728 729void SkXfermode::xfer16(uint16_t* dst, 730 const SkPMColor* SK_RESTRICT src, int count, 731 const SkAlpha* SK_RESTRICT aa) const { 732 SkASSERT(dst && src && count >= 0); 733 734 if (NULL == aa) { 735 for (int i = count - 1; i >= 0; --i) { 736 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 737 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); 738 } 739 } else { 740 for (int i = count - 1; i >= 0; --i) { 741 unsigned a = aa[i]; 742 if (0 != a) { 743 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 744 SkPMColor C = this->xferColor(src[i], dstC); 745 if (0xFF != a) { 746 C = SkFourByteInterp(C, dstC, a); 747 } 748 dst[i] = SkPixel32ToPixel16_ToU16(C); 749 } 750 } 751 } 752} 753 754void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 755 const SkPMColor src[], int count, 756 const SkAlpha* SK_RESTRICT aa) const { 757 SkASSERT(dst && src && count >= 0); 758 759 if (NULL == aa) { 760 for (int i = count - 1; i >= 0; --i) { 761 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); 762 dst[i] = SkToU8(SkGetPackedA32(res)); 763 } 764 } else { 765 for (int i = count - 1; i >= 0; --i) { 766 unsigned a = aa[i]; 767 if (0 != a) { 768 SkAlpha dstA = dst[i]; 769 unsigned A = SkGetPackedA32(this->xferColor(src[i], 770 (SkPMColor)(dstA << SK_A32_SHIFT))); 771 if (0xFF != a) { 772 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 773 } 774 dst[i] = SkToU8(A); 775 } 776 } 777 } 778} 779 780/////////////////////////////////////////////////////////////////////////////// 781 782void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 783 const SkPMColor* SK_RESTRICT src, int count, 784 const SkAlpha* SK_RESTRICT aa) const { 785 SkASSERT(dst && src && count >= 0); 786 787 SkXfermodeProc proc = fProc; 788 789 if (NULL != proc) { 790 if (NULL == aa) { 791 for (int i = count - 1; i >= 0; --i) { 792 dst[i] = proc(src[i], dst[i]); 793 } 794 } else { 795 for (int i = count - 1; i >= 0; --i) { 796 unsigned a = aa[i]; 797 if (0 != a) { 798 SkPMColor dstC = dst[i]; 799 SkPMColor C = proc(src[i], dstC); 800 if (a != 0xFF) { 801 C = SkFourByteInterp(C, dstC, a); 802 } 803 dst[i] = C; 804 } 805 } 806 } 807 } 808} 809 810void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, 811 const SkPMColor* SK_RESTRICT src, int count, 812 const SkAlpha* SK_RESTRICT aa) const { 813 SkASSERT(dst && src && count >= 0); 814 815 SkXfermodeProc proc = fProc; 816 817 if (NULL != proc) { 818 if (NULL == aa) { 819 for (int i = count - 1; i >= 0; --i) { 820 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 821 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); 822 } 823 } else { 824 for (int i = count - 1; i >= 0; --i) { 825 unsigned a = aa[i]; 826 if (0 != a) { 827 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 828 SkPMColor C = proc(src[i], dstC); 829 if (0xFF != a) { 830 C = SkFourByteInterp(C, dstC, a); 831 } 832 dst[i] = SkPixel32ToPixel16_ToU16(C); 833 } 834 } 835 } 836 } 837} 838 839void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 840 const SkPMColor* SK_RESTRICT src, int count, 841 const SkAlpha* SK_RESTRICT aa) const { 842 SkASSERT(dst && src && count >= 0); 843 844 SkXfermodeProc proc = fProc; 845 846 if (NULL != proc) { 847 if (NULL == aa) { 848 for (int i = count - 1; i >= 0; --i) { 849 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); 850 dst[i] = SkToU8(SkGetPackedA32(res)); 851 } 852 } else { 853 for (int i = count - 1; i >= 0; --i) { 854 unsigned a = aa[i]; 855 if (0 != a) { 856 SkAlpha dstA = dst[i]; 857 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); 858 unsigned A = SkGetPackedA32(res); 859 if (0xFF != a) { 860 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 861 } 862 dst[i] = SkToU8(A); 863 } 864 } 865 } 866 } 867} 868 869SkProcXfermode::SkProcXfermode(SkReadBuffer& buffer) 870 : SkXfermode(buffer) { 871 fProc = NULL; 872 if (!buffer.isCrossProcess()) { 873 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 874 } 875} 876 877void SkProcXfermode::flatten(SkWriteBuffer& buffer) const { 878 this->INHERITED::flatten(buffer); 879 if (!buffer.isCrossProcess()) { 880 buffer.writeFunctionPtr((void*)fProc); 881 } 882} 883 884#ifndef SK_IGNORE_TO_STRING 885void SkProcXfermode::toString(SkString* str) const { 886 str->appendf("SkProcXfermode: %p", fProc); 887} 888#endif 889 890////////////////////////////////////////////////////////////////////////////// 891 892#if SK_SUPPORT_GPU 893 894#include "GrEffect.h" 895#include "GrCoordTransform.h" 896#include "GrEffectUnitTest.h" 897#include "GrTBackendEffectFactory.h" 898#include "gl/GrGLEffect.h" 899 900/** 901 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs. 902 */ 903class XferEffect : public GrEffect { 904public: 905 static bool IsSupportedMode(SkXfermode::Mode mode) { 906 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; 907 } 908 909 static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) { 910 if (!IsSupportedMode(mode)) { 911 return NULL; 912 } else { 913 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background))); 914 return CreateEffectRef(effect); 915 } 916 } 917 918 virtual void getConstantColorComponents(GrColor* color, 919 uint32_t* validFlags) const SK_OVERRIDE { 920 *validFlags = 0; 921 } 922 923 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 924 return GrTBackendEffectFactory<XferEffect>::getInstance(); 925 } 926 927 static const char* Name() { return "XferEffect"; } 928 929 SkXfermode::Mode mode() const { return fMode; } 930 const GrTextureAccess& backgroundAccess() const { return fBackgroundAccess; } 931 932 class GLEffect : public GrGLEffect { 933 public: 934 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 935 : GrGLEffect(factory) { 936 } 937 virtual void emitCode(GrGLShaderBuilder* builder, 938 const GrDrawEffect& drawEffect, 939 EffectKey key, 940 const char* outputColor, 941 const char* inputColor, 942 const TransformedCoordsArray& coords, 943 const TextureSamplerArray& samplers) SK_OVERRIDE { 944 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode(); 945 const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture(); 946 const char* dstColor; 947 if (backgroundTex) { 948 dstColor = "bgColor"; 949 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor); 950 builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); 951 builder->fsCodeAppendf(";\n"); 952 } else { 953 dstColor = builder->dstColor(); 954 } 955 SkASSERT(NULL != dstColor); 956 957 // We don't try to optimize for this case at all 958 if (NULL == inputColor) { 959 builder->fsCodeAppendf("\t\tconst vec4 ones = vec4(1);\n"); 960 inputColor = "ones"; 961 } 962 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); 963 964 // These all perform src-over on the alpha channel. 965 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", 966 outputColor, inputColor, inputColor, dstColor); 967 968 switch (mode) { 969 case SkXfermode::kOverlay_Mode: 970 // Overlay is Hard-Light with the src and dst reversed 971 HardLight(builder, outputColor, dstColor, inputColor); 972 break; 973 case SkXfermode::kDarken_Mode: 974 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " 975 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 976 outputColor, 977 inputColor, dstColor, inputColor, 978 dstColor, inputColor, dstColor); 979 break; 980 case SkXfermode::kLighten_Mode: 981 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " 982 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 983 outputColor, 984 inputColor, dstColor, inputColor, 985 dstColor, inputColor, dstColor); 986 break; 987 case SkXfermode::kColorDodge_Mode: 988 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); 989 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); 990 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); 991 break; 992 case SkXfermode::kColorBurn_Mode: 993 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); 994 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); 995 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); 996 break; 997 case SkXfermode::kHardLight_Mode: 998 HardLight(builder, outputColor, inputColor, dstColor); 999 break; 1000 case SkXfermode::kSoftLight_Mode: 1001 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); 1002 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); 1003 builder->fsCodeAppendf("\t\t} else {\n"); 1004 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); 1005 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); 1006 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); 1007 builder->fsCodeAppendf("\t\t}\n"); 1008 break; 1009 case SkXfermode::kDifference_Mode: 1010 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" 1011 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", 1012 outputColor, inputColor, dstColor, inputColor, dstColor, 1013 dstColor, inputColor); 1014 break; 1015 case SkXfermode::kExclusion_Mode: 1016 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " 1017 "2.0 * %s.rgb * %s.rgb;\n", 1018 outputColor, dstColor, inputColor, dstColor, inputColor); 1019 break; 1020 case SkXfermode::kMultiply_Mode: 1021 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " 1022 "(1.0 - %s.a) * %s.rgb + " 1023 "%s.rgb * %s.rgb;\n", 1024 outputColor, inputColor, dstColor, dstColor, inputColor, 1025 inputColor, dstColor); 1026 break; 1027 case SkXfermode::kHue_Mode: { 1028 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S 1029 SkString setSat, setLum; 1030 AddSatFunction(builder, &setSat); 1031 AddLumFunction(builder, &setLum); 1032 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1033 dstColor, inputColor); 1034 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1035 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1036 dstColor); 1037 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1038 outputColor, inputColor, dstColor, dstColor, inputColor); 1039 break; 1040 } 1041 case SkXfermode::kSaturation_Mode: { 1042 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S 1043 SkString setSat, setLum; 1044 AddSatFunction(builder, &setSat); 1045 AddLumFunction(builder, &setLum); 1046 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1047 dstColor, inputColor); 1048 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1049 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1050 dstColor); 1051 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1052 outputColor, inputColor, dstColor, dstColor, inputColor); 1053 break; 1054 } 1055 case SkXfermode::kColor_Mode: { 1056 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S 1057 SkString setLum; 1058 AddLumFunction(builder, &setLum); 1059 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1060 inputColor, dstColor); 1061 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", 1062 outputColor, setLum.c_str(), dstColor, inputColor); 1063 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1064 outputColor, inputColor, dstColor, dstColor, inputColor); 1065 break; 1066 } 1067 case SkXfermode::kLuminosity_Mode: { 1068 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S 1069 SkString setLum; 1070 AddLumFunction(builder, &setLum); 1071 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1072 inputColor, dstColor); 1073 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", 1074 outputColor, setLum.c_str(), dstColor, inputColor); 1075 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1076 outputColor, inputColor, dstColor, dstColor, inputColor); 1077 break; 1078 } 1079 default: 1080 GrCrash("Unknown XferEffect mode."); 1081 break; 1082 } 1083 } 1084 1085 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1086 return drawEffect.castEffect<XferEffect>().mode(); 1087 } 1088 1089 private: 1090 static void HardLight(GrGLShaderBuilder* builder, 1091 const char* final, 1092 const char* src, 1093 const char* dst) { 1094 static const char kComponents[] = {'r', 'g', 'b'}; 1095 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { 1096 char component = kComponents[i]; 1097 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1098 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component); 1099 builder->fsCodeAppend("\t\t} else {\n"); 1100 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n", 1101 final, component, src, dst, dst, dst, component, src, src, component); 1102 builder->fsCodeAppend("\t\t}\n"); 1103 } 1104 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", 1105 final, src, dst, dst, src); 1106 } 1107 1108 // Does one component of color-dodge 1109 static void ColorDodgeComponent(GrGLShaderBuilder* builder, 1110 const char* final, 1111 const char* src, 1112 const char* dst, 1113 const char component) { 1114 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); 1115 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1116 final, component, src, component, dst); 1117 builder->fsCodeAppend("\t\t} else {\n"); 1118 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); 1119 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n"); 1120 builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1121 final, component, src, dst, src, component, dst, dst, component, 1122 src); 1123 builder->fsCodeAppend("\t\t\t} else {\n"); 1124 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", 1125 dst, dst, component, src); 1126 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1127 final, component, src, src, component, dst, dst, component, src); 1128 builder->fsCodeAppend("\t\t\t}\n"); 1129 builder->fsCodeAppend("\t\t}\n"); 1130 } 1131 1132 // Does one component of color-burn 1133 static void ColorBurnComponent(GrGLShaderBuilder* builder, 1134 const char* final, 1135 const char* src, 1136 const char* dst, 1137 const char component) { 1138 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); 1139 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1140 final, component, src, dst, src, component, dst, dst, component, 1141 src); 1142 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); 1143 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1144 final, component, dst, component, src); 1145 builder->fsCodeAppend("\t\t} else {\n"); 1146 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", 1147 dst, dst, dst, component, src, src, component); 1148 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1149 final, component, src, src, component, dst, dst, component, src); 1150 builder->fsCodeAppend("\t\t}\n"); 1151 } 1152 1153 // Does one component of soft-light. Caller should have already checked that dst alpha > 0. 1154 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, 1155 const char* final, 1156 const char* src, 1157 const char* dst, 1158 const char component) { 1159 // if (2S < Sa) 1160 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1161 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) 1162 builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n", 1163 final, component, dst, component, dst, component, src, src, 1164 component, dst, dst, src, component, dst, component, src, src, 1165 component); 1166 // else if (4D < Da) 1167 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", 1168 dst, component, dst); 1169 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", 1170 dst, component, dst, component); 1171 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); 1172 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); 1173 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); 1174 // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2 1175 builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n", 1176 final, component, src, component, src, component, dst, component, 1177 src, src, component, dst, src, src, component, src, src, 1178 component); 1179 builder->fsCodeAppendf("\t\t\t} else {\n"); 1180 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S 1181 builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", 1182 final, component, dst, dst, component, src, src, component, dst, 1183 src, component, dst, component, src, src, component, src, 1184 component); 1185 builder->fsCodeAppendf("\t\t\t}\n"); 1186 } 1187 1188 // Adds a function that takes two colors and an alpha as input. It produces a color with the 1189 // hue and saturation of the first color, the luminosity of the second color, and the input 1190 // alpha. It has this signature: 1191 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). 1192 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) { 1193 // Emit a helper that gets the luminance of a color. 1194 SkString getFunction; 1195 GrGLShaderVar getLumArgs[] = { 1196 GrGLShaderVar("color", kVec3f_GrSLType), 1197 }; 1198 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n"); 1199 builder->fsEmitFunction(kFloat_GrSLType, 1200 "luminance", 1201 SK_ARRAY_COUNT(getLumArgs), getLumArgs, 1202 getLumBody.c_str(), 1203 &getFunction); 1204 1205 // Emit the set luminance function. 1206 GrGLShaderVar setLumArgs[] = { 1207 GrGLShaderVar("hueSat", kVec3f_GrSLType), 1208 GrGLShaderVar("alpha", kFloat_GrSLType), 1209 GrGLShaderVar("lumColor", kVec3f_GrSLType), 1210 }; 1211 SkString setLumBody; 1212 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str()); 1213 setLumBody.append("\tvec3 outColor = hueSat + diff;\n"); 1214 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str()); 1215 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n" 1216 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n" 1217 "\tif (minComp < 0.0) {\n" 1218 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n" 1219 "\t}\n" 1220 "\tif (maxComp > alpha) {\n" 1221 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" 1222 "\t}\n" 1223 "\treturn outColor;\n"); 1224 builder->fsEmitFunction(kVec3f_GrSLType, 1225 "set_luminance", 1226 SK_ARRAY_COUNT(setLumArgs), setLumArgs, 1227 setLumBody.c_str(), 1228 setLumFunction); 1229 } 1230 1231 // Adds a function that creates a color with the hue and luminosity of one input color and 1232 // the saturation of another color. It will have this signature: 1233 // float set_saturation(vec3 hueLumColor, vec3 satColor) 1234 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) { 1235 // Emit a helper that gets the saturation of a color 1236 SkString getFunction; 1237 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; 1238 SkString getSatBody; 1239 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " 1240 "min(min(color.r, color.g), color.b);\n"); 1241 builder->fsEmitFunction(kFloat_GrSLType, 1242 "saturation", 1243 SK_ARRAY_COUNT(getSatArgs), getSatArgs, 1244 getSatBody.c_str(), 1245 &getFunction); 1246 1247 // Emit a helper that sets the saturation given sorted input channels. This used 1248 // to use inout params for min, mid, and max components but that seems to cause 1249 // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the 1250 // adjusted min, mid, and max inputs, respectively. 1251 SkString helperFunction; 1252 GrGLShaderVar helperArgs[] = { 1253 GrGLShaderVar("minComp", kFloat_GrSLType), 1254 GrGLShaderVar("midComp", kFloat_GrSLType), 1255 GrGLShaderVar("maxComp", kFloat_GrSLType), 1256 GrGLShaderVar("sat", kFloat_GrSLType), 1257 }; 1258 static const char kHelperBody[] = "\tif (minComp < maxComp) {\n" 1259 "\t\tvec3 result;\n" 1260 "\t\tresult.r = 0.0;\n" 1261 "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n" 1262 "\t\tresult.b = sat;\n" 1263 "\t\treturn result;\n" 1264 "\t} else {\n" 1265 "\t\treturn vec3(0, 0, 0);\n" 1266 "\t}\n"; 1267 builder->fsEmitFunction(kVec3f_GrSLType, 1268 "set_saturation_helper", 1269 SK_ARRAY_COUNT(helperArgs), helperArgs, 1270 kHelperBody, 1271 &helperFunction); 1272 1273 GrGLShaderVar setSatArgs[] = { 1274 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), 1275 GrGLShaderVar("satColor", kVec3f_GrSLType), 1276 }; 1277 const char* helpFunc = helperFunction.c_str(); 1278 SkString setSatBody; 1279 setSatBody.appendf("\tfloat sat = %s(satColor);\n" 1280 "\tif (hueLumColor.r <= hueLumColor.g) {\n" 1281 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n" 1282 "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n" 1283 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1284 "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n" 1285 "\t\t} else {\n" 1286 "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n" 1287 "\t\t}\n" 1288 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1289 "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n" 1290 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n" 1291 "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n" 1292 "\t} else {\n" 1293 "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n" 1294 "\t}\n" 1295 "\treturn hueLumColor;\n", 1296 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, 1297 helpFunc, helpFunc); 1298 builder->fsEmitFunction(kVec3f_GrSLType, 1299 "set_saturation", 1300 SK_ARRAY_COUNT(setSatArgs), setSatArgs, 1301 setSatBody.c_str(), 1302 setSatFunction); 1303 1304 } 1305 1306 typedef GrGLEffect INHERITED; 1307 }; 1308 1309 GR_DECLARE_EFFECT_TEST; 1310 1311private: 1312 XferEffect(SkXfermode::Mode mode, GrTexture* background) 1313 : fMode(mode) { 1314 if (background) { 1315 fBackgroundTransform.reset(kLocal_GrCoordSet, background); 1316 this->addCoordTransform(&fBackgroundTransform); 1317 fBackgroundAccess.reset(background); 1318 this->addTextureAccess(&fBackgroundAccess); 1319 } else { 1320 this->setWillReadDstColor(); 1321 } 1322 } 1323 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { 1324 const XferEffect& s = CastEffect<XferEffect>(other); 1325 return fMode == s.fMode && 1326 fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture(); 1327 } 1328 1329 SkXfermode::Mode fMode; 1330 GrCoordTransform fBackgroundTransform; 1331 GrTextureAccess fBackgroundAccess; 1332 1333 typedef GrEffect INHERITED; 1334}; 1335 1336GR_DEFINE_EFFECT_TEST(XferEffect); 1337GrEffectRef* XferEffect::TestCreate(SkRandom* rand, 1338 GrContext*, 1339 const GrDrawTargetCaps&, 1340 GrTexture*[]) { 1341 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode); 1342 1343 AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL))); 1344 return CreateEffectRef(gEffect); 1345} 1346 1347#endif 1348 1349/////////////////////////////////////////////////////////////////////////////// 1350/////////////////////////////////////////////////////////////////////////////// 1351 1352SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) { 1353 uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs); 1354 if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) { 1355 // out of range, just set to something harmless 1356 mode32 = SkXfermode::kSrcOut_Mode; 1357 } 1358 fMode = (SkXfermode::Mode)mode32; 1359 1360 const ProcCoeff& rec = gProcCoeffs[fMode]; 1361 // these may be valid, or may be CANNOT_USE_COEFF 1362 fSrcCoeff = rec.fSC; 1363 fDstCoeff = rec.fDC; 1364 // now update our function-ptr in the super class 1365 this->INHERITED::setProc(rec.fProc); 1366} 1367 1368bool SkProcCoeffXfermode::asMode(Mode* mode) const { 1369 if (mode) { 1370 *mode = fMode; 1371 } 1372 return true; 1373} 1374 1375bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const { 1376 if (CANNOT_USE_COEFF == fSrcCoeff) { 1377 return false; 1378 } 1379 1380 if (sc) { 1381 *sc = fSrcCoeff; 1382 } 1383 if (dc) { 1384 *dc = fDstCoeff; 1385 } 1386 return true; 1387} 1388 1389#if SK_SUPPORT_GPU 1390bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect, 1391 GrTexture* background) const { 1392 if (XferEffect::IsSupportedMode(fMode)) { 1393 if (NULL != effect) { 1394 *effect = XferEffect::Create(fMode, background); 1395 SkASSERT(NULL != *effect); 1396 } 1397 return true; 1398 } 1399 return false; 1400} 1401#endif 1402 1403void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const { 1404 this->INHERITED::flatten(buffer); 1405 buffer.write32(fMode); 1406} 1407 1408const char* SkXfermode::ModeName(Mode mode) { 1409 SkASSERT((unsigned) mode <= (unsigned)kLastMode); 1410 const char* gModeStrings[] = { 1411 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", 1412 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", 1413 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", 1414 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", 1415 "Multiply", "Hue", "Saturation", "Color", "Luminosity" 1416 }; 1417 return gModeStrings[mode]; 1418 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); 1419} 1420 1421#ifndef SK_IGNORE_TO_STRING 1422void SkProcCoeffXfermode::toString(SkString* str) const { 1423 str->append("SkProcCoeffXfermode: "); 1424 1425 str->append("mode: "); 1426 str->append(ModeName(fMode)); 1427 1428 static const char* gCoeffStrings[kCoeffCount] = { 1429 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" 1430 }; 1431 1432 str->append(" src: "); 1433 if (CANNOT_USE_COEFF == fSrcCoeff) { 1434 str->append("can't use"); 1435 } else { 1436 str->append(gCoeffStrings[fSrcCoeff]); 1437 } 1438 1439 str->append(" dst: "); 1440 if (CANNOT_USE_COEFF == fDstCoeff) { 1441 str->append("can't use"); 1442 } else { 1443 str->append(gCoeffStrings[fDstCoeff]); 1444 } 1445} 1446#endif 1447 1448/////////////////////////////////////////////////////////////////////////////// 1449 1450class SkClearXfermode : public SkProcCoeffXfermode { 1451public: 1452 static SkClearXfermode* Create(const ProcCoeff& rec) { 1453 return SkNEW_ARGS(SkClearXfermode, (rec)); 1454 } 1455 1456 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1457 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1458 1459 SK_TO_STRING_OVERRIDE() 1460 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 1461 1462private: 1463 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 1464 SkClearXfermode(SkReadBuffer& buffer) 1465 : SkProcCoeffXfermode(buffer) {} 1466 1467 typedef SkProcCoeffXfermode INHERITED; 1468}; 1469 1470void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1471 const SkPMColor* SK_RESTRICT, int count, 1472 const SkAlpha* SK_RESTRICT aa) const { 1473 SkASSERT(dst && count >= 0); 1474 1475 if (NULL == aa) { 1476 memset(dst, 0, count << 2); 1477 } else { 1478 for (int i = count - 1; i >= 0; --i) { 1479 unsigned a = aa[i]; 1480 if (0xFF == a) { 1481 dst[i] = 0; 1482 } else if (a != 0) { 1483 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 1484 } 1485 } 1486 } 1487} 1488void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1489 const SkPMColor* SK_RESTRICT, int count, 1490 const SkAlpha* SK_RESTRICT aa) const { 1491 SkASSERT(dst && count >= 0); 1492 1493 if (NULL == aa) { 1494 memset(dst, 0, count); 1495 } else { 1496 for (int i = count - 1; i >= 0; --i) { 1497 unsigned a = aa[i]; 1498 if (0xFF == a) { 1499 dst[i] = 0; 1500 } else if (0 != a) { 1501 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 1502 } 1503 } 1504 } 1505} 1506 1507#ifndef SK_IGNORE_TO_STRING 1508void SkClearXfermode::toString(SkString* str) const { 1509 this->INHERITED::toString(str); 1510} 1511#endif 1512 1513/////////////////////////////////////////////////////////////////////////////// 1514 1515class SkSrcXfermode : public SkProcCoeffXfermode { 1516public: 1517 static SkSrcXfermode* Create(const ProcCoeff& rec) { 1518 return SkNEW_ARGS(SkSrcXfermode, (rec)); 1519 } 1520 1521 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1522 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1523 1524 SK_TO_STRING_OVERRIDE() 1525 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 1526 1527private: 1528 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 1529 SkSrcXfermode(SkReadBuffer& buffer) 1530 : SkProcCoeffXfermode(buffer) {} 1531 1532 typedef SkProcCoeffXfermode INHERITED; 1533}; 1534 1535void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1536 const SkPMColor* SK_RESTRICT src, int count, 1537 const SkAlpha* SK_RESTRICT aa) const { 1538 SkASSERT(dst && src && count >= 0); 1539 1540 if (NULL == aa) { 1541 memcpy(dst, src, count << 2); 1542 } else { 1543 for (int i = count - 1; i >= 0; --i) { 1544 unsigned a = aa[i]; 1545 if (a == 0xFF) { 1546 dst[i] = src[i]; 1547 } else if (a != 0) { 1548 dst[i] = SkFourByteInterp(src[i], dst[i], a); 1549 } 1550 } 1551 } 1552} 1553 1554void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1555 const SkPMColor* SK_RESTRICT src, int count, 1556 const SkAlpha* SK_RESTRICT aa) const { 1557 SkASSERT(dst && src && count >= 0); 1558 1559 if (NULL == aa) { 1560 for (int i = count - 1; i >= 0; --i) { 1561 dst[i] = SkToU8(SkGetPackedA32(src[i])); 1562 } 1563 } else { 1564 for (int i = count - 1; i >= 0; --i) { 1565 unsigned a = aa[i]; 1566 if (0 != a) { 1567 unsigned srcA = SkGetPackedA32(src[i]); 1568 if (a == 0xFF) { 1569 dst[i] = SkToU8(srcA); 1570 } else { 1571 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 1572 } 1573 } 1574 } 1575 } 1576} 1577#ifndef SK_IGNORE_TO_STRING 1578void SkSrcXfermode::toString(SkString* str) const { 1579 this->INHERITED::toString(str); 1580} 1581#endif 1582 1583/////////////////////////////////////////////////////////////////////////////// 1584 1585class SkDstInXfermode : public SkProcCoeffXfermode { 1586public: 1587 static SkDstInXfermode* Create(const ProcCoeff& rec) { 1588 return SkNEW_ARGS(SkDstInXfermode, (rec)); 1589 } 1590 1591 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1592 1593 SK_TO_STRING_OVERRIDE() 1594 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 1595 1596private: 1597 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 1598 SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {} 1599 1600 typedef SkProcCoeffXfermode INHERITED; 1601}; 1602 1603void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1604 const SkPMColor* SK_RESTRICT src, int count, 1605 const SkAlpha* SK_RESTRICT aa) const { 1606 SkASSERT(dst && src); 1607 1608 if (count <= 0) { 1609 return; 1610 } 1611 if (NULL != aa) { 1612 return this->INHERITED::xfer32(dst, src, count, aa); 1613 } 1614 1615 do { 1616 unsigned a = SkGetPackedA32(*src); 1617 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 1618 dst++; 1619 src++; 1620 } while (--count != 0); 1621} 1622 1623#ifndef SK_IGNORE_TO_STRING 1624void SkDstInXfermode::toString(SkString* str) const { 1625 this->INHERITED::toString(str); 1626} 1627#endif 1628 1629/////////////////////////////////////////////////////////////////////////////// 1630 1631class SkDstOutXfermode : public SkProcCoeffXfermode { 1632public: 1633 static SkDstOutXfermode* Create(const ProcCoeff& rec) { 1634 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 1635 } 1636 1637 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1638 1639 SK_TO_STRING_OVERRIDE() 1640 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 1641 1642private: 1643 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 1644 SkDstOutXfermode(SkReadBuffer& buffer) 1645 : INHERITED(buffer) {} 1646 1647 typedef SkProcCoeffXfermode INHERITED; 1648}; 1649 1650void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1651 const SkPMColor* SK_RESTRICT src, int count, 1652 const SkAlpha* SK_RESTRICT aa) const { 1653 SkASSERT(dst && src); 1654 1655 if (count <= 0) { 1656 return; 1657 } 1658 if (NULL != aa) { 1659 return this->INHERITED::xfer32(dst, src, count, aa); 1660 } 1661 1662 do { 1663 unsigned a = SkGetPackedA32(*src); 1664 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 1665 dst++; 1666 src++; 1667 } while (--count != 0); 1668} 1669 1670#ifndef SK_IGNORE_TO_STRING 1671void SkDstOutXfermode::toString(SkString* str) const { 1672 this->INHERITED::toString(str); 1673} 1674#endif 1675 1676/////////////////////////////////////////////////////////////////////////////// 1677 1678SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex); 1679static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; // All NULL to start. 1680static bool gXfermodeCached[SK_ARRAY_COUNT(gCachedXfermodes)]; // All false to start. 1681 1682void SkXfermode::Term() { 1683 SkAutoMutexAcquire ac(gCachedXfermodesMutex); 1684 1685 for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) { 1686 SkSafeUnref(gCachedXfermodes[i]); 1687 gCachedXfermodes[i] = NULL; 1688 } 1689} 1690 1691extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, 1692 SkXfermode::Mode mode); 1693extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode); 1694 1695 1696static void create_mode(SkXfermode::Mode mode) { 1697 SkASSERT(NULL == gCachedXfermodes[mode]); 1698 1699 ProcCoeff rec = gProcCoeffs[mode]; 1700 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); 1701 if (pp != NULL) { 1702 rec.fProc = pp; 1703 } 1704 1705 SkXfermode* xfer = NULL; 1706 // check if we have a platform optim for that 1707 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); 1708 if (xfm != NULL) { 1709 xfer = xfm; 1710 } else { 1711 // All modes can in theory be represented by the ProcCoeff rec, since 1712 // it contains function ptrs. However, a few modes are both simple and 1713 // commonly used, so we call those out for their own subclasses here. 1714 switch (mode) { 1715 case SkXfermode::kClear_Mode: 1716 xfer = SkClearXfermode::Create(rec); 1717 break; 1718 case SkXfermode::kSrc_Mode: 1719 xfer = SkSrcXfermode::Create(rec); 1720 break; 1721 case SkXfermode::kSrcOver_Mode: 1722 SkASSERT(false); // should not land here 1723 break; 1724 case SkXfermode::kDstIn_Mode: 1725 xfer = SkDstInXfermode::Create(rec); 1726 break; 1727 case SkXfermode::kDstOut_Mode: 1728 xfer = SkDstOutXfermode::Create(rec); 1729 break; 1730 default: 1731 // no special-case, just rely in the rec and its function-ptrs 1732 xfer = SkProcCoeffXfermode::Create(rec, mode); 1733 break; 1734 } 1735 } 1736 gCachedXfermodes[mode] = xfer; 1737} 1738 1739SkXfermode* SkXfermode::Create(Mode mode) { 1740 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1741 SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount); 1742 1743 if ((unsigned)mode >= kModeCount) { 1744 // report error 1745 return NULL; 1746 } 1747 1748 // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover 1749 // so we can just return NULL from the factory. 1750 if (kSrcOver_Mode == mode) { 1751 return NULL; 1752 } 1753 1754 SkOnce(&gXfermodeCached[mode], &gCachedXfermodesMutex, create_mode, mode); 1755 SkXfermode* xfer = gCachedXfermodes[mode]; 1756 SkASSERT(xfer != NULL); 1757 return SkSafeRef(xfer); 1758} 1759 1760SkXfermodeProc SkXfermode::GetProc(Mode mode) { 1761 SkXfermodeProc proc = NULL; 1762 if ((unsigned)mode < kModeCount) { 1763 proc = gProcCoeffs[mode].fProc; 1764 } 1765 return proc; 1766} 1767 1768bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1769 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1770 1771 if ((unsigned)mode >= (unsigned)kModeCount) { 1772 // illegal mode parameter 1773 return false; 1774 } 1775 1776 const ProcCoeff& rec = gProcCoeffs[mode]; 1777 1778 if (CANNOT_USE_COEFF == rec.fSC) { 1779 return false; 1780 } 1781 1782 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1783 if (src) { 1784 *src = rec.fSC; 1785 } 1786 if (dst) { 1787 *dst = rec.fDC; 1788 } 1789 return true; 1790} 1791 1792bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { 1793 if (NULL == xfer) { 1794 if (mode) { 1795 *mode = kSrcOver_Mode; 1796 } 1797 return true; 1798 } 1799 return xfer->asMode(mode); 1800} 1801 1802bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { 1803 if (NULL == xfer) { 1804 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1805 } 1806 return xfer->asCoeff(src, dst); 1807} 1808 1809bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { 1810 // if xfer==null then the mode is srcover 1811 Mode m = kSrcOver_Mode; 1812 if (xfer && !xfer->asMode(&m)) { 1813 return false; 1814 } 1815 return mode == m; 1816} 1817 1818/////////////////////////////////////////////////////////////////////////////// 1819//////////// 16bit xfermode procs 1820 1821#ifdef SK_DEBUG 1822static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1823static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1824#endif 1825 1826static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1827 SkASSERT(require_255(src)); 1828 return SkPixel32ToPixel16(src); 1829} 1830 1831static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1832 return dst; 1833} 1834 1835static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1836 SkASSERT(require_0(src)); 1837 return dst; 1838} 1839 1840static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1841 SkASSERT(require_255(src)); 1842 return SkPixel32ToPixel16(src); 1843} 1844 1845static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1846 SkASSERT(require_0(src)); 1847 return dst; 1848} 1849 1850static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1851 SkASSERT(require_255(src)); 1852 return dst; 1853} 1854 1855static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1856 SkASSERT(require_255(src)); 1857 return SkPixel32ToPixel16(src); 1858} 1859 1860static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1861 SkASSERT(require_255(src)); 1862 return dst; 1863} 1864 1865static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1866 SkASSERT(require_0(src)); 1867 return dst; 1868} 1869 1870static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1871 unsigned isa = 255 - SkGetPackedA32(src); 1872 1873 return SkPackRGB16( 1874 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1875 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1876 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1877} 1878 1879static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1880 SkASSERT(require_0(src)); 1881 return dst; 1882} 1883 1884static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1885 SkASSERT(require_255(src)); 1886 return SkPixel32ToPixel16(src); 1887} 1888 1889static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1890 SkASSERT(require_255(src)); 1891 return dst; 1892} 1893 1894/********* 1895 darken and lighten boil down to this. 1896 1897 darken = (1 - Sa) * Dc + min(Sc, Dc) 1898 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1899 1900 if (Sa == 0) these become 1901 darken = Dc + min(0, Dc) = 0 1902 lighten = Dc + max(0, Dc) = Dc 1903 1904 if (Sa == 1) these become 1905 darken = min(Sc, Dc) 1906 lighten = max(Sc, Dc) 1907*/ 1908 1909static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1910 SkASSERT(require_0(src)); 1911 return 0; 1912} 1913 1914static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1915 SkASSERT(require_255(src)); 1916 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1917 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1918 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1919 return SkPackRGB16(r, g, b); 1920} 1921 1922static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1923 SkASSERT(require_0(src)); 1924 return dst; 1925} 1926 1927static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1928 SkASSERT(require_255(src)); 1929 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1930 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1931 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1932 return SkPackRGB16(r, g, b); 1933} 1934 1935struct Proc16Rec { 1936 SkXfermodeProc16 fProc16_0; 1937 SkXfermodeProc16 fProc16_255; 1938 SkXfermodeProc16 fProc16_General; 1939}; 1940 1941static const Proc16Rec gModeProcs16[] = { 1942 { NULL, NULL, NULL }, // CLEAR 1943 { NULL, src_modeproc16_255, NULL }, 1944 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1945 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1946 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1947 { NULL, srcin_modeproc16_255, NULL }, 1948 { NULL, dstin_modeproc16_255, NULL }, 1949 { NULL, NULL, NULL },// SRC_OUT 1950 { dstout_modeproc16_0, NULL, NULL }, 1951 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1952 { NULL, dstatop_modeproc16_255, NULL }, 1953 { NULL, NULL, NULL }, // XOR 1954 1955 { NULL, NULL, NULL }, // plus 1956 { NULL, NULL, NULL }, // modulate 1957 { NULL, NULL, NULL }, // screen 1958 { NULL, NULL, NULL }, // overlay 1959 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1960 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1961 { NULL, NULL, NULL }, // colordodge 1962 { NULL, NULL, NULL }, // colorburn 1963 { NULL, NULL, NULL }, // hardlight 1964 { NULL, NULL, NULL }, // softlight 1965 { NULL, NULL, NULL }, // difference 1966 { NULL, NULL, NULL }, // exclusion 1967 { NULL, NULL, NULL }, // multiply 1968 { NULL, NULL, NULL }, // hue 1969 { NULL, NULL, NULL }, // saturation 1970 { NULL, NULL, NULL }, // color 1971 { NULL, NULL, NULL }, // luminosity 1972}; 1973 1974SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1975 SkXfermodeProc16 proc16 = NULL; 1976 if ((unsigned)mode < kModeCount) { 1977 const Proc16Rec& rec = gModeProcs16[mode]; 1978 unsigned a = SkColorGetA(srcColor); 1979 1980 if (0 == a) { 1981 proc16 = rec.fProc16_0; 1982 } else if (255 == a) { 1983 proc16 = rec.fProc16_255; 1984 } else { 1985 proc16 = rec.fProc16_General; 1986 } 1987 } 1988 return proc16; 1989} 1990 1991SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1992 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1993 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1994 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1995 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1996 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1997#if !SK_ARM_NEON_IS_NONE 1998 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode) 1999#endif 2000#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 2001 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSSE2ProcCoeffXfermode) 2002#endif 2003SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 2004