Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Unified Diff: src/core/Sk4pxXfermode.h

Issue 1214443002: Color dodge and burn with SkPMFloat. (Closed) Base URL: https://skia.googlesource.com/skia@master
Patch Set: reed Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | src/core/SkPMFloat.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/Sk4pxXfermode.h
diff --git a/src/core/Sk4pxXfermode.h b/src/core/Sk4pxXfermode.h
index 09490dc9904b9eab82652b93ecbbed24d68073fb..b58718304610d7ff2decfa08de4db2e291660887 100644
--- a/src/core/Sk4pxXfermode.h
+++ b/src/core/Sk4pxXfermode.h
@@ -9,11 +9,13 @@
#define Sk4pxXfermode_DEFINED
#include "Sk4px.h"
+#include "SkPMFloat.h"
// This file is possibly included into multiple .cpp files.
// Each gets its own independent instantiation by wrapping in an anonymous namespace.
namespace {
+// Most xfermodes can be done most efficiently 4 pixels at a time in 8 or 16-bit fixed point.
#define XFERMODE(Name) \
struct Name { \
static Sk4px Xfer(const Sk4px&, const Sk4px&); \
@@ -97,7 +99,48 @@ XFERMODE(Lighten) {
colors = (sda < dsa).thenElse(dstover, srcover);
return alphas.zeroColors() + colors.zeroAlphas();
}
+#undef XFERMODE
+
+// Some xfermodes use math like divide or sqrt that's best done in floats 1 pixel at a time.
+#define XFERMODE(Name) \
+ struct Name { \
+ static SkPMFloat Xfer(const SkPMFloat&, const SkPMFloat&); \
+ static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \
+ }; \
+ inline SkPMFloat Name::Xfer(const SkPMFloat& s, const SkPMFloat& d)
+
+XFERMODE(ColorDodge) {
+ auto sa = s.alphas(),
+ da = d.alphas(),
+ isa = Sk4f(1)-sa,
+ ida = Sk4f(1)-da;
+ auto srcover = s + d*isa,
+ dstover = d + s*ida,
+ otherwise = sa * Sk4f::Min(da, (d*sa)*(sa-s).approxInvert()) + s*ida + d*isa;
+
+ // Order matters here, preferring d==0 over s==sa.
+ auto colors = (d == Sk4f(0)).thenElse(dstover,
+ (s == sa).thenElse(srcover,
+ otherwise));
+ return srcover * SkPMFloat(1,0,0,0) + colors * SkPMFloat(0,1,1,1);
+}
+XFERMODE(ColorBurn) {
+ auto sa = s.alphas(),
+ da = d.alphas(),
+ isa = Sk4f(1)-sa,
+ ida = Sk4f(1)-da;
+
+ auto srcover = s + d*isa,
+ dstover = d + s*ida,
+ otherwise = sa*(da-Sk4f::Min(da, (da-d)*sa*s.approxInvert())) + s*ida + d*isa;
+
+ // Order matters here, preferring d==da over s==0.
+ auto colors = (d == da).thenElse(dstover,
+ (s == Sk4f(0)).thenElse(srcover,
+ otherwise));
+ return srcover * SkPMFloat(1,0,0,0) + colors * SkPMFloat(0,1,1,1);
+}
#undef XFERMODE
// A reasonable fallback mode for doing AA is to simply apply the transfermode first,
@@ -140,7 +183,34 @@ public:
}
private:
- SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
+ SkT4pxXfermode(const ProcCoeff& rec) : INHERITED(rec, ProcType::kMode) {}
+
+ typedef SkProcCoeffXfermode INHERITED;
+};
+
+template <typename ProcType>
+class SkTPMFloatXfermode : public SkProcCoeffXfermode {
+public:
+ static SkProcCoeffXfermode* Create(const ProcCoeff& rec) {
+ return SkNEW_ARGS(SkTPMFloatXfermode, (rec));
+ }
+
+ void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
+ for (int i = 0; i < n; i++) {
+ SkPMFloat s(src[i]),
+ d(dst[i]),
+ b(ProcType::Xfer(s,d));
+ if (aa) {
+ // We do aa in full float precision before going back down to bytes, because we can!
+ SkPMFloat a = Sk4f(aa[i]) * Sk4f(1.0f/255);
+ b = b*a + d*(Sk4f(1)-a);
+ }
+ dst[i] = b.round();
+ }
+ }
+
+private:
+ SkTPMFloatXfermode(const ProcCoeff& rec) : INHERITED(rec, ProcType::kMode) {}
typedef SkProcCoeffXfermode INHERITED;
};
@@ -171,6 +241,9 @@ static SkProcCoeffXfermode* SkCreate4pxXfermode(const ProcCoeff& rec, SkXfermode
case SkXfermode::kOverlay_Mode: return SkT4pxXfermode<Overlay>::Create(rec);
case SkXfermode::kDarken_Mode: return SkT4pxXfermode<Darken>::Create(rec);
case SkXfermode::kLighten_Mode: return SkT4pxXfermode<Lighten>::Create(rec);
+
+ case SkXfermode::kColorDodge_Mode: return SkTPMFloatXfermode<ColorDodge>::Create(rec);
+ case SkXfermode::kColorBurn_Mode: return SkTPMFloatXfermode<ColorBurn>::Create(rec);
#endif
default: break;
}
« no previous file with comments | « no previous file | src/core/SkPMFloat.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698