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 #include "SkXfermode.h" | 9 #include "SkXfermode.h" |
10 #include "SkXfermode_opts_SSE2.h" | 10 #include "SkXfermode_opts_SSE2.h" |
11 #include "SkXfermode_proccoeff.h" | 11 #include "SkXfermode_proccoeff.h" |
| 12 #include "Sk4px.h" |
12 #include "SkColorPriv.h" | 13 #include "SkColorPriv.h" |
13 #include "SkLazyPtr.h" | 14 #include "SkLazyPtr.h" |
14 #include "SkMathPriv.h" | 15 #include "SkMathPriv.h" |
15 #include "SkPMFloat.h" | 16 #include "SkPMFloat.h" |
16 #include "SkReadBuffer.h" | 17 #include "SkReadBuffer.h" |
17 #include "SkString.h" | 18 #include "SkString.h" |
18 #include "SkUtilsArm.h" | 19 #include "SkUtilsArm.h" |
19 #include "SkWriteBuffer.h" | 20 #include "SkWriteBuffer.h" |
20 | 21 |
21 #ifndef SK_SUPPORT_LEGACY_SCALAR_XFERMODES | 22 #ifndef SK_SUPPORT_LEGACY_SCALAR_XFERMODES |
(...skipping 1240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1262 } | 1263 } |
1263 static const bool kFoldCoverageIntoSrcAlpha = true; | 1264 static const bool kFoldCoverageIntoSrcAlpha = true; |
1264 static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode; | 1265 static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode; |
1265 }; | 1266 }; |
1266 | 1267 |
1267 // kPlus_Mode [Sa + Da, Sc + Dc] | 1268 // kPlus_Mode [Sa + Da, Sc + Dc] |
1268 struct Plus4f { | 1269 struct Plus4f { |
1269 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | 1270 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { |
1270 return check_as_pmfloat(clamp_255(src + dst)); | 1271 return check_as_pmfloat(clamp_255(src + dst)); |
1271 } | 1272 } |
1272 static const bool kFoldCoverageIntoSrcAlpha = true; | 1273 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { |
| 1274 return src.saturatedAdd(dst); |
| 1275 } |
| 1276 static const bool kFoldCoverageIntoSrcAlpha = false; |
1273 static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode; | 1277 static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode; |
1274 }; | 1278 }; |
1275 | 1279 |
1276 // kModulate_Mode [Sa * Da, Sc * Dc] | 1280 // kModulate_Mode [Sa * Da, Sc * Dc] |
1277 struct Modulate4f { | 1281 struct Modulate4f { |
1278 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | 1282 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { |
1279 const Sk4f inv255(gInv255); | 1283 const Sk4f inv255(gInv255); |
1280 return check_as_pmfloat(src * dst * inv255); | 1284 return check_as_pmfloat(src * dst * inv255); |
1281 } | 1285 } |
| 1286 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { |
| 1287 return src.mulWiden(dst).div255RoundNarrow(); |
| 1288 } |
1282 static const bool kFoldCoverageIntoSrcAlpha = false; | 1289 static const bool kFoldCoverageIntoSrcAlpha = false; |
1283 static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode; | 1290 static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode; |
1284 }; | 1291 }; |
1285 | 1292 |
1286 // kScreen_Mode [S + D - S * D] | 1293 // kScreen_Mode [S + D - S * D] |
1287 struct Screen4f { | 1294 struct Screen4f { |
1288 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | 1295 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { |
1289 const Sk4f inv255(gInv255); | 1296 const Sk4f inv255(gInv255); |
1290 return check_as_pmfloat(src + dst - src * dst * inv255); | 1297 return check_as_pmfloat(src + dst - src * dst * inv255); |
1291 } | 1298 } |
| 1299 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { |
| 1300 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subt
ract can be done |
| 1301 // in 8-bit space without overflow. S + (1-S)*D is a touch faster becau
se 255-x is an xor. |
| 1302 // TODO: do we need to explicitly implement / call Sk16b(255) ^ src ? |
| 1303 return src + Sk4px(Sk16b(255) - src).mulWiden(dst).div255RoundNarrow(); |
| 1304 } |
1292 static const bool kFoldCoverageIntoSrcAlpha = true; | 1305 static const bool kFoldCoverageIntoSrcAlpha = true; |
1293 static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode; | 1306 static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode; |
1294 }; | 1307 }; |
1295 | 1308 |
1296 struct Multiply4f { | 1309 struct Multiply4f { |
1297 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | 1310 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { |
1298 const Sk4f inv255(gInv255); | 1311 const Sk4f inv255(gInv255); |
1299 Sk4f sa = Sk4f(src.a()); | 1312 Sk4f sa = Sk4f(src.a()); |
1300 Sk4f da = Sk4f(dst.a()); | 1313 Sk4f da = Sk4f(dst.a()); |
1301 Sk4f sc = src; | 1314 Sk4f sc = src; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1363 dst[i] = SkPMFloat(res).round(); | 1376 dst[i] = SkPMFloat(res).round(); |
1364 } | 1377 } |
1365 } | 1378 } |
1366 } | 1379 } |
1367 | 1380 |
1368 private: | 1381 private: |
1369 SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMo
de) {} | 1382 SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMo
de) {} |
1370 | 1383 |
1371 typedef SkProcCoeffXfermode INHERITED; | 1384 typedef SkProcCoeffXfermode INHERITED; |
1372 }; | 1385 }; |
| 1386 |
| 1387 template <typename ProcType> |
| 1388 class SkT4pxXfermode : public SkProcCoeffXfermode { |
| 1389 public: |
| 1390 static SkXfermode* Create(const ProcCoeff& rec) { |
| 1391 return SkNEW_ARGS(SkT4pxXfermode, (rec)); |
| 1392 } |
| 1393 |
| 1394 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { |
| 1395 if (NULL == aa) { |
| 1396 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr
c4) { |
| 1397 return ProcType::Xfer(src4, dst4); |
| 1398 }); |
| 1399 } else { |
| 1400 Sk4px::MapDstSrcAlpha(n, dst, src, aa, |
| 1401 [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha
) { |
| 1402 // We can't exploit kFoldCoverageIntoSrcAlpha. That requires >=2
4-bit intermediates. |
| 1403 Sk4px res4 = ProcType::Xfer(src4, dst4); |
| 1404 return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk16b(25
5)-alpha)) |
| 1405 .div255RoundNarrow(); |
| 1406 }); |
| 1407 } |
| 1408 } |
| 1409 |
| 1410 private: |
| 1411 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kM
ode) {} |
| 1412 |
| 1413 typedef SkProcCoeffXfermode INHERITED; |
| 1414 }; |
1373 #endif | 1415 #endif |
1374 | 1416 |
1375 /////////////////////////////////////////////////////////////////////////////// | 1417 /////////////////////////////////////////////////////////////////////////////// |
1376 | 1418 |
1377 class SkDstOutXfermode : public SkProcCoeffXfermode { | 1419 class SkDstOutXfermode : public SkProcCoeffXfermode { |
1378 public: | 1420 public: |
1379 static SkDstOutXfermode* Create(const ProcCoeff& rec) { | 1421 static SkDstOutXfermode* Create(const ProcCoeff& rec) { |
1380 return SkNEW_ARGS(SkDstOutXfermode, (rec)); | 1422 return SkNEW_ARGS(SkDstOutXfermode, (rec)); |
1381 } | 1423 } |
1382 | 1424 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 switch (mode) { | 1480 switch (mode) { |
1439 case SkXfermode::kSrcATop_Mode: | 1481 case SkXfermode::kSrcATop_Mode: |
1440 xfer = SkT4fXfermode<SrcATop4f>::Create(rec); | 1482 xfer = SkT4fXfermode<SrcATop4f>::Create(rec); |
1441 break; | 1483 break; |
1442 case SkXfermode::kDstATop_Mode: | 1484 case SkXfermode::kDstATop_Mode: |
1443 xfer = SkT4fXfermode<DstATop4f>::Create(rec); | 1485 xfer = SkT4fXfermode<DstATop4f>::Create(rec); |
1444 break; | 1486 break; |
1445 case SkXfermode::kXor_Mode: | 1487 case SkXfermode::kXor_Mode: |
1446 xfer = SkT4fXfermode<Xor4f>::Create(rec); | 1488 xfer = SkT4fXfermode<Xor4f>::Create(rec); |
1447 break; | 1489 break; |
| 1490 #ifdef SK_PREFER_LEGACY_FLOAT_XFERMODES |
1448 case SkXfermode::kPlus_Mode: | 1491 case SkXfermode::kPlus_Mode: |
1449 xfer = SkT4fXfermode<Plus4f>::Create(rec); | 1492 xfer = SkT4fXfermode<Plus4f>::Create(rec); |
1450 break; | 1493 break; |
1451 case SkXfermode::kModulate_Mode: | 1494 case SkXfermode::kModulate_Mode: |
1452 xfer = SkT4fXfermode<Modulate4f>::Create(rec); | 1495 xfer = SkT4fXfermode<Modulate4f>::Create(rec); |
1453 break; | 1496 break; |
1454 case SkXfermode::kScreen_Mode: | 1497 case SkXfermode::kScreen_Mode: |
1455 xfer = SkT4fXfermode<Screen4f>::Create(rec); | 1498 xfer = SkT4fXfermode<Screen4f>::Create(rec); |
1456 break; | 1499 break; |
| 1500 #else |
| 1501 case SkXfermode::kPlus_Mode: |
| 1502 xfer = SkT4pxXfermode<Plus4f>::Create(rec); |
| 1503 break; |
| 1504 case SkXfermode::kModulate_Mode: |
| 1505 xfer = SkT4pxXfermode<Modulate4f>::Create(rec); |
| 1506 break; |
| 1507 case SkXfermode::kScreen_Mode: |
| 1508 xfer = SkT4pxXfermode<Screen4f>::Create(rec); |
| 1509 break; |
| 1510 #endif |
1457 case SkXfermode::kMultiply_Mode: | 1511 case SkXfermode::kMultiply_Mode: |
1458 xfer = SkT4fXfermode<Multiply4f>::Create(rec); | 1512 xfer = SkT4fXfermode<Multiply4f>::Create(rec); |
1459 break; | 1513 break; |
1460 case SkXfermode::kDifference_Mode: | 1514 case SkXfermode::kDifference_Mode: |
1461 xfer = SkT4fXfermode<Difference4f>::Create(rec); | 1515 xfer = SkT4fXfermode<Difference4f>::Create(rec); |
1462 break; | 1516 break; |
1463 case SkXfermode::kExclusion_Mode: | 1517 case SkXfermode::kExclusion_Mode: |
1464 xfer = SkT4fXfermode<Exclusion4f>::Create(rec); | 1518 xfer = SkT4fXfermode<Exclusion4f>::Create(rec); |
1465 break; | 1519 break; |
1466 default: | 1520 default: |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1762 } else { | 1816 } else { |
1763 proc16 = rec.fProc16_General; | 1817 proc16 = rec.fProc16_General; |
1764 } | 1818 } |
1765 } | 1819 } |
1766 return proc16; | 1820 return proc16; |
1767 } | 1821 } |
1768 | 1822 |
1769 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) | 1823 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
1770 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) | 1824 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
1771 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1825 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |