| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkXfermode.h" | 10 #include "SkXfermode.h" |
| 11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
| 12 #include "SkFlattenableBuffers.h" | 12 #include "SkFlattenableBuffers.h" |
| 13 #include "SkMathPriv.h" | 13 #include "SkMathPriv.h" |
| 14 #include "SkString.h" | 14 #include "SkString.h" |
| 15 #include "SkXfermode_proccoeff.h" |
| 15 | 16 |
| 16 SK_DEFINE_INST_COUNT(SkXfermode) | 17 SK_DEFINE_INST_COUNT(SkXfermode) |
| 17 | 18 |
| 18 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) | 19 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) |
| 19 | 20 |
| 20 #if 0 | 21 #if 0 |
| 21 // idea for higher precision blends in xfer procs (and slightly faster) | 22 // idea for higher precision blends in xfer procs (and slightly faster) |
| 22 // see DstATop as a probable caller | 23 // see DstATop as a probable caller |
| 23 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { | 24 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { |
| 24 SkASSERT(a <= 255); | 25 SkASSERT(a <= 255); |
| (...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 Db = 0; | 625 Db = 0; |
| 625 } | 626 } |
| 626 | 627 |
| 627 int a = srcover_byte(sa, da); | 628 int a = srcover_byte(sa, da); |
| 628 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); | 629 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); |
| 629 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); | 630 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); |
| 630 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); | 631 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); |
| 631 return SkPackARGB32(a, r, g, b); | 632 return SkPackARGB32(a, r, g, b); |
| 632 } | 633 } |
| 633 | 634 |
| 634 | 635 const ProcCoeff gProcCoeffs[] = { |
| 635 struct ProcCoeff { | |
| 636 SkXfermodeProc fProc; | |
| 637 SkXfermode::Coeff fSC; | |
| 638 SkXfermode::Coeff fDC; | |
| 639 }; | |
| 640 | |
| 641 #define CANNOT_USE_COEFF SkXfermode::Coeff(-1) | |
| 642 | |
| 643 static const ProcCoeff gProcCoeffs[] = { | |
| 644 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, | 636 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, |
| 645 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, | 637 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, |
| 646 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, | 638 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, |
| 647 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, | 639 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, |
| 648 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, | 640 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, |
| 649 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, | 641 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, |
| 650 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, | 642 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, |
| 651 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, | 643 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, |
| 652 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, | 644 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, |
| 653 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, | 645 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, |
| (...skipping 691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1345 | 1337 |
| 1346 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermod
e::Mode>(mode), NULL))); | 1338 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermod
e::Mode>(mode), NULL))); |
| 1347 return CreateEffectRef(gEffect); | 1339 return CreateEffectRef(gEffect); |
| 1348 } | 1340 } |
| 1349 | 1341 |
| 1350 #endif | 1342 #endif |
| 1351 | 1343 |
| 1352 /////////////////////////////////////////////////////////////////////////////// | 1344 /////////////////////////////////////////////////////////////////////////////// |
| 1353 /////////////////////////////////////////////////////////////////////////////// | 1345 /////////////////////////////////////////////////////////////////////////////// |
| 1354 | 1346 |
| 1355 class SkProcCoeffXfermode : public SkProcXfermode { | |
| 1356 public: | |
| 1357 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) | |
| 1358 : INHERITED(rec.fProc) { | |
| 1359 fMode = mode; | |
| 1360 // these may be valid, or may be CANNOT_USE_COEFF | |
| 1361 fSrcCoeff = rec.fSC; | |
| 1362 fDstCoeff = rec.fDC; | |
| 1363 } | |
| 1364 | |
| 1365 virtual bool asMode(Mode* mode) const SK_OVERRIDE { | |
| 1366 if (mode) { | |
| 1367 *mode = fMode; | |
| 1368 } | |
| 1369 return true; | |
| 1370 } | |
| 1371 | |
| 1372 virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE { | |
| 1373 if (CANNOT_USE_COEFF == fSrcCoeff) { | |
| 1374 return false; | |
| 1375 } | |
| 1376 | |
| 1377 if (sc) { | |
| 1378 *sc = fSrcCoeff; | |
| 1379 } | |
| 1380 if (dc) { | |
| 1381 *dc = fDstCoeff; | |
| 1382 } | |
| 1383 return true; | |
| 1384 } | |
| 1385 | |
| 1386 #if SK_SUPPORT_GPU | |
| 1387 virtual bool asNewEffectOrCoeff(GrContext*, | |
| 1388 GrEffectRef** effect, | |
| 1389 Coeff* src, | |
| 1390 Coeff* dst, | |
| 1391 GrTexture* background) const SK_OVERRIDE { | |
| 1392 if (this->asCoeff(src, dst)) { | |
| 1393 return true; | |
| 1394 } | |
| 1395 if (XferEffect::IsSupportedMode(fMode)) { | |
| 1396 if (NULL != effect) { | |
| 1397 *effect = XferEffect::Create(fMode, background); | |
| 1398 SkASSERT(NULL != *effect); | |
| 1399 } | |
| 1400 return true; | |
| 1401 } | |
| 1402 return false; | |
| 1403 } | |
| 1404 #endif | |
| 1405 | |
| 1406 SK_DEVELOPER_TO_STRING() | |
| 1407 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) | |
| 1408 | |
| 1409 protected: | |
| 1410 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { | |
| 1411 fMode = (SkXfermode::Mode)buffer.read32(); | |
| 1412 | |
| 1413 const ProcCoeff& rec = gProcCoeffs[fMode]; | |
| 1414 // these may be valid, or may be CANNOT_USE_COEFF | |
| 1415 fSrcCoeff = rec.fSC; | |
| 1416 fDstCoeff = rec.fDC; | |
| 1417 // now update our function-ptr in the super class | |
| 1418 this->INHERITED::setProc(rec.fProc); | |
| 1419 } | |
| 1420 | |
| 1421 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { | |
| 1422 this->INHERITED::flatten(buffer); | |
| 1423 buffer.write32(fMode); | |
| 1424 } | |
| 1425 | |
| 1426 private: | |
| 1427 Mode fMode; | |
| 1428 Coeff fSrcCoeff, fDstCoeff; | |
| 1429 | |
| 1430 typedef SkProcXfermode INHERITED; | |
| 1431 }; | |
| 1432 | 1347 |
| 1433 const char* SkXfermode::ModeName(Mode mode) { | 1348 const char* SkXfermode::ModeName(Mode mode) { |
| 1434 SkASSERT((unsigned) mode <= (unsigned)kLastMode); | 1349 SkASSERT((unsigned) mode <= (unsigned)kLastMode); |
| 1435 const char* gModeStrings[] = { | 1350 const char* gModeStrings[] = { |
| 1436 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", | 1351 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", |
| 1437 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", | 1352 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", |
| 1438 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", | 1353 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", |
| 1439 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", | 1354 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", |
| 1440 "Multiply", "Hue", "Saturation", "Color", "Luminosity" | 1355 "Multiply", "Hue", "Saturation", "Color", "Luminosity" |
| 1441 }; | 1356 }; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1681 } | 1596 } |
| 1682 | 1597 |
| 1683 #ifdef SK_DEVELOPER | 1598 #ifdef SK_DEVELOPER |
| 1684 void SkDstOutXfermode::toString(SkString* str) const { | 1599 void SkDstOutXfermode::toString(SkString* str) const { |
| 1685 this->INHERITED::toString(str); | 1600 this->INHERITED::toString(str); |
| 1686 } | 1601 } |
| 1687 #endif | 1602 #endif |
| 1688 | 1603 |
| 1689 /////////////////////////////////////////////////////////////////////////////// | 1604 /////////////////////////////////////////////////////////////////////////////// |
| 1690 | 1605 |
| 1606 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXf
ermode::Mode mode); |
| 1607 |
| 1691 SkXfermode* SkXfermode::Create(Mode mode) { | 1608 SkXfermode* SkXfermode::Create(Mode mode) { |
| 1692 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); | 1609 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); |
| 1693 SkASSERT((unsigned)mode < kModeCount); | 1610 SkASSERT((unsigned)mode < kModeCount); |
| 1694 | 1611 |
| 1695 const ProcCoeff& rec = gProcCoeffs[mode]; | 1612 const ProcCoeff& rec = gProcCoeffs[mode]; |
| 1696 | 1613 |
| 1614 // check if we have a platform optim for that |
| 1615 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); |
| 1616 if (xfm != NULL) { |
| 1617 return xfm; |
| 1618 } |
| 1619 |
| 1697 switch (mode) { | 1620 switch (mode) { |
| 1698 case kClear_Mode: | 1621 case kClear_Mode: |
| 1699 return SkNEW_ARGS(SkClearXfermode, (rec)); | 1622 return SkNEW_ARGS(SkClearXfermode, (rec)); |
| 1700 case kSrc_Mode: | 1623 case kSrc_Mode: |
| 1701 return SkNEW_ARGS(SkSrcXfermode, (rec)); | 1624 return SkNEW_ARGS(SkSrcXfermode, (rec)); |
| 1702 case kSrcOver_Mode: | 1625 case kSrcOver_Mode: |
| 1703 return NULL; | 1626 return NULL; |
| 1704 case kDstIn_Mode: | 1627 case kDstIn_Mode: |
| 1705 return SkNEW_ARGS(SkDstInXfermode, (rec)); | 1628 return SkNEW_ARGS(SkDstInXfermode, (rec)); |
| 1706 case kDstOut_Mode: | 1629 case kDstOut_Mode: |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1941 return proc16; | 1864 return proc16; |
| 1942 } | 1865 } |
| 1943 | 1866 |
| 1944 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) | 1867 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
| 1945 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) | 1868 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
| 1946 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) | 1869 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) |
| 1947 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) | 1870 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) |
| 1948 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) | 1871 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) |
| 1949 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) | 1872 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) |
| 1950 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1873 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| OLD | NEW |