aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2016-01-30 18:52:31 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-01-30 18:52:31 -0800
commit395eabeb0e72334c45324874c6e009b54634df21 (patch)
treeb6ff3f497e98db84417c3c6f6e8e2235c277101b
parentafd25f703d9bbc9cd80b03b63b30abd14db4911d (diff)
float components in xfermodes
-rw-r--r--bench/Xfer4fBench.cpp60
-rw-r--r--gm/color4f.cpp69
-rw-r--r--gm/xfer4f.cpp18
-rw-r--r--gyp/core.gypi3
-rw-r--r--include/core/SkColor.h8
-rw-r--r--include/core/SkXfermode.h17
-rw-r--r--src/core/SkBlitter.cpp18
-rw-r--r--src/core/SkBlitter_PM4f.cpp159
-rw-r--r--src/core/SkColor.cpp6
-rw-r--r--src/core/SkCoreBlitters.h30
-rw-r--r--src/core/SkPM4fPriv.h77
-rw-r--r--src/core/SkXfer4f.cpp134
-rw-r--r--src/core/SkXfer4f.h24
-rw-r--r--src/core/SkXfermode.cpp1
-rw-r--r--src/core/SkXfermode4f.cpp327
-rw-r--r--src/effects/SkColorMatrixFilter.cpp8
16 files changed, 680 insertions, 279 deletions
diff --git a/bench/Xfer4fBench.cpp b/bench/Xfer4fBench.cpp
index 2c281695ef..751f0dfca2 100644
--- a/bench/Xfer4fBench.cpp
+++ b/bench/Xfer4fBench.cpp
@@ -8,24 +8,25 @@
#include "Benchmark.h"
#include "SkString.h"
-#include "SkXfer4f.h"
+#include "SkXfermode.h"
#define INNER_LOOPS 100
// Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode.
class Xfer4fBench : public Benchmark {
public:
- Xfer4fBench(SkXfermode::Mode mode, const char name[], bool doN, uint32_t flags) : fDoN(doN) {
- fProc1 = SkPM4fXfer1ProcFactory(mode, flags);
- fProcN = SkPM4fXferNProcFactory(mode, flags);
+ Xfer4fBench(SkXfermode::Mode mode, const char name[], bool doN, uint32_t flags)
+ : fDoN(doN)
+ , fFlags(flags)
+ {
+ fProc1 = SkXfermode::GetPM4fProc1(mode, flags);
+ fProcN = SkXfermode::GetPM4fProcN(mode, flags);
fName.printf("xfer4f_%s_%c_%s_%s", name, fDoN ? 'N' : '1',
- (flags & kSrcIsOpaque_SkXfer4fFlag) ? "opaque" : "alpha",
- (flags & kDstIsSRGB_SkXfer4fFlag) ? "srgb" : "linear");
+ (flags & SkXfermode::kSrcIsOpaque_PM4fFlag) ? "opaque" : "alpha",
+ (flags & SkXfermode::kDstIsSRGB_PM4fFlag) ? "srgb" : "linear");
- SkPM4f c;
- c.fVec[0] = 1; c.fVec[1] = 1; c.fVec[2] = 1; c.fVec[3] = 1;
for (int i = 0; i < N; ++i) {
- fSrc[i] = c;
+ fSrc[i] = {{ 1, 1, 1, 1 }};
fDst[i] = 0;
}
}
@@ -36,22 +37,24 @@ protected:
const char* onGetName() override { return fName.c_str(); }
void onDraw(int loops, SkCanvas*) override {
- for (int i = 0; i < loops; ++i) {
- for (int j = 0; j < INNER_LOOPS; ++j) {
- if (fDoN) {
- fProcN(fDst, fSrc, N);
- } else {
- fProc1(fDst, fSrc[0], N);
- }
+ const SkXfermode::PM4fState state{ nullptr, fFlags };
+ const uint8_t* aa = nullptr;
+
+ for (int i = 0; i < loops * INNER_LOOPS; ++i) {
+ if (fDoN) {
+ fProcN(state, fDst, fSrc, N, aa);
+ } else {
+ fProc1(state, fDst, fSrc[0], N, aa);
}
}
}
private:
SkString fName;
- SkPM4fXfer1Proc fProc1;
- SkPM4fXferNProc fProcN;
+ SkXfermode::PM4fProc1 fProc1;
+ SkXfermode::PM4fProcN fProcN;
bool fDoN;
+ uint32_t fFlags;
enum {
N = 1000,
@@ -62,12 +65,17 @@ private:
typedef Benchmark INHERITED;
};
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, kDstIsSRGB_SkXfer4fFlag); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, 0); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, kDstIsSRGB_SkXfer4fFlag | kSrcIsOpaque_SkXfer4fFlag); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, kSrcIsOpaque_SkXfer4fFlag); )
+#define F00 0
+#define F01 (SkXfermode::kSrcIsOpaque_PM4fFlag)
+#define F10 (SkXfermode::kDstIsSRGB_PM4fFlag)
+#define F11 (SkXfermode::kSrcIsOpaque_PM4fFlag | SkXfermode::kDstIsSRGB_PM4fFlag)
+
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F10); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F00); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F11); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F01); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, kDstIsSRGB_SkXfer4fFlag); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, 0); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, kDstIsSRGB_SkXfer4fFlag | kSrcIsOpaque_SkXfer4fFlag); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, kSrcIsOpaque_SkXfer4fFlag); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F10); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F00); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F11); )
+DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F01); )
diff --git a/gm/color4f.cpp b/gm/color4f.cpp
new file mode 100644
index 0000000000..98ce0824cc
--- /dev/null
+++ b/gm/color4f.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+#include "SkSurface.h"
+
+#include "SkColorMatrixFilter.h"
+#include "SkGradientShader.h"
+
+static SkShader* make_opaque_color() {
+ return SkShader::CreateColorShader(0xFFFF0000);
+}
+
+static SkShader* make_alpha_color() {
+ return SkShader::CreateColorShader(0x80FF0000);
+}
+
+static SkColorFilter* make_cf_null() {
+ return nullptr;
+}
+
+static SkColorFilter* make_cf0() {
+ SkColorMatrix cm;
+ cm.setSaturation(0.75f);
+ return SkColorMatrixFilter::Create(cm);
+}
+
+static void draw_into_canvas(SkCanvas* canvas) {
+ const SkRect r = SkRect::MakeWH(100, 100);
+ SkShader* (*shaders[])() { make_opaque_color, make_alpha_color };
+ SkColorFilter* (*filters[])() { make_cf_null, make_cf0 };
+
+ SkPaint paint;
+ for (auto shProc : shaders) {
+ paint.setShader(shProc())->unref();
+ for (auto cfProc : filters) {
+ SkSafeUnref(paint.setColorFilter(cfProc()));
+ canvas->drawRect(r, paint);
+ canvas->translate(120, 0);
+ }
+ }
+}
+
+DEF_SIMPLE_GM(color4f, canvas, 510, 250) {
+ canvas->translate(20, 20);
+
+ SkPaint bg;
+ // need the target to be opaque, so we can draw it to the screen
+ // even if it holds sRGB values.
+ bg.setColor(0xFFFFFFFF);
+
+ SkColorProfileType const profiles[] { kLinear_SkColorProfileType, kSRGB_SkColorProfileType };
+ for (auto profile : profiles) {
+ const SkImageInfo info = SkImageInfo::Make(500, 100, kN32_SkColorType, kPremul_SkAlphaType,
+ profile);
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRaster(info));
+ surface->getCanvas()->drawPaint(bg);
+ draw_into_canvas(surface->getCanvas());
+ surface->draw(canvas, 0, 0, nullptr);
+ canvas->translate(0, 120);
+ }
+}
diff --git a/gm/xfer4f.cpp b/gm/xfer4f.cpp
index 1951fdbde2..b74b6e0685 100644
--- a/gm/xfer4f.cpp
+++ b/gm/xfer4f.cpp
@@ -8,7 +8,7 @@
#include "gm.h"
#include "SkCanvas.h"
#include "SkImageInfo.h"
-#include "SkXfer4f.h"
+#include "SkXfermode.h"
static void draw_rect(SkCanvas* canvas, const SkRect& r, SkColor c, SkColorProfileType profile) {
const SkIRect ir = r.round();
@@ -21,26 +21,28 @@ static void draw_rect(SkCanvas* canvas, const SkRect& r, SkColor c, SkColorProfi
uint32_t flags = 0;
if (SkColorGetA(c) == 0xFF) {
- flags |= kSrcIsOpaque_SkXfer4fFlag;
+ flags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
}
if (kSRGB_SkColorProfileType == profile) {
- flags |= kDstIsSRGB_SkXfer4fFlag;
+ flags |= SkXfermode::kDstIsSRGB_PM4fFlag;
}
- const SkPM4f src = SkPM4f::FromPMColor(SkPreMultiplyColor(c));
- auto proc1 = SkPM4fXfer1ProcFactory(SkXfermode::kSrcOver_Mode, flags);
+ const SkXfermode::PM4fState state { nullptr, flags };
+
+ const SkPM4f src = SkColor4f::FromColor(c).premul();
+ auto proc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, flags);
for (int y = 0; y < ir.height()/2; ++y) {
- proc1(pm.writable_addr32(0, y), src, ir.width());
+ proc1(state, pm.writable_addr32(0, y), src, ir.width(), nullptr);
}
SkPM4f srcRow[1000];
for (int i = 0; i < ir.width(); ++i) {
srcRow[i] = src;
}
- auto procN = SkPM4fXferNProcFactory(SkXfermode::kSrcOver_Mode, flags);
+ auto procN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, flags);
// +1 to skip a row, so we can see the boundary between proc1 and procN
for (int y = ir.height()/2 + 1; y < ir.height(); ++y) {
- procN(pm.writable_addr32(0, y), srcRow, ir.width());
+ procN(state, pm.writable_addr32(0, y), srcRow, ir.width(), nullptr);
}
canvas->drawBitmap(bm, r.left(), r.top(), nullptr);
diff --git a/gyp/core.gypi b/gyp/core.gypi
index b5405a40ca..b80f43a72f 100644
--- a/gyp/core.gypi
+++ b/gyp/core.gypi
@@ -58,6 +58,7 @@
'<(skia_src_path)/core/SkBlitter.cpp',
'<(skia_src_path)/core/SkBlitter_A8.cpp',
'<(skia_src_path)/core/SkBlitter_ARGB32.cpp',
+ '<(skia_src_path)/core/SkBlitter_PM4f.cpp',
'<(skia_src_path)/core/SkBlitter_RGB16.cpp',
'<(skia_src_path)/core/SkBlitter_Sprite.cpp',
'<(skia_src_path)/core/SkBuffer.cpp',
@@ -293,8 +294,8 @@
'<(skia_src_path)/core/SkVertState.cpp',
'<(skia_src_path)/core/SkWriteBuffer.cpp',
'<(skia_src_path)/core/SkWriter32.cpp',
- '<(skia_src_path)/core/SkXfer4f.cpp',
'<(skia_src_path)/core/SkXfermode.cpp',
+ '<(skia_src_path)/core/SkXfermode4f.cpp',
'<(skia_src_path)/core/SkXfermode_proccoeff.h',
'<(skia_src_path)/core/SkXfermodeInterpretation.cpp',
'<(skia_src_path)/core/SkXfermodeInterpretation.h',
diff --git a/include/core/SkColor.h b/include/core/SkColor.h
index 099771af98..461a53877d 100644
--- a/include/core/SkColor.h
+++ b/include/core/SkColor.h
@@ -172,11 +172,15 @@ struct SkPM4f {
};
float fVec[4];
- float a() const { return fVec[3]; }
+ float a() const { return fVec[A]; }
static SkPM4f FromPMColor(SkPMColor);
- bool isUnit() const;
+#ifdef SK_DEBUG
+ void assertIsUnit() const;
+#else
+ void assertIsUnit() const {}
+#endif
};
/*
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 261f580ea8..890a0b97fd 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -229,6 +229,23 @@ public:
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
+ enum PM4fFlags {
+ kSrcIsOpaque_PM4fFlag = 1 << 0,
+ kDstIsSRGB_PM4fFlag = 1 << 1,
+ };
+ struct PM4fState {
+ const SkXfermode* fXfer;
+ uint32_t fFlags;
+ };
+ typedef void (*PM4fProc1)(const PM4fState&, uint32_t dst[], const SkPM4f& src,
+ int count, const SkAlpha coverage[]);
+ typedef void (*PM4fProcN)(const PM4fState&, uint32_t dst[], const SkPM4f src[],
+ int count, const SkAlpha coverage[]);
+ static PM4fProc1 GetPM4fProc1(Mode, uint32_t flags);
+ static PM4fProcN GetPM4fProcN(Mode, uint32_t flags);
+ virtual PM4fProc1 getPM4fProc1(uint32_t flags) const;
+ virtual PM4fProcN getPM4fProcN(uint32_t flags) const;
+
protected:
SkXfermode() {}
/** The default implementation of xfer32/xfer16/xferA8 in turn call this
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index b73be40a45..eec31525a6 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -19,6 +19,15 @@
#include "SkXfermode.h"
#include "SkXfermodeInterpretation.h"
+// define this for testing srgb blits
+//#define SK_SUPPORT_SRGB_RASTER
+
+#ifdef SK_SUPPORT_SRGB_RASTER
+ #define ALLOW_SRGB true
+#else
+ #define ALLOW_SRGB false
+#endif
+
SkBlitter::~SkBlitter() {}
bool SkBlitter::isNullBlitter() const { return false; }
@@ -905,8 +914,13 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device,
case kN32_SkColorType:
if (shader) {
- blitter = allocator->createT<SkARGB32_Shader_Blitter>(
- device, *paint, shaderContext);
+ if (shaderContext->supports4f() && ALLOW_SRGB) {
+ blitter = allocator->createT<SkARGB32_Shader4f_Blitter>(
+ device, *paint, shaderContext);
+ } else {
+ blitter = allocator->createT<SkARGB32_Shader_Blitter>(
+ device, *paint, shaderContext);
+ }
} else if (paint->getColor() == SK_ColorBLACK) {
blitter = allocator->createT<SkARGB32_Black_Blitter>(device, *paint);
} else if (paint->getAlpha() == 0xFF) {
diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp
new file mode 100644
index 0000000000..bd8ae493da
--- /dev/null
+++ b/src/core/SkBlitter_PM4f.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCoreBlitters.h"
+#include "SkColorPriv.h"
+#include "SkShader.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+#include "SkBlitMask.h"
+
+//////////////////////////////////////////////////////////////////////////////////////
+
+SkARGB32_Shader4f_Blitter::SkARGB32_Shader4f_Blitter(const SkPixmap& device,
+ const SkPaint& paint, SkShader::Context* shaderContext)
+ : INHERITED(device, paint, shaderContext)
+{
+ const uint32_t shaderFlags = shaderContext->getFlags();
+
+ SkASSERT(shaderFlags & SkShader::kSupports4f_Flag);
+
+ fBuffer = (SkPM4f*)sk_malloc_throw(device.width() * (sizeof(SkPM4f)));
+
+ fState.fXfer = SkSafeRef(paint.getXfermode());
+ fState.fFlags = 0;
+ if (shaderFlags & SkShader::kOpaqueAlpha_Flag) {
+ fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
+ }
+ if (device.info().isSRGB()) {
+ fState.fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag;
+ }
+ if (fState.fXfer) {
+ fProc1 = fState.fXfer->getPM4fProc1(fState.fFlags);
+ fProcN = fState.fXfer->getPM4fProcN(fState.fFlags);
+ } else {
+ fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fState.fFlags);
+ fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fState.fFlags);
+ }
+
+ fConstInY = SkToBool(shaderFlags & SkShader::kConstInY32_Flag);
+}
+
+SkARGB32_Shader4f_Blitter::~SkARGB32_Shader4f_Blitter() {
+ SkSafeUnref(fState.fXfer);
+ sk_free(fBuffer);
+}
+
+void SkARGB32_Shader4f_Blitter::blitH(int x, int y, int width) {
+ SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
+
+ uint32_t* device = fDevice.writable_addr32(x, y);
+ fShaderContext->shadeSpan4f(x, y, fBuffer, width);
+ fProcN(fState, device, fBuffer, width, nullptr);
+}
+
+void SkARGB32_Shader4f_Blitter::blitRect(int x, int y, int width, int height) {
+ SkASSERT(x >= 0 && y >= 0 &&
+ x + width <= fDevice.width() && y + height <= fDevice.height());
+
+ uint32_t* device = fDevice.writable_addr32(x, y);
+ size_t deviceRB = fDevice.rowBytes();
+
+ if (fConstInY) {
+ fShaderContext->shadeSpan4f(x, y, fBuffer, width);
+ do {
+ fProcN(fState, device, fBuffer, width, nullptr);
+ y += 1;
+ device = (uint32_t*)((char*)device + deviceRB);
+ } while (--height > 0);
+ } else {
+ do {
+ fShaderContext->shadeSpan4f(x, y, fBuffer, width);
+ fProcN(fState, device, fBuffer, width, nullptr);
+ y += 1;
+ device = (uint32_t*)((char*)device + deviceRB);
+ } while (--height > 0);
+ }
+}
+
+void SkARGB32_Shader4f_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
+ const int16_t runs[]) {
+ uint32_t* device = fDevice.writable_addr32(x, y);
+
+ for (;;) {
+ int count = *runs;
+ if (count <= 0) {
+ break;
+ }
+ int aa = *antialias;
+ if (aa) {
+ fShaderContext->shadeSpan4f(x, y, fBuffer, count);
+ if (aa == 255) {
+ fProcN(fState, device, fBuffer, count, nullptr);
+ } else {
+ // count is almost always 1
+ for (int i = count - 1; i >= 0; --i) {
+ fProcN(fState, &device[i], &fBuffer[i], 1, antialias);
+ }
+ }
+ }
+ device += count;
+ runs += count;
+ antialias += count;
+ x += count;
+ }
+}
+
+void SkARGB32_Shader4f_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) {
+ // we only handle kA8
+ if (SkMask::kA8_Format != mask.fFormat) {
+ this->INHERITED::blitMask(mask, clip);
+ return;
+ }
+
+ SkASSERT(mask.fBounds.contains(clip));
+
+ const int x = clip.fLeft;
+ const int width = clip.width();
+ int y = clip.fTop;
+ int height = clip.height();
+
+ char* dstRow = (char*)fDevice.writable_addr32(x, y);
+ const size_t dstRB = fDevice.rowBytes();
+ const uint8_t* maskRow = (const uint8_t*)mask.getAddr(x, y);
+ const size_t maskRB = mask.fRowBytes;
+
+ do {
+ fShaderContext->shadeSpan4f(x, y, fBuffer, width);
+ fProcN(fState, reinterpret_cast<SkPMColor*>(dstRow), fBuffer, width, maskRow);
+ dstRow += dstRB;
+ maskRow += maskRB;
+ y += 1;
+ } while (--height > 0);
+}
+
+void SkARGB32_Shader4f_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
+ SkASSERT(x >= 0 && y >= 0 && y + height <= fDevice.height());
+
+ uint32_t* device = fDevice.writable_addr32(x, y);
+ size_t deviceRB = fDevice.rowBytes();
+
+ if (fConstInY) {
+ fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
+ do {
+ fProcN(fState, device, fBuffer, 1, &alpha);
+ device = (uint32_t*)((char*)device + deviceRB);
+ } while (--height > 0);
+ } else {
+ do {
+ fShaderContext->shadeSpan4f(x, y, fBuffer, 1);
+ fProcN(fState, device, fBuffer, 1, &alpha);
+ y += 1;
+ device = (uint32_t*)((char*)device + deviceRB);
+ } while (--height > 0);
+ }
+}
diff --git a/src/core/SkColor.cpp b/src/core/SkColor.cpp
index 9deac7a197..cf6e0b2e9f 100644
--- a/src/core/SkColor.cpp
+++ b/src/core/SkColor.cpp
@@ -142,7 +142,9 @@ SkPM4f SkColor4f::premul() const {
return pm4;
}
-bool SkPM4f::isUnit() const {
+#ifdef SK_DEBUG
+void SkPM4f::assertIsUnit() const {
auto c4 = Sk4f::Load(fVec);
- return (c4 >= Sk4f(0)).allTrue() && (c4 <= Sk4f(1)).allTrue();
+ SkASSERT((c4 >= Sk4f(0)).allTrue() && (c4 <= Sk4f(1)).allTrue());
}
+#endif
diff --git a/src/core/SkCoreBlitters.h b/src/core/SkCoreBlitters.h
index b327039682..d2559f565b 100644
--- a/src/core/SkCoreBlitters.h
+++ b/src/core/SkCoreBlitters.h
@@ -170,7 +170,7 @@ public:
void blitRect(int x, int y, int width, int height) override;
void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) override;
void blitMask(const SkMask&, const SkIRect&) override;
-
+
private:
SkXfermode* fXfermode;
SkPMColor* fBuffer;
@@ -178,13 +178,37 @@ private:
SkBlitRow::Proc32 fProc32Blend;
bool fShadeDirectlyIntoDevice;
bool fConstInY;
-
+
// illegal
SkARGB32_Shader_Blitter& operator=(const SkARGB32_Shader_Blitter&);
-
+
typedef SkShaderBlitter INHERITED;
};
+class SkARGB32_Shader4f_Blitter : public SkARGB32_Shader_Blitter {
+public:
+ SkARGB32_Shader4f_Blitter(const SkPixmap& device, const SkPaint& paint,
+ SkShader::Context* shaderContext);
+ virtual ~SkARGB32_Shader4f_Blitter();
+ void blitH(int x, int y, int width) override;
+ void blitV(int x, int y, int height, SkAlpha alpha) override;
+ void blitRect(int x, int y, int width, int height) override;
+ void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) override;
+ void blitMask(const SkMask&, const SkIRect&) override;
+
+private:
+ SkXfermode::PM4fState fState;
+ SkXfermode::PM4fProc1 fProc1;
+ SkXfermode::PM4fProcN fProcN;
+ SkPM4f* fBuffer;
+ bool fConstInY;
+
+ // illegal
+ SkARGB32_Shader4f_Blitter& operator=(const SkARGB32_Shader4f_Blitter&);
+
+ typedef SkARGB32_Shader_Blitter INHERITED;
+};
+
///////////////////////////////////////////////////////////////////////////////
/* These return the correct subclass of blitter for their device config.
diff --git a/src/core/SkPM4fPriv.h b/src/core/SkPM4fPriv.h
index a4cec5c449..81aff7013c 100644
--- a/src/core/SkPM4fPriv.h
+++ b/src/core/SkPM4fPriv.h
@@ -27,12 +27,12 @@ static inline Sk4f to_4f(uint32_t b4) {
return SkNx_cast<float>(Sk4b::Load((const uint8_t*)&b4));
}
-static inline Sk4f s2l(const Sk4f& s4) {
+static inline Sk4f srgb_to_linear(const Sk4f& s4) {
return set_alpha(s4 * s4, get_alpha(s4));
}
-static inline Sk4f l2s(const Sk4f& l4) {
- return set_alpha(l4.rsqrt1() * l4, get_alpha(l4));
+static inline Sk4f linear_to_srgb(const Sk4f& l4) {
+ return set_alpha(l4.sqrt(), get_alpha(l4));
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -42,7 +42,7 @@ static inline Sk4f Sk4f_fromL32(uint32_t src) {
}
static inline Sk4f Sk4f_fromS32(uint32_t src) {
- return s2l(to_4f(src) * Sk4f(1.0f/255));
+ return srgb_to_linear(to_4f(src) * Sk4f(1.0f/255));
}
static inline uint32_t Sk4f_toL32(const Sk4f& x4) {
@@ -50,72 +50,5 @@ static inline uint32_t Sk4f_toL32(const Sk4f& x4) {
}
static inline uint32_t Sk4f_toS32(const Sk4f& x4) {
- return to_4b(l2s(x4) * Sk4f(255) + Sk4f(0.5f));
+ return to_4b(linear_to_srgb(x4) * Sk4f(255) + Sk4f(0.5f));
}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-static Sk4f unit_to_l255_round(const SkPM4f& pm4) {
- return Sk4f::Load(pm4.fVec) * Sk4f(255) + Sk4f(0.5f);
-}
-
-static Sk4f unit_to_s255_round(const SkPM4f& pm4) {
- return l2s(Sk4f::Load(pm4.fVec)) * Sk4f(255) + Sk4f(0.5f);
-}
-
-static inline void SkPM4f_l32_src_mode(SkPMColor dst[], const SkPM4f src[], int count) {
- for (int i = 0; i < (count >> 2); ++i) {
- SkASSERT(src[0].isUnit());
- SkASSERT(src[1].isUnit());
- SkASSERT(src[2].isUnit());
- SkASSERT(src[3].isUnit());
- Sk4f_ToBytes((uint8_t*)dst,
- unit_to_l255_round(src[0]), unit_to_l255_round(src[1]),
- unit_to_l255_round(src[2]), unit_to_l255_round(src[3]));
- src += 4;
- dst += 4;
- }
- count &= 3;
- for (int i = 0; i < count; ++i) {
- SkASSERT(src[i].isUnit());
- SkNx_cast<uint8_t>(unit_to_l255_round(src[i])).store((uint8_t*)&dst[i]);
- }
-}
-
-static inline void SkPM4f_l32_srcover_mode(SkPMColor dst[], const SkPM4f src[], int count) {
- for (int i = 0; i < count; ++i) {
- SkASSERT(src[i].isUnit());
- Sk4f s4 = Sk4f::Load(src[i].fVec);
- Sk4f d4 = Sk4f_fromL32(dst[i]);
- dst[i] = Sk4f_toL32(s4 + d4 * Sk4f(1 - get_alpha(s4)));
- }
-}
-
-static inline void SkPM4f_s32_src_mode(SkPMColor dst[], const SkPM4f src[], int count) {
- for (int i = 0; i < (count >> 2); ++i) {
- SkASSERT(src[0].isUnit());
- SkASSERT(src[1].isUnit());
- SkASSERT(src[2].isUnit());
- SkASSERT(src[3].isUnit());
- Sk4f_ToBytes((uint8_t*)dst,
- unit_to_s255_round(src[0]), unit_to_s255_round(src[1]),
- unit_to_s255_round(src[2]), unit_to_s255_round(src[3]));
- src += 4;
- dst += 4;
- }
- count &= 3;
- for (int i = 0; i < count; ++i) {
- SkASSERT(src[i].isUnit());
- SkNx_cast<uint8_t>(unit_to_s255_round(src[i])).store((uint8_t*)&dst[i]);
- }
-}
-
-static inline void SkPM4f_s32_srcover_mode(SkPMColor dst[], const SkPM4f src[], int count) {
- for (int i = 0; i < count; ++i) {
- SkASSERT(src[i].isUnit());
- Sk4f s4 = Sk4f::Load(src[i].fVec);
- Sk4f d4 = Sk4f_fromS32(dst[i]);
- dst[i] = Sk4f_toS32(s4 + d4 * Sk4f(1 - get_alpha(s4)));
- }
-}
-
diff --git a/src/core/SkXfer4f.cpp b/src/core/SkXfer4f.cpp
deleted file mode 100644
index b177e49b18..0000000000
--- a/src/core/SkXfer4f.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "SkXfer4f.h"
-#include "SkPM4fPriv.h"
-#include "SkUtils.h"
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-void CLEAR_pm41p(uint32_t dst[], const SkPM4f& src, int count) {
- sk_bzero(dst, count * sizeof(uint32_t));
-}
-
-void CLEAR_pm4np(uint32_t dst[], const SkPM4f src[], int count) {
- sk_bzero(dst, count * sizeof(uint32_t));
-}
-
-//////////
-
-template <bool isSRGB> void SRC_pm41p(uint32_t dst[], const SkPM4f& src, int count) {
- uint32_t res;
- if (isSRGB) {
- res = Sk4f_toS32(Sk4f::Load(src.fVec));
- } else {
- res = Sk4f_toL32(Sk4f::Load(src.fVec));
- }
- sk_memset32(dst, res, count);
-}
-
-template <bool isSRGB> void SRC_pm4np(uint32_t dst[], const SkPM4f src[], int count) {
- if (isSRGB) {
- SkPM4f_s32_src_mode(dst, src, count);
- } else {
- SkPM4f_l32_src_mode(dst, src, count);
- }
-}
-
-//////////
-
-void DST_pm41p(uint32_t dst[], const SkPM4f& src, int count) {}
-void DST_pm4np(uint32_t dst[], const SkPM4f src[], int count) {}
-
-//////////
-
-template <bool isSRGB> void SRCOVER_pm41p(uint32_t dst[], const SkPM4f& src, int count) {
- SkASSERT(src.isUnit());
- Sk4f s4 = Sk4f::Load(src.fVec);
- Sk4f scale(1 - s4.kth<SkPM4f::A>());
-
- if (!isSRGB) {
- s4 = s4 * Sk4f(255);
- }
-
- for (int i = 0; i < count; ++i) {
- if (isSRGB) {
- Sk4f d4 = Sk4f_fromS32(dst[i]);
- dst[i] = Sk4f_toS32(s4 + d4 * scale);
- } else {
- Sk4f d4 = to_4f(dst[i]);
- dst[i] = to_4b(s4 + d4 * scale + Sk4f(0.5f));
- }
- }
-}
-
-template <bool isSRGB> void SRCOVER_pm4np(uint32_t dst[], const SkPM4f src[], int count) {
- if (isSRGB) {
- SkPM4f_s32_srcover_mode(dst, src, count);
- } else {
- SkPM4f_l32_srcover_mode(dst, src, count);
- }
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-struct Pair {
- SkPM4fXfer1Proc fProc1;
- SkPM4fXferNProc fProcN;
-};
-
-const Pair gClearPairs[] = {
- { CLEAR_pm41p, CLEAR_pm4np },
- { CLEAR_pm41p, CLEAR_pm4np },
- { CLEAR_pm41p, CLEAR_pm4np },
- { CLEAR_pm41p, CLEAR_pm4np },
-};
-
-const Pair gSrcPairs[] = {
- { SRC_pm41p<false>, SRC_pm4np<false> }, // linear [alpha ignored]
- { SRC_pm41p<false>, SRC_pm4np<false> }, // linear [opaque ignored]
- { SRC_pm41p<true>, SRC_pm4np<true> }, // srgb [alpha ignored]
- { SRC_pm41p<true>, SRC_pm4np<true> }, // srgb [opaque ignored]
-};
-
-const Pair gDstPairs[] = {
- { DST_pm41p, DST_pm4np },
- { DST_pm41p, DST_pm4np },
- { DST_pm41p, DST_pm4np },
- { DST_pm41p, DST_pm4np },
-};
-
-const Pair gSrcOverPairs[] = {
- { SRCOVER_pm41p<false>, SRCOVER_pm4np<false> }, // linear alpha
- { SRC_pm41p<false>, SRC_pm4np<false> }, // linear opaque
- { SRCOVER_pm41p<true>, SRCOVER_pm4np<true> }, // srgb alpha
- { SRC_pm41p<true>, SRC_pm4np<true> }, // srgb opaque
-};
-
-static const Pair* find_pair(SkXfermode::Mode mode, uint32_t flags) {
- SkASSERT(0 == (flags & ~3));
- const Pair* pairs = nullptr;
-
- switch (mode) {
- case SkXfermode::kClear_Mode: pairs = gClearPairs;
- case SkXfermode::kSrc_Mode: pairs = gSrcPairs; break;
- case SkXfermode::kDst_Mode: pairs = gDstPairs;
- case SkXfermode::kSrcOver_Mode: pairs = gSrcOverPairs; break;
- default: return nullptr;
- }
- return &pairs[flags & 3];
-}
-
-SkPM4fXfer1Proc SkPM4fXfer1ProcFactory(SkXfermode::Mode mode, uint32_t flags) {
- const Pair* pair = find_pair(mode, flags);
- return pair ? pair->fProc1 : nullptr;
-}
-
-SkPM4fXferNProc SkPM4fXferNProcFactory(SkXfermode::Mode mode, uint32_t flags) {
- const Pair* pair = find_pair(mode, flags);
- return pair ? pair->fProcN : nullptr;
-}
diff --git a/src/core/SkXfer4f.h b/src/core/SkXfer4f.h
deleted file mode 100644
index fd6657f1c2..0000000000
--- a/src/core/SkXfer4f.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef SkXfermodePriv_DEFINED
-#define SkXfermodePriv_DEFINED
-
-#include "SkXfermode.h"
-
-enum SkXfef4fFlags {
- kSrcIsOpaque_SkXfer4fFlag = 1 << 0,
- kDstIsSRGB_SkXfer4fFlag = 1 << 1,
-};
-
-typedef void (*SkPM4fXfer1Proc)(uint32_t dst[], const SkPM4f& src, int count);
-typedef void (*SkPM4fXferNProc)(uint32_t dst[], const SkPM4f src[], int count);
-
-SkPM4fXfer1Proc SkPM4fXfer1ProcFactory(SkXfermode::Mode, uint32_t flags);
-SkPM4fXferNProc SkPM4fXferNProcFactory(SkXfermode::Mode, uint32_t flags);
-
-#endif
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index c3a40dc45d..f6d83fae29 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -1,4 +1,3 @@
-
/*
* Copyright 2006 The Android Open Source Project
*
diff --git a/src/core/SkXfermode4f.cpp b/src/core/SkXfermode4f.cpp
new file mode 100644
index 0000000000..0485a5e6ed
--- /dev/null
+++ b/src/core/SkXfermode4f.cpp
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkPM4fPriv.h"
+#include "SkUtils.h"
+#include "SkXfermode.h"
+
+struct XferProcPair {
+ SkXfermode::PM4fProc1 fP1;
+ SkXfermode::PM4fProcN fPN;
+};
+
+enum DstType {
+ kLinear_Dst,
+ kSRGB_Dst,
+};
+
+static Sk4f scale_by_coverage(const Sk4f& x4, uint8_t coverage) {
+ return x4 * Sk4f(coverage * (1/255.0f));
+}
+
+static Sk4f lerp(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) {
+ return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f));
+}
+
+template <DstType D> Sk4f load_dst(SkPMColor dstC) {
+ return (D == kSRGB_Dst) ? Sk4f_fromS32(dstC) : Sk4f_fromL32(dstC);
+}
+
+template <DstType D> uint32_t store_dst(const Sk4f& x4) {
+ return (D == kSRGB_Dst) ? Sk4f_toS32(x4) : Sk4f_toL32(x4);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static Sk4f scale_255_round(const SkPM4f& pm4) {
+ return Sk4f::Load(pm4.fVec) * Sk4f(255) + Sk4f(0.5f);
+}
+
+static void pm4f_to_linear_32(SkPMColor dst[], const SkPM4f src[], int count) {
+ while (count >= 4) {
+ src[0].assertIsUnit();
+ src[1].assertIsUnit();
+ src[2].assertIsUnit();
+ src[3].assertIsUnit();
+ Sk4f_ToBytes((uint8_t*)dst,
+ scale_255_round(src[0]), scale_255_round(src[1]),
+ scale_255_round(src[2]), scale_255_round(src[3]));
+ src += 4;
+ dst += 4;
+ count -= 4;
+ }
+ for (int i = 0; i < count; ++i) {
+ src[i].assertIsUnit();
+ SkNx_cast<uint8_t>(scale_255_round(src[i])).store((uint8_t*)&dst[i]);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// These are our fallback impl for the SkPM4f procs...
+//
+// They just convert the src color(s) into a linear SkPMColor value(s), and then
+// call the existing virtual xfer32. This clear throws away data (converting floats to bytes)
+// in the src, and ignores the sRGB flag, but should draw about the same as if the caller
+// had passed in SkPMColor values directly.
+//
+
+void xfer_pm4_proc_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f& src,
+ int count, const SkAlpha aa[]) {
+ uint32_t pm;
+ pm4f_to_linear_32(&pm, &src, 1);
+
+ const int N = 128;
+ SkPMColor tmp[N];
+ sk_memset32(tmp, pm, SkMin32(count, N));
+ while (count > 0) {
+ const int n = SkMin32(count, N);
+ state.fXfer->xfer32(dst, tmp, n, aa);
+
+ dst += n;
+ if (aa) {
+ aa += n;
+ }
+ count -= n;
+ }
+}
+
+void xfer_pm4_proc_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f src[],
+ int count, const SkAlpha aa[]) {
+ const int N = 128;
+ SkPMColor tmp[N];
+ while (count > 0) {
+ const int n = SkMin32(count, N);
+ pm4f_to_linear_32(tmp, src, n);
+ state.fXfer->xfer32(dst, tmp, n, aa);
+
+ src += n;
+ dst += n;
+ if (aa) {
+ aa += n;
+ }
+ count -= n;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void clear_linear_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[],
+ int count, const SkAlpha aa[]) {
+ if (aa) {
+ for (int i = 0; i < count; ++i) {
+ unsigned a = aa[i];
+ if (a) {
+ SkPMColor dstC = dst[i];
+ SkPMColor C = 0;
+ if (0xFF != a) {
+ C = SkFourByteInterp(C, dstC, a);
+ }
+ dst[i] = C;
+ }
+ }
+ } else {
+ sk_bzero(dst, count * sizeof(SkPMColor));
+ }
+}
+
+static void clear_linear_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f&,
+ int count, const SkAlpha coverage[]) {
+ clear_linear_n(state, dst, nullptr, count, coverage);
+}
+
+static void clear_srgb_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[],
+ int count, const SkAlpha aa[]) {
+ if (aa) {
+ for (int i = 0; i < count; ++i) {
+ unsigned a = aa[i];
+ if (a) {
+ Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - a) * (1/255.0f));
+ dst[i] = Sk4f_toS32(d);
+ }
+ }
+ } else {
+ sk_bzero(dst, count * sizeof(SkPMColor));
+ }
+}
+
+static void clear_srgb_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f&,
+ int count, const SkAlpha coverage[]) {
+ clear_srgb_n(state, dst, nullptr, count, coverage);
+}
+
+const XferProcPair gProcs_Clear[] = {
+ { clear_linear_1, clear_linear_n }, // linear [alpha]
+ { clear_linear_1, clear_linear_n }, // linear [opaque]
+ { clear_srgb_1, clear_srgb_n }, // srgb [alpha]
+ { clear_srgb_1, clear_srgb_n }, // srgb [opaque]
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DstType D> void src_n(const SkXfermode::PM4fState& state, uint32_t dst[],
+ const SkPM4f src[], int count, const SkAlpha aa[]) {
+ for (int i = 0; i < count; ++i) {
+ unsigned a = 0xFF;
+ if (aa) {
+ a = aa[i];
+ if (0 == a) {
+ continue;
+ }
+ }
+ Sk4f r4 = Sk4f::Load(src[i].fVec); // src always overrides dst
+ if (a != 0xFF) {
+ Sk4f d4 = load_dst<D>(dst[i]);
+ r4 = lerp(r4, d4, a);
+ }
+ dst[i] = store_dst<D>(r4);
+ }
+}
+
+template <DstType D> void src_1(const SkXfermode::PM4fState& state, uint32_t dst[],
+ const SkPM4f& src, int count, const SkAlpha aa[]) {
+ const Sk4f r4 = Sk4f::Load(src.fVec); // src always overrides dst
+ const uint32_t r32 = store_dst<D>(r4);
+
+ if (aa) {
+ for (int i = 0; i < count; ++i) {
+ unsigned a = aa[i];
+ if (0 == a) {
+ continue;
+ }
+ if (a != 0xFF) {
+ Sk4f d4 = load_dst<D>(dst[i]);
+ dst[i] = store_dst<D>(lerp(r4, d4, a));
+ } else {
+ dst[i] = r32;
+ }
+ }
+ } else {
+ sk_memset32(dst, r32, count);
+ }
+}
+
+const XferProcPair gProcs_Src[] = {
+ { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear [alpha]
+ { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear [opaque]
+ { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb [alpha]
+ { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb [opaque]
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static void dst_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[],
+ int count, const SkAlpha aa[]) {}
+
+static void dst_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f&,
+ int count, const SkAlpha coverage[]) {}
+
+const XferProcPair gProcs_Dst[] = {
+ { dst_1, dst_n },
+ { dst_1, dst_n },
+ { dst_1, dst_n },
+ { dst_1, dst_n },
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DstType D> void srcover_n(const SkXfermode::PM4fState& state, uint32_t dst[],
+ const SkPM4f src[], int count, const SkAlpha aa[]) {
+ if (aa) {
+ for (int i = 0; i < count; ++i) {
+ unsigned a = aa[i];
+ if (0 == a) {
+ continue;
+ }
+ Sk4f s4 = Sk4f::Load(src[i].fVec);
+ Sk4f d4 = load_dst<D>(dst[i]);
+ if (a != 0xFF) {
+ s4 = scale_by_coverage(s4, a);
+ }
+ Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
+ dst[i] = store_dst<D>(r4);
+ }
+ } else {
+ for (int i = 0; i < count; ++i) {
+ Sk4f s4 = Sk4f::Load(src[i].fVec);
+ Sk4f d4 = load_dst<D>(dst[i]);
+ Sk4f r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
+ dst[i] = store_dst<D>(r4);
+ }
+ }
+}
+
+template <DstType D> void srcover_1(const SkXfermode::PM4fState& state, uint32_t dst[],
+ const SkPM4f& src, int count, const SkAlpha aa[]) {
+ Sk4f s4 = Sk4f::Load(src.fVec);
+ Sk4f scale = Sk4f(1 - get_alpha(s4));
+
+ if (aa) {
+ for (int i = 0; i < count; ++i) {
+ unsigned a = aa[i];
+ if (0 == a) {
+ continue;
+ }
+ Sk4f d4 = load_dst<D>(dst[i]);
+ Sk4f r4;
+ if (a != 0xFF) {
+ s4 = scale_by_coverage(s4, a);
+ r4 = s4 + d4 * Sk4f(1 - get_alpha(s4));
+ } else {
+ r4 = s4 + d4 * scale;
+ }
+ dst[i] = store_dst<D>(r4);
+ }
+ } else {
+ for (int i = 0; i < count; ++i) {
+ Sk4f d4 = load_dst<D>(dst[i]);
+ Sk4f r4 = s4 + d4 * scale;
+ dst[i] = store_dst<D>(r4);
+ }
+ }
+}
+
+const XferProcPair gProcs_SrcOver[] = {
+ { srcover_1<kLinear_Dst>, srcover_n<kLinear_Dst> }, // linear alpha
+ { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear opaque [ we are src-mode ]
+ { srcover_1<kSRGB_Dst>, srcover_n<kSRGB_Dst> }, // srgb alpha
+ { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb opaque [ we are src-mode ]
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+static XferProcPair find_procs(SkXfermode::Mode mode, uint32_t flags) {
+ SkASSERT(0 == (flags & ~3));
+ flags &= 3;
+
+ switch (mode) {
+ case SkXfermode::kClear_Mode: return gProcs_Clear[flags];
+ case SkXfermode::kSrc_Mode: return gProcs_Src[flags];
+ case SkXfermode::kDst_Mode: return gProcs_Dst[flags];
+ case SkXfermode::kSrcOver_Mode: return gProcs_SrcOver[flags];
+ default:
+ break;
+ }
+ return { xfer_pm4_proc_1, xfer_pm4_proc_n };
+}
+
+SkXfermode::PM4fProc1 SkXfermode::GetPM4fProc1(Mode mode, uint32_t flags) {
+ return find_procs(mode, flags).fP1;
+}
+
+SkXfermode::PM4fProcN SkXfermode::GetPM4fProcN(Mode mode, uint32_t flags) {
+ return find_procs(mode, flags).fPN;
+}
+
+SkXfermode::PM4fProc1 SkXfermode::getPM4fProc1(uint32_t flags) const {
+ Mode mode;
+ return this->asMode(&mode) ? GetPM4fProc1(mode, flags) : xfer_pm4_proc_1;
+}
+
+SkXfermode::PM4fProcN SkXfermode::getPM4fProcN(uint32_t flags) const {
+ Mode mode;
+ return this->asMode(&mode) ? GetPM4fProcN(mode, flags) : xfer_pm4_proc_n;
+}
diff --git a/src/effects/SkColorMatrixFilter.cpp b/src/effects/SkColorMatrixFilter.cpp
index 980412b8dd..4bc07b39db 100644
--- a/src/effects/SkColorMatrixFilter.cpp
+++ b/src/effects/SkColorMatrixFilter.cpp
@@ -68,16 +68,16 @@ uint32_t SkColorMatrixFilter::getFlags() const {
}
static Sk4f scale_rgb(float scale) {
- static_assert(SK_A32_SHIFT == 24, "Alpha is lane 3");
+ static_assert(SkPM4f::A == 3, "Alpha is lane 3");
return Sk4f(scale, scale, scale, 1);
}
static Sk4f premul(const Sk4f& x) {
- return x * scale_rgb(x.kth<SK_A32_SHIFT/8>());
+ return x * scale_rgb(x.kth<SkPM4f::A>());
}
static Sk4f unpremul(const Sk4f& x) {
- return x * scale_rgb(1 / x.kth<SK_A32_SHIFT/8>()); // TODO: fast/approx invert?
+ return x * scale_rgb(1 / x.kth<SkPM4f::A>()); // TODO: fast/approx invert?
}
static Sk4f clamp_0_1(const Sk4f& x) {
@@ -105,7 +105,7 @@ void filter_span(const float array[], const T src[], int count, T dst[]) {
for (int i = 0; i < count; i++) {
Sk4f srcf = Adaptor::To4f(src[i]);
- float srcA = srcf.kth<SK_A32_SHIFT/8>();
+ float srcA = srcf.kth<SkPM4f::A>();
if (0 == srcA) {
dst[i] = matrix_translate_pmcolor;