Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkXfermode.h" | 8 #include "SkXfermode.h" |
| 9 #include "SkXfermode_proccoeff.h" | 9 #include "SkXfermode_proccoeff.h" |
| 10 #include "SkColorPriv.h" | 10 #include "SkColorPriv.h" |
| 11 #include "SkMathPriv.h" | 11 #include "SkMathPriv.h" |
| 12 #include "SkOnce.h" | 12 #include "SkOnce.h" |
| 13 #include "SkOpts.h" | 13 #include "SkOpts.h" |
| 14 #include "SkRasterPipeline.h" | |
| 14 #include "SkReadBuffer.h" | 15 #include "SkReadBuffer.h" |
| 15 #include "SkString.h" | 16 #include "SkString.h" |
| 16 #include "SkWriteBuffer.h" | 17 #include "SkWriteBuffer.h" |
| 17 #include "SkPM4f.h" | 18 #include "SkPM4f.h" |
| 18 | 19 |
| 19 #if SK_SUPPORT_GPU | 20 #if SK_SUPPORT_GPU |
| 20 #include "GrFragmentProcessor.h" | 21 #include "GrFragmentProcessor.h" |
| 21 #include "effects/GrCustomXfermode.h" | 22 #include "effects/GrCustomXfermode.h" |
| 22 #include "effects/GrPorterDuffXferProcessor.h" | 23 #include "effects/GrPorterDuffXferProcessor.h" |
| 23 #include "effects/GrXfermodeFragmentProcessor.h" | 24 #include "effects/GrXfermodeFragmentProcessor.h" |
| (...skipping 1400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1424 return this->onAppendStages(pipeline); | 1425 return this->onAppendStages(pipeline); |
| 1425 } | 1426 } |
| 1426 | 1427 |
| 1427 bool SkXfermode::onAppendStages(SkRasterPipeline*) const { | 1428 bool SkXfermode::onAppendStages(SkRasterPipeline*) const { |
| 1428 return false; | 1429 return false; |
| 1429 } | 1430 } |
| 1430 | 1431 |
| 1431 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) | 1432 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
| 1432 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) | 1433 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
| 1433 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1434 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
| 1435 | |
| 1436 static Sk4f inv(const Sk4f& x) { return 1.0f - x; } | |
| 1437 | |
| 1438 // Most of these modes apply the same logic kernel to each channel. | |
| 1439 template <Sk4f kernel(const Sk4f& s, const Sk4f& sa, const Sk4f& d, const Sk4f& da)> | |
|
reed1
2016/07/25 16:40:28
given vector_call, do we still need to pass by con
mtklein
2016/07/25 17:48:18
Yes we could require kernel's type to be
Sk4f
| |
| 1440 static void SK_VECTORCALL rgba(SkRasterPipeline::Stage* st, size_t x, | |
| 1441 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | |
| 1442 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 1443 r = kernel(r,a,dr,da); | |
| 1444 g = kernel(g,a,dg,da); | |
| 1445 b = kernel(b,a,db,da); | |
| 1446 a = kernel(a,a,da,da); | |
| 1447 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 1448 } | |
| 1449 | |
| 1450 #define KERNEL(name) static Sk4f name(const Sk4f& s, const Sk4f& sa, const Sk4f& d, const Sk4f& da) | |
| 1451 KERNEL(clear) { return 0.0f; } | |
| 1452 KERNEL(dst) { return d; } | |
| 1453 KERNEL(dstover) { return d + inv(da)*s; } | |
| 1454 | |
| 1455 KERNEL(srcin) { return s * da; } | |
| 1456 KERNEL(srcout) { return s * inv(da); } | |
| 1457 KERNEL(srcatop) { return s*da + d*inv(sa); } | |
| 1458 KERNEL(dstin) { return srcin (d,da,s,sa); } | |
| 1459 KERNEL(dstout) { return srcout (d,da,s,sa); } | |
| 1460 KERNEL(dstatop) { return srcatop(d,da,s,sa); } | |
| 1461 | |
| 1462 KERNEL(modulate) { return s*d; } | |
| 1463 KERNEL(multiply) { return s*inv(da) + d*inv(sa) + s*d; } | |
| 1464 KERNEL(plus) { return s + d; } | |
| 1465 KERNEL(screen) { return s + d - s*d; } | |
| 1466 KERNEL(xor_) { return s*inv(da) + d*inv(sa); } | |
| 1467 | |
| 1468 // Most of the rest apply the same logic to each color channel, and srcover's lo gic to alpha. | |
| 1469 // (darken and lighten can actually go either way, but they're a little faster t his way.) | |
| 1470 template <Sk4f kernel(const Sk4f& s, const Sk4f& sa, const Sk4f& d, const Sk4f& da)> | |
| 1471 static void SK_VECTORCALL rgb_srcover(SkRasterPipeline::Stage* st, size_t x, | |
| 1472 Sk4f r, Sk4f g, Sk4f b, Sk4f a, | |
| 1473 Sk4f dr, Sk4f dg, Sk4f db, Sk4f da) { | |
| 1474 r = kernel(r,a,dr,da); | |
| 1475 g = kernel(g,a,dg,da); | |
| 1476 b = kernel(b,a,db,da); | |
| 1477 a = a + da*inv(a); | |
| 1478 st->next(x, r,g,b,a, dr,dg,db,da); | |
| 1479 } | |
| 1480 | |
| 1481 KERNEL(colorburn) { | |
| 1482 return (d == da ).thenElse(d + s*inv(da), | |
| 1483 (s == 0.0f).thenElse(s + d*inv(sa), | |
| 1484 sa*(da - Sk4f::Min(da, (da-d)*sa/s)) + s*inv(da) + d*inv(sa))); | |
| 1485 } | |
| 1486 KERNEL(colordodge) { | |
| 1487 return (d == 0.0f).thenElse(d + s*inv(da), | |
| 1488 (s == sa ).thenElse(s + d*inv(sa), | |
| 1489 sa*Sk4f::Min(da, (d*sa)/(sa - s)) + s*inv(da) + d*inv(sa))); | |
| 1490 } | |
| 1491 KERNEL(darken) { return s + d - Sk4f::Max(s*da, d*sa); } | |
| 1492 KERNEL(difference) { return s + d - 2.0f*Sk4f::Min(s*da,d*sa); } | |
| 1493 KERNEL(exclusion) { return s + d - 2.0f*s*d; } | |
| 1494 KERNEL(hardlight) { | |
| 1495 return s*inv(da) + d*inv(sa) | |
| 1496 + (2.0f*s <= sa).thenElse(2.0f*s*d, sa*da - 2.0f*(da-d)*(sa-s)); | |
| 1497 } | |
| 1498 KERNEL(lighten) { return s + d - Sk4f::Min(s*da, d*sa); } | |
| 1499 KERNEL(overlay) { return hardlight(d,da,s,sa); } | |
| 1500 KERNEL(softlight) { | |
| 1501 Sk4f m = (da > 0.0f).thenElse(d / da, 0.0f), | |
| 1502 s2 = 2.0f*s, | |
| 1503 m4 = 4.0f*m; | |
| 1504 | |
| 1505 // The logic forks three ways: | |
| 1506 // 1. dark src? | |
| 1507 // 2. light src, dark dst? | |
| 1508 // 3. light src, light dst? | |
| 1509 Sk4f darkSrc = d*(sa + (s2 - sa)*(1.0f - m)), // Used in case 1. | |
| 1510 darkDst = (m4*m4 + m4)*(m - 1.0f) + 7.0f*m, // Used in case 2. | |
| 1511 liteDst = m.rsqrt().invert() - m, // Used in case 3. | |
| 1512 liteSrc = d*sa + da*(s2 - sa) * (4.0f*d <= da).thenElse(darkDst, liteDs t); // 2 or 3? | |
| 1513 return s*inv(da) + d*inv(sa) + (s2 <= sa).thenElse(darkSrc, liteSrc); // 1 or (2 or 3)? | |
| 1514 } | |
| 1515 #undef KERNEL | |
| 1516 | |
| 1517 bool SkProcCoeffXfermode::onAppendStages(SkRasterPipeline* p) const { | |
| 1518 switch (fMode) { | |
| 1519 case kSrcOver_Mode: SkASSERT(false); return false; // Well how did we g et here? | |
| 1520 | |
| 1521 case kSrc_Mode: /*This stage is a no-op.*/ return true; | |
| 1522 case kDst_Mode: p->append(rgba<dst>); return true; | |
| 1523 case kSrcATop_Mode: p->append(rgba<srcatop>); return true; | |
| 1524 case kDstATop_Mode: p->append(rgba<dstatop>); return true; | |
| 1525 case kSrcIn_Mode: p->append(rgba<srcin>); return true; | |
| 1526 case kDstIn_Mode: p->append(rgba<dstin>); return true; | |
| 1527 case kSrcOut_Mode: p->append(rgba<srcout>); return true; | |
| 1528 case kDstOut_Mode: p->append(rgba<dstout>); return true; | |
| 1529 case kDstOver_Mode: p->append(rgba<dstover>); return true; | |
| 1530 | |
| 1531 case kClear_Mode: p->append(rgba<clear>); return true; | |
| 1532 case kModulate_Mode: p->append(rgba<modulate>); return true; | |
| 1533 case kMultiply_Mode: p->append(rgba<multiply>); return true; | |
| 1534 case kPlus_Mode: p->append(rgba<plus>); return true; | |
| 1535 case kScreen_Mode: p->append(rgba<screen>); return true; | |
| 1536 case kXor_Mode: p->append(rgba<xor_>); return true; | |
| 1537 | |
| 1538 case kColorBurn_Mode: p->append(rgb_srcover<colorburn>); return true; | |
| 1539 case kColorDodge_Mode: p->append(rgb_srcover<colordodge>); return true; | |
| 1540 case kDarken_Mode: p->append(rgb_srcover<darken>); return true; | |
| 1541 case kDifference_Mode: p->append(rgb_srcover<difference>); return true; | |
| 1542 case kExclusion_Mode: p->append(rgb_srcover<exclusion>); return true; | |
| 1543 case kHardLight_Mode: p->append(rgb_srcover<hardlight>); return true; | |
| 1544 case kLighten_Mode: p->append(rgb_srcover<lighten>); return true; | |
| 1545 case kOverlay_Mode: p->append(rgb_srcover<overlay>); return true; | |
| 1546 case kSoftLight_Mode: p->append(rgb_srcover<softlight>); return true; | |
| 1547 | |
| 1548 // TODO | |
| 1549 case kColor_Mode: return false; | |
| 1550 case kHue_Mode: return false; | |
| 1551 case kLuminosity_Mode: return false; | |
| 1552 case kSaturation_Mode: return false; | |
| 1553 } | |
| 1554 return false; | |
| 1555 } | |
| OLD | NEW |