aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkXfermode.cpp
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2017-06-14 01:27:02 +0000
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-14 01:27:18 +0000
commitf90aa014d8639a0881b4cfb831b72eb0c8dfbbd7 (patch)
tree3b1ea4107a60b9a8a8d29e16f5da01cf8c28a15f /src/core/SkXfermode.cpp
parent847d4c5714ff4e1420ce69611cffd68487cb9422 (diff)
Revert "Revert "use pipeline for non-opt xfermodes""
This reverts commit 4f8c695736c8ae4fed2190a8e1301a4f4a979898. Reason for revert: suppression re-landed in chrome Original change's description: > Revert "use pipeline for non-opt xfermodes" > > This reverts commit e93cf97175d348ce1400762bdd8d9acabdd29766. > > Reason for revert: unblock Chrome roll > > Original change's description: > > use pipeline for non-opt xfermodes > > > > Produces slightly different results for Hue, Saturation, Color, Luminosity, > > seemingly around the aa edging. > > > > Bug: skia: > > Change-Id: I6364818c9788863e5fad6d14cad4797d073dbea3 > > Reviewed-on: https://skia-review.googlesource.com/19554 > > Reviewed-by: Mike Klein <mtklein@google.com> > > Commit-Queue: Mike Reed <reed@google.com> > > TBR=mtklein@google.com,fmalita@chromium.org,reed@google.com > > Change-Id: Ib85a51753d21ce778fa5cfedd6b7d1b5b2b87096 > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Bug: skia: > Reviewed-on: https://skia-review.googlesource.com/19745 > Reviewed-by: Mike Klein <mtklein@chromium.org> > Commit-Queue: Mike Klein <mtklein@chromium.org> TBR=mtklein@chromium.org,mtklein@google.com,fmalita@chromium.org,reed@google.com Change-Id: I1201b5abae1514edf9143927064ce060095592f4 No-Presubmit: true No-Tree-Checks: true No-Try: true Bug: skia: Reviewed-on: https://skia-review.googlesource.com/19760 Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src/core/SkXfermode.cpp')
-rw-r--r--src/core/SkXfermode.cpp696
1 files changed, 34 insertions, 662 deletions
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 0dd9e87cdf..54ac5891a3 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -6,16 +6,16 @@
*/
#include "SkBlendModePriv.h"
-#include "SkXfermode_proccoeff.h"
#include "SkColorPriv.h"
#include "SkMathPriv.h"
#include "SkOnce.h"
#include "SkOpts.h"
+#include "SkPM4f.h"
#include "SkRasterPipeline.h"
#include "SkReadBuffer.h"
#include "SkString.h"
#include "SkWriteBuffer.h"
-#include "SkPM4f.h"
+#include "SkXfermodePriv.h"
#if SK_SUPPORT_GPU
#include "GrFragmentProcessor.h"
@@ -24,668 +24,50 @@
#include "effects/GrXfermodeFragmentProcessor.h"
#endif
-#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
-
-static inline unsigned saturated_add(unsigned a, unsigned b) {
- SkASSERT(a <= 255);
- SkASSERT(b <= 255);
- unsigned sum = a + b;
- if (sum > 255) {
- sum = 255;
- }
- return sum;
-}
-
-static inline int clamp_signed_byte(int n) {
- if (n < 0) {
- n = 0;
- } else if (n > 255) {
- n = 255;
- }
- return n;
-}
-
-static inline int clamp_div255round(int prod) {
- if (prod <= 0) {
- return 0;
- } else if (prod >= 255*255) {
- return 255;
- } else {
- return SkDiv255Round(prod);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-// kClear_Mode, //!< [0, 0]
-static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
- return 0;
-}
-
-// kSrc_Mode, //!< [Sa, Sc]
-static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
- return src;
-}
-
-// kDst_Mode, //!< [Da, Dc]
-static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
- return dst;
-}
-
-// kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
-static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
-#if 0
- // this is the old, more-correct way, but it doesn't guarantee that dst==255
- // will always stay opaque
- return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
-#else
- // this is slightly faster, but more importantly guarantees that dst==255
- // will always stay opaque
- return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
-#endif
-}
-
-// kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
-static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
- // this is the reverse of srcover, just flipping src and dst
- // see srcover's comment about the 256 for opaqueness guarantees
- return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
-}
-
-// kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
-static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
- return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
-}
-
-// kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
-static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
- return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
-}
-
-// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
-static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
- return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
-}
-
-// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
-static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
- return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
-}
-
-// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
-static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
- unsigned sa = SkGetPackedA32(src);
- unsigned da = SkGetPackedA32(dst);
- unsigned isa = 255 - sa;
-
- return SkPackARGB32(da,
- SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
- SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
- SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
- SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
- SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
- SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
-}
-
-// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
-static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
- unsigned sa = SkGetPackedA32(src);
- unsigned da = SkGetPackedA32(dst);
- unsigned ida = 255 - da;
-
- return SkPackARGB32(sa,
- SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
- SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
- SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
- SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
- SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
- SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
-}
-
-// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
-static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
- unsigned sa = SkGetPackedA32(src);
- unsigned da = SkGetPackedA32(dst);
- unsigned isa = 255 - sa;
- unsigned ida = 255 - da;
-
- return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
- SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
- SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
- SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
- SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
- SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
- SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
-// kPlus_Mode
-static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
- unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
- unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
- unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
- unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
- return SkPackARGB32(a, r, g, b);
-}
-
-// kModulate_Mode
-static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
- int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
- int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
- int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
- int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
- return SkPackARGB32(a, r, g, b);
-}
-
-static inline int srcover_byte(int a, int b) {
- return a + b - SkAlphaMulAlpha(a, b);
-}
-
-// kMultiply_Mode
-// B(Cb, Cs) = Cb x Cs
-// multiply uses its own version of blendfunc_byte because sa and da are not needed
-static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
- return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
-}
-
-static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kScreen_Mode
-static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
- int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
- int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
- int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
- int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
- return SkPackARGB32(a, r, g, b);
-}
-
-// kOverlay_Mode
-static inline int overlay_byte(int sc, int dc, int sa, int da) {
- int tmp = sc * (255 - da) + dc * (255 - sa);
- int rc;
- if (2 * dc <= da) {
- rc = 2 * sc * dc;
- } else {
- rc = sa * da - 2 * (da - dc) * (sa - sc);
- }
- return clamp_div255round(rc + tmp);
-}
-static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kDarken_Mode
-static inline int darken_byte(int sc, int dc, int sa, int da) {
- int sd = sc * da;
- int ds = dc * sa;
- if (sd < ds) {
- // srcover
- return sc + dc - SkDiv255Round(ds);
- } else {
- // dstover
- return dc + sc - SkDiv255Round(sd);
- }
-}
-static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kLighten_Mode
-static inline int lighten_byte(int sc, int dc, int sa, int da) {
- int sd = sc * da;
- int ds = dc * sa;
- if (sd > ds) {
- // srcover
- return sc + dc - SkDiv255Round(ds);
- } else {
- // dstover
- return dc + sc - SkDiv255Round(sd);
- }
-}
-static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kColorDodge_Mode
-static inline int colordodge_byte(int sc, int dc, int sa, int da) {
- int diff = sa - sc;
- int rc;
- if (0 == dc) {
- return SkAlphaMulAlpha(sc, 255 - da);
- } else if (0 == diff) {
- rc = sa * da + sc * (255 - da) + dc * (255 - sa);
- } else {
- diff = dc * sa / diff;
- rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
- }
- return clamp_div255round(rc);
-}
-static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kColorBurn_Mode
-static inline int colorburn_byte(int sc, int dc, int sa, int da) {
- int rc;
- if (dc == da) {
- rc = sa * da + sc * (255 - da) + dc * (255 - sa);
- } else if (0 == sc) {
- return SkAlphaMulAlpha(dc, 255 - sa);
- } else {
- int tmp = (da - dc) * sa / sc;
- rc = sa * (da - ((da < tmp) ? da : tmp))
- + sc * (255 - da) + dc * (255 - sa);
- }
- return clamp_div255round(rc);
-}
-static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kHardLight_Mode
-static inline int hardlight_byte(int sc, int dc, int sa, int da) {
- int rc;
- if (2 * sc <= sa) {
- rc = 2 * sc * dc;
- } else {
- rc = sa * da - 2 * (da - dc) * (sa - sc);
- }
- return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
-}
-static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// returns 255 * sqrt(n/255)
-static U8CPU sqrt_unit_byte(U8CPU n) {
- return SkSqrtBits(n, 15+4);
-}
-
-// kSoftLight_Mode
-static inline int softlight_byte(int sc, int dc, int sa, int da) {
- int m = da ? dc * 256 / da : 0;
- int rc;
- if (2 * sc <= sa) {
- rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
- } else if (4 * dc <= da) {
- int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
- rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
- } else {
- int tmp = sqrt_unit_byte(m) - m;
- rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
- }
- return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
-}
-static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kDifference_Mode
-static inline int difference_byte(int sc, int dc, int sa, int da) {
- int tmp = SkMin32(sc * da, dc * sa);
- return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
-}
-static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kExclusion_Mode
-static inline int exclusion_byte(int sc, int dc, int, int) {
- // this equations is wacky, wait for SVG to confirm it
- //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
-
- // The above equation can be simplified as follows
- int r = 255*(sc + dc) - 2 * sc * dc;
- return clamp_div255round(r);
-}
-static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
- int sa = SkGetPackedA32(src);
- int da = SkGetPackedA32(dst);
- int a = srcover_byte(sa, da);
- int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
- int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
- int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
- return SkPackARGB32(a, r, g, b);
-}
-
-// The CSS compositing spec introduces the following formulas:
-// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
-// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
-// while PDF and CG uses the one from Rec. Rec. 601
-// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
-static inline int Lum(int r, int g, int b)
-{
- return SkDiv255Round(r * 77 + g * 150 + b * 28);
-}
+///////////////////////////////////////////////////////////////////////////////////////////////////
-static inline int min2(int a, int b) { return a < b ? a : b; }
-static inline int max2(int a, int b) { return a > b ? a : b; }
-#define minimum(a, b, c) min2(min2(a, b), c)
-#define maximum(a, b, c) max2(max2(a, b), c)
+class SkProcCoeffXfermode : public SkXfermode {
+public:
+ SkProcCoeffXfermode(SkBlendMode mode) : fMode(mode) {}
-static inline int Sat(int r, int g, int b) {
- return maximum(r, g, b) - minimum(r, g, b);
-}
+ void xfer32(SkPMColor dst[], const SkPMColor src[], int count,
+ const SkAlpha aa[]) const override {
+ SkASSERT(dst && src && count >= 0);
-static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
- if(*Cmax > *Cmin) {
- *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
- *Cmax = s;
- } else {
- *Cmax = 0;
- *Cmid = 0;
- }
+ bool needs_swap = (kN32_SkColorType == kBGRA_8888_SkColorType) &&
+ SkBlendMode_CaresAboutRBOrder(fMode);
- *Cmin = 0;
-}
+ SkRasterPipeline_<256> p;
-static inline void SetSat(int* r, int* g, int* b, int s) {
- if(*r <= *g) {
- if(*g <= *b) {
- setSaturationComponents(r, g, b, s);
- } else if(*r <= *b) {
- setSaturationComponents(r, b, g, s);
- } else {
- setSaturationComponents(b, r, g, s);
+ p.append(SkRasterPipeline::load_8888, &dst);
+ if (needs_swap) {
+ p.append(SkRasterPipeline::swap_rb);
+ }
+ p.append(SkRasterPipeline::move_src_dst);
+ p.append(SkRasterPipeline::load_8888, &src);
+ if (needs_swap) {
+ p.append(SkRasterPipeline::swap_rb);
}
- } else if(*r <= *b) {
- setSaturationComponents(g, r, b, s);
- } else if(*g <= *b) {
- setSaturationComponents(g, b, r, s);
- } else {
- setSaturationComponents(b, g, r, s);
- }
-}
-
-static inline void clipColor(int* r, int* g, int* b, int a) {
- int L = Lum(*r, *g, *b);
- int n = minimum(*r, *g, *b);
- int x = maximum(*r, *g, *b);
- int denom;
- if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
- *r = L + SkMulDiv(*r - L, L, denom);
- *g = L + SkMulDiv(*g - L, L, denom);
- *b = L + SkMulDiv(*b - L, L, denom);
- }
-
- if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
- int numer = a - L;
- *r = L + SkMulDiv(*r - L, numer, denom);
- *g = L + SkMulDiv(*g - L, numer, denom);
- *b = L + SkMulDiv(*b - L, numer, denom);
- }
-}
-
-static inline void SetLum(int* r, int* g, int* b, int a, int l) {
- int d = l - Lum(*r, *g, *b);
- *r += d;
- *g += d;
- *b += d;
-
- clipColor(r, g, b, a);
-}
-
-// non-separable blend modes are done in non-premultiplied alpha
-#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
- clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
-
-// kHue_Mode
-// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
-// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
-static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
- int sr = SkGetPackedR32(src);
- int sg = SkGetPackedG32(src);
- int sb = SkGetPackedB32(src);
- int sa = SkGetPackedA32(src);
-
- int dr = SkGetPackedR32(dst);
- int dg = SkGetPackedG32(dst);
- int db = SkGetPackedB32(dst);
- int da = SkGetPackedA32(dst);
- int Sr, Sg, Sb;
-
- if(sa && da) {
- Sr = sr * sa;
- Sg = sg * sa;
- Sb = sb * sa;
- SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
- SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
- } else {
- Sr = 0;
- Sg = 0;
- Sb = 0;
- }
-
- int a = srcover_byte(sa, da);
- int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
- int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
- int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kSaturation_Mode
-// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
-// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
-static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
- int sr = SkGetPackedR32(src);
- int sg = SkGetPackedG32(src);
- int sb = SkGetPackedB32(src);
- int sa = SkGetPackedA32(src);
-
- int dr = SkGetPackedR32(dst);
- int dg = SkGetPackedG32(dst);
- int db = SkGetPackedB32(dst);
- int da = SkGetPackedA32(dst);
- int Dr, Dg, Db;
-
- if(sa && da) {
- Dr = dr * sa;
- Dg = dg * sa;
- Db = db * sa;
- SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
- SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
- } else {
- Dr = 0;
- Dg = 0;
- Db = 0;
- }
-
- int a = srcover_byte(sa, da);
- int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
- int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
- int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kColor_Mode
-// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
-// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
-static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
- int sr = SkGetPackedR32(src);
- int sg = SkGetPackedG32(src);
- int sb = SkGetPackedB32(src);
- int sa = SkGetPackedA32(src);
-
- int dr = SkGetPackedR32(dst);
- int dg = SkGetPackedG32(dst);
- int db = SkGetPackedB32(dst);
- int da = SkGetPackedA32(dst);
- int Sr, Sg, Sb;
-
- if(sa && da) {
- Sr = sr * da;
- Sg = sg * da;
- Sb = sb * da;
- SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
- } else {
- Sr = 0;
- Sg = 0;
- Sb = 0;
- }
-
- int a = srcover_byte(sa, da);
- int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
- int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
- int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
- return SkPackARGB32(a, r, g, b);
-}
-
-// kLuminosity_Mode
-// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
-// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
-static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
- int sr = SkGetPackedR32(src);
- int sg = SkGetPackedG32(src);
- int sb = SkGetPackedB32(src);
- int sa = SkGetPackedA32(src);
- int dr = SkGetPackedR32(dst);
- int dg = SkGetPackedG32(dst);
- int db = SkGetPackedB32(dst);
- int da = SkGetPackedA32(dst);
- int Dr, Dg, Db;
+ SkBlendMode_AppendStagesNoClamp(fMode, &p);
+ if (aa) {
+ p.append(SkRasterPipeline::lerp_u8, &aa);
+ }
+ SkBlendMode_AppendClampIfNeeded(fMode, &p);
- if(sa && da) {
- Dr = dr * sa;
- Dg = dg * sa;
- Db = db * sa;
- SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
- } else {
- Dr = 0;
- Dg = 0;
- Db = 0;
+ if (needs_swap) {
+ p.append(SkRasterPipeline::swap_rb);
+ }
+ p.append(SkRasterPipeline::store_8888, &dst);
+ p.run(0, 0, count);
}
- int a = srcover_byte(sa, da);
- int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
- int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
- int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
- return SkPackARGB32(a, r, g, b);
-}
+private:
+ const SkBlendMode fMode;
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-const SkXfermodeProc gProcs[] = {
- clear_modeproc,
- src_modeproc,
- dst_modeproc,
- srcover_modeproc,
- dstover_modeproc,
- srcin_modeproc,
- dstin_modeproc,
- srcout_modeproc,
- dstout_modeproc,
- srcatop_modeproc,
- dstatop_modeproc,
- xor_modeproc,
-
- plus_modeproc,
- modulate_modeproc,
- screen_modeproc,
- overlay_modeproc,
- darken_modeproc,
- lighten_modeproc,
- colordodge_modeproc,
- colorburn_modeproc,
- hardlight_modeproc,
- softlight_modeproc,
- difference_modeproc,
- exclusion_modeproc,
- multiply_modeproc,
- hue_modeproc,
- saturation_modeproc,
- color_modeproc,
- luminosity_modeproc,
+ typedef SkXfermode INHERITED;
};
-///////////////////////////////////////////////////////////////////////////////
-///////////////////////////////////////////////////////////////////////////////
-
-void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
- const SkPMColor* SK_RESTRICT src, int count,
- const SkAlpha* SK_RESTRICT aa) const {
- SkASSERT(dst && src && count >= 0);
-
- SkXfermodeProc proc = fProc;
-
- if (proc) {
- if (nullptr == aa) {
- for (int i = count - 1; i >= 0; --i) {
- dst[i] = proc(src[i], dst[i]);
- }
- } else {
- for (int i = count - 1; i >= 0; --i) {
- unsigned a = aa[i];
- if (0 != a) {
- SkPMColor dstC = dst[i];
- SkPMColor C = proc(src[i], dstC);
- if (a != 0xFF) {
- C = SkFourByteInterp(C, dstC, a);
- }
- dst[i] = C;
- }
- }
- }
- }
-}
-
const char* SkBlendMode_Name(SkBlendMode mode) {
SkASSERT((unsigned) mode <= (unsigned)SkBlendMode::kLastMode);
const char* gModeStrings[] = {
@@ -712,30 +94,20 @@ sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
}
const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
- SkASSERT(SK_ARRAY_COUNT(gProcs) == COUNT_BLENDMODES);
static SkOnce once[COUNT_BLENDMODES];
static SkXfermode* cached[COUNT_BLENDMODES];
once[(int)mode]([mode] {
- SkXfermodeProc proc = gProcs[(int)mode];
if (auto xfermode = SkOpts::create_xfermode(mode)) {
cached[(int)mode] = xfermode;
} else {
- cached[(int)mode] = new SkProcCoeffXfermode(proc, mode);
+ cached[(int)mode] = new SkProcCoeffXfermode(mode);
}
});
return sk_ref_sp(cached[(int)mode]);
}
-SkXfermodeProc SkXfermode::GetProc(SkBlendMode mode) {
- SkXfermodeProc proc = nullptr;
- if ((unsigned)mode <= (unsigned)SkBlendMode::kLastMode) {
- proc = gProcs[(unsigned)mode];
- }
- return proc;
-}
-
///////////////////////////////////////////////////////////////////////////////////////////////////
bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {