| Index: src/core/SkXfermode.cpp
|
| diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
|
| index ba9670a9dbc1aa9222912ea672c0b8567ce65341..ee000233d57e9fa95cc7bde0777640ccd4226970 100644
|
| --- a/src/core/SkXfermode.cpp
|
| +++ b/src/core/SkXfermode.cpp
|
| @@ -9,6 +9,7 @@
|
| #include "SkXfermode.h"
|
| #include "SkXfermode_opts_SSE2.h"
|
| #include "SkXfermode_proccoeff.h"
|
| +#include "Sk4px.h"
|
| #include "SkColorPriv.h"
|
| #include "SkLazyPtr.h"
|
| #include "SkMathPriv.h"
|
| @@ -1269,7 +1270,10 @@ struct Plus4f {
|
| static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
|
| return check_as_pmfloat(clamp_255(src + dst));
|
| }
|
| - static const bool kFoldCoverageIntoSrcAlpha = true;
|
| + static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
|
| + return src.saturatedAdd(dst);
|
| + }
|
| + static const bool kFoldCoverageIntoSrcAlpha = false;
|
| static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode;
|
| };
|
|
|
| @@ -1279,6 +1283,9 @@ struct Modulate4f {
|
| const Sk4f inv255(gInv255);
|
| return check_as_pmfloat(src * dst * inv255);
|
| }
|
| + static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
|
| + return src.mulWiden(dst).div255RoundNarrow();
|
| + }
|
| static const bool kFoldCoverageIntoSrcAlpha = false;
|
| static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode;
|
| };
|
| @@ -1289,6 +1296,12 @@ struct Screen4f {
|
| const Sk4f inv255(gInv255);
|
| return check_as_pmfloat(src + dst - src * dst * inv255);
|
| }
|
| + static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
|
| + // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract can be done
|
| + // in 8-bit space without overflow. S + (1-S)*D is a touch faster because 255-x is an xor.
|
| + // TODO: do we need to explicitly implement / call Sk16b(255) ^ src ?
|
| + return src + Sk4px(Sk16b(255) - src).mulWiden(dst).div255RoundNarrow();
|
| + }
|
| static const bool kFoldCoverageIntoSrcAlpha = true;
|
| static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode;
|
| };
|
| @@ -1370,6 +1383,35 @@ private:
|
|
|
| typedef SkProcCoeffXfermode INHERITED;
|
| };
|
| +
|
| +template <typename ProcType>
|
| +class SkT4pxXfermode : public SkProcCoeffXfermode {
|
| +public:
|
| + static SkXfermode* Create(const ProcCoeff& rec) {
|
| + return SkNEW_ARGS(SkT4pxXfermode, (rec));
|
| + }
|
| +
|
| + void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
|
| + if (NULL == aa) {
|
| + Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& src4) {
|
| + return ProcType::Xfer(src4, dst4);
|
| + });
|
| + } else {
|
| + Sk4px::MapDstSrcAlpha(n, dst, src, aa,
|
| + [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha) {
|
| + // We can't exploit kFoldCoverageIntoSrcAlpha. That requires >=24-bit intermediates.
|
| + Sk4px res4 = ProcType::Xfer(src4, dst4);
|
| + return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk16b(255)-alpha))
|
| + .div255RoundNarrow();
|
| + });
|
| + }
|
| + }
|
| +
|
| +private:
|
| + SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
|
| +
|
| + typedef SkProcCoeffXfermode INHERITED;
|
| +};
|
| #endif
|
|
|
| ///////////////////////////////////////////////////////////////////////////////
|
| @@ -1445,6 +1487,7 @@ SkXfermode* create_mode(int iMode) {
|
| case SkXfermode::kXor_Mode:
|
| xfer = SkT4fXfermode<Xor4f>::Create(rec);
|
| break;
|
| + #ifdef SK_PREFER_LEGACY_FLOAT_XFERMODES
|
| case SkXfermode::kPlus_Mode:
|
| xfer = SkT4fXfermode<Plus4f>::Create(rec);
|
| break;
|
| @@ -1454,6 +1497,17 @@ SkXfermode* create_mode(int iMode) {
|
| case SkXfermode::kScreen_Mode:
|
| xfer = SkT4fXfermode<Screen4f>::Create(rec);
|
| break;
|
| + #else
|
| + case SkXfermode::kPlus_Mode:
|
| + xfer = SkT4pxXfermode<Plus4f>::Create(rec);
|
| + break;
|
| + case SkXfermode::kModulate_Mode:
|
| + xfer = SkT4pxXfermode<Modulate4f>::Create(rec);
|
| + break;
|
| + case SkXfermode::kScreen_Mode:
|
| + xfer = SkT4pxXfermode<Screen4f>::Create(rec);
|
| + break;
|
| + #endif
|
| case SkXfermode::kMultiply_Mode:
|
| xfer = SkT4fXfermode<Multiply4f>::Create(rec);
|
| break;
|
|
|