aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2016-02-24 06:21:36 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2016-02-24 06:21:36 -0800
commit8f7b0b2d809510d4af4e6ff6f731bac78eded6c4 (patch)
treea3e62f14e6b02b60b915a312a1d83ffeed235c35
parentcbbc9df143287e5fd85063822aa2c570ed8df9d5 (diff)
simplify/unify xferproc api
-rw-r--r--bench/Xfer4fBench.cpp79
-rw-r--r--bench/XferU64Bench.cpp74
-rw-r--r--gm/SkLinearBitmapPipelineGM.cpp5
-rw-r--r--gm/xfer4f.cpp107
-rw-r--r--include/core/SkXfermode.h48
-rw-r--r--src/core/SkBitmapProcShader.h2
-rw-r--r--src/core/SkBlitter_PM4f.cpp130
-rw-r--r--src/core/SkSpriteBlitter4f.cpp32
-rw-r--r--src/core/SkXfermode.cpp5
-rw-r--r--src/core/SkXfermode4f.cpp150
-rw-r--r--src/core/SkXfermodeU64.cpp123
11 files changed, 303 insertions, 452 deletions
diff --git a/bench/Xfer4fBench.cpp b/bench/Xfer4fBench.cpp
index f2bcedc3ed..bc234a7edb 100644
--- a/bench/Xfer4fBench.cpp
+++ b/bench/Xfer4fBench.cpp
@@ -15,20 +15,22 @@
#define INNER_LOOPS 1000
// Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode.
-class Xfer4fBench : public Benchmark {
+class XferD32Bench : public Benchmark {
public:
- Xfer4fBench(SkXfermode::Mode mode, const char name[], bool doN, uint32_t flags)
+ XferD32Bench(SkXfermode::Mode mode, const char name[], bool doN, uint32_t flags)
: fDoN(doN)
, fFlags(flags & ~USE_AA)
{
- fProc1 = SkXfermode::GetPM4fProc1(mode, fFlags);
- fProcN = SkXfermode::GetPM4fProcN(mode, fFlags);
+ fXfer.reset(SkXfermode::Create(mode));
+
+ fProc1 = SkXfermode::GetD32Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D32Flag);
+ fProcN = SkXfermode::GetD32Proc(fXfer, fFlags);
fName.printf("xfer4f_%s_%s_%c_%s_%s",
name,
(flags & USE_AA) ? "aa" : "bw",
fDoN ? 'N' : '1',
- (flags & SkXfermode::kSrcIsOpaque_PM4fFlag) ? "opaque" : "alpha",
- (flags & SkXfermode::kDstIsSRGB_PM4fFlag) ? "srgb" : "linear");
+ (flags & SkXfermode::kSrcIsOpaque_D32Flag) ? "opaque" : "alpha",
+ (flags & SkXfermode::kDstIsSRGB_D32Flag) ? "srgb" : "linear");
for (int i = 0; i < N; ++i) {
fSrc[i] = {{ 1, 1, 1, 1 }};
@@ -49,24 +51,23 @@ protected:
const char* onGetName() override { return fName.c_str(); }
void onDraw(int loops, SkCanvas*) override {
- const SkXfermode::PM4fState state{ nullptr, fFlags };
-
for (int i = 0; i < loops * INNER_LOOPS; ++i) {
if (fDoN) {
- fProcN(state, fDst, fSrc, N, fAA);
+ fProcN(fXfer, fDst, fSrc, N, fAA);
} else {
- fProc1(state, fDst, fSrc[0], N, fAA);
+ fProc1(fXfer, fDst, fSrc, N, fAA);
}
}
}
private:
- SkString fName;
- SkXfermode::PM4fProc1 fProc1;
- SkXfermode::PM4fProcN fProcN;
- const SkAlpha* fAA;
- bool fDoN;
- uint32_t fFlags;
+ SkAutoTUnref<SkXfermode> fXfer;
+ SkString fName;
+ SkXfermode::D32Proc fProc1;
+ SkXfermode::D32Proc fProcN;
+ const SkAlpha* fAA;
+ bool fDoN;
+ uint32_t fFlags;
enum {
N = 1000,
@@ -79,26 +80,26 @@ private:
};
#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, 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); )
-
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F10 | USE_AA); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F00 | USE_AA); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F11 | USE_AA); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", false, F01 | USE_AA); )
-
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F10 | USE_AA); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F00 | USE_AA); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F11 | USE_AA); )
-DEF_BENCH( return new Xfer4fBench(SkXfermode::kSrcOver_Mode, "srcover", true, F01 | USE_AA); )
+#define F01 (SkXfermode::kSrcIsOpaque_D32Flag)
+#define F10 (SkXfermode::kDstIsSRGB_D32Flag)
+#define F11 (SkXfermode::kSrcIsOpaque_D32Flag | SkXfermode::kDstIsSRGB_D32Flag)
+
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F10); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F00); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F11); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F01); )
+
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F10); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F00); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F11); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F01); )
+
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F10 | USE_AA); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F00 | USE_AA); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F11 | USE_AA); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", false, F01 | USE_AA); )
+
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F10 | USE_AA); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F00 | USE_AA); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F11 | USE_AA); )
+DEF_BENCH( return new XferD32Bench(SkXfermode::kSrcOver_Mode, "srcover", true, F01 | USE_AA); )
diff --git a/bench/XferU64Bench.cpp b/bench/XferU64Bench.cpp
index b81bc1e354..a57ba60ec1 100644
--- a/bench/XferU64Bench.cpp
+++ b/bench/XferU64Bench.cpp
@@ -15,22 +15,22 @@
#define INNER_LOOPS 1000
// Benchmark that draws non-AA rects or AA text with an SkXfermode::Mode.
-class XferU64Bench : public Benchmark {
+class XferD64Bench : public Benchmark {
public:
- XferU64Bench(SkXfermode::Mode mode, const char name[], bool doN, uint32_t flags)
+ XferD64Bench(SkXfermode::Mode mode, const char name[], bool doN, uint32_t flags)
: fDoN(doN)
, fFlags(flags & ~USE_AA)
{
fXfer.reset(SkXfermode::Create(mode));
- fProc1 = SkXfermode::GetU64Proc1(mode, fFlags);
- fProcN = SkXfermode::GetU64ProcN(mode, fFlags);
+ fProc1 = SkXfermode::GetD64Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D64Flag);
+ fProcN = SkXfermode::GetD64Proc(fXfer, fFlags);
fName.printf("xferu64_%s_%s_%c_%s_%s",
name,
(flags & USE_AA) ? "aa" : "bw",
fDoN ? 'N' : '1',
- (flags & SkXfermode::kSrcIsOpaque_U64Flag) ? "opaque" : "alpha",
- (flags & SkXfermode::kDstIsFloat16_U64Flag) ? "f16" : "u16");
+ (flags & SkXfermode::kSrcIsOpaque_D64Flag) ? "opaque" : "alpha",
+ (flags & SkXfermode::kDstIsFloat16_D64Flag) ? "f16" : "u16");
for (int i = 0; i < N; ++i) {
fSrc[i] = {{ 1, 1, 1, 1 }};
@@ -51,25 +51,23 @@ protected:
const char* onGetName() override { return fName.c_str(); }
void onDraw(int loops, SkCanvas*) override {
- const SkXfermode::U64State state{ fXfer, fFlags };
-
for (int i = 0; i < loops * INNER_LOOPS; ++i) {
if (fDoN) {
- fProcN(state, fDst, fSrc, N, fAA);
+ fProcN(fXfer, fDst, fSrc, N, fAA);
} else {
- fProc1(state, fDst, fSrc[0], N, fAA);
+ fProc1(fXfer, fDst, fSrc, N, fAA);
}
}
}
private:
SkAutoTUnref<SkXfermode> fXfer;
- SkString fName;
- SkXfermode::U64Proc1 fProc1;
- SkXfermode::U64ProcN fProcN;
- const SkAlpha* fAA;
- bool fDoN;
- uint32_t fFlags;
+ SkString fName;
+ SkXfermode::D64Proc fProc1;
+ SkXfermode::D64Proc fProcN;
+ const SkAlpha* fAA;
+ bool fDoN;
+ uint32_t fFlags;
enum {
N = 1000,
@@ -82,29 +80,29 @@ private:
};
#define F00 0
-#define F01 (SkXfermode::kSrcIsOpaque_U64Flag)
-#define F10 (SkXfermode::kDstIsFloat16_U64Flag)
-#define F11 (SkXfermode::kDstIsFloat16_U64Flag | SkXfermode::kSrcIsOpaque_U64Flag)
+#define F01 (SkXfermode::kSrcIsOpaque_D64Flag)
+#define F10 (SkXfermode::kDstIsFloat16_D64Flag)
+#define F11 (SkXfermode::kDstIsFloat16_D64Flag | SkXfermode::kSrcIsOpaque_D64Flag)
#define MODE SkXfermode::kSrcOver_Mode
#define NAME "srcover"
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F10 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F11 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F10); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F11); )
-
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F00 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F01 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F00); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, true, F01); )
-
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F10 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F11 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F10); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F11); )
-
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F00 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F01 | USE_AA); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F00); )
-DEF_BENCH( return new XferU64Bench(MODE, NAME, false, F01); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F10 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F11 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F10); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F11); )
+
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F00 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F01 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F00); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, true, F01); )
+
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F10 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F11 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F10); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F11); )
+
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F00 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F01 | USE_AA); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F00); )
+DEF_BENCH( return new XferD64Bench(MODE, NAME, false, F01); )
diff --git a/gm/SkLinearBitmapPipelineGM.cpp b/gm/SkLinearBitmapPipelineGM.cpp
index c8fcfc9efe..74068179ba 100644
--- a/gm/SkLinearBitmapPipelineGM.cpp
+++ b/gm/SkLinearBitmapPipelineGM.cpp
@@ -115,8 +115,7 @@ static void draw_rect_fp(SkCanvas* canvas, const SkRect& r, SkColor c, const SkM
//if (kSRGB_SkColorProfileType == profile) {
//flags |= SkXfermode::kDstIsSRGB_PM4fFlag;
//}
- const SkXfermode::PM4fState state { nullptr, flags };
- auto procN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, flags);
+ auto procN = SkXfermode::GetD32Proc(nullptr, flags);
SkLinearBitmapPipeline pipeline{
inv, filterQuality,
@@ -124,7 +123,7 @@ static void draw_rect_fp(SkCanvas* canvas, const SkRect& r, SkColor c, const SkM
for (int y = 0; y < ir.height(); y++) {
pipeline.shadeSpan4f(0, y, dstBits, ir.width());
- procN(state, pmdst.writable_addr32(0, y), dstBits, ir.width(), nullptr);
+ procN(nullptr, pmdst.writable_addr32(0, y), dstBits, ir.width(), nullptr);
}
delete [] dstBits;
diff --git a/gm/xfer4f.cpp b/gm/xfer4f.cpp
deleted file mode 100644
index dc7196d399..0000000000
--- a/gm/xfer4f.cpp
+++ /dev/null
@@ -1,107 +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 "gm.h"
-#include "SkCanvas.h"
-#include "SkImageInfo.h"
-#include "SkXfermode.h"
-#include "SkPM4f.h"
-
-static void draw_rect(SkCanvas* canvas, const SkRect& r, SkColor c, SkColorProfileType profile,
- const SkAlpha aa[]) {
- const SkIRect ir = r.round();
-
- SkBitmap bm;
- bm.allocN32Pixels(ir.width(), ir.height());
- bm.eraseColor(0xFFFFFFFF);
- SkPixmap pm;
- bm.peekPixels(&pm);
-
- uint32_t flags = 0;
- if (SkColorGetA(c) == 0xFF) {
- flags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
- }
- if (kSRGB_SkColorProfileType == profile) {
- flags |= SkXfermode::kDstIsSRGB_PM4fFlag;
- }
-
- 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(state, pm.writable_addr32(0, y), src, ir.width(), aa);
- }
-
- SkPM4f srcRow[1000];
- for (int i = 0; i < ir.width(); ++i) {
- srcRow[i] = src;
- }
- 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(state, pm.writable_addr32(0, y), srcRow, ir.width(), aa);
- }
-
- canvas->drawBitmap(bm, r.left(), r.top(), nullptr);
-}
-
-/*
- * Test SkXfer4fProcs directly for src-over, comparing them to current SkColor blits.
- */
-DEF_SIMPLE_GM(xfer4f_srcover, canvas, 580, 760) {
- const int IW = 50;
- const SkScalar W = IW;
- const SkScalar H = 100;
-
- const int profiles[] = {
- -1,
- kLinear_SkColorProfileType,
- kSRGB_SkColorProfileType,
- };
- const SkColor colors[] = {
- SK_ColorBLACK, SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
- 0x88000000, 0x88FF0000, 0x8800FF00, 0x880000FF
- };
-
- uint8_t aa_scanline[IW];
- for (int i = 0; i < IW; ++i) {
- aa_scanline[i] = i * 255 / (IW - 1);
- }
- uint8_t const* aa_table[] = { nullptr, aa_scanline };
-
- SkBitmap mask;
- mask.installPixels(SkImageInfo::MakeA8(IW, 1), aa_scanline, IW);
-
- canvas->translate(20, 20);
-
- const SkRect r = SkRect::MakeWH(W, H);
- for (const uint8_t* aa : aa_table) {
- canvas->save();
- for (auto profile : profiles) {
- canvas->save();
- for (SkColor c : colors) {
- if (profile < 0) {
- SkPaint p;
- p.setColor(c);
- if (aa) {
- canvas->drawBitmapRect(mask, r, &p);
- } else {
- canvas->drawRect(r, p);
- }
- } else {
- draw_rect(canvas, r, c, (SkColorProfileType)profile, aa);
- }
- canvas->translate(W + 20, 0);
- }
- canvas->restore();
- canvas->translate(0, H + 20);
- }
- canvas->restore();
- canvas->translate(0, (H + 20) * SK_ARRAY_COUNT(profiles) + 20);
- }
-}
diff --git a/include/core/SkXfermode.h b/include/core/SkXfermode.h
index 04630e75f6..2c4da5f999 100644
--- a/include/core/SkXfermode.h
+++ b/include/core/SkXfermode.h
@@ -220,38 +220,23 @@ public:
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
SK_DEFINE_FLATTENABLE_TYPE(SkXfermode)
- enum PM4fFlags {
- kSrcIsOpaque_PM4fFlag = 1 << 0,
- kDstIsSRGB_PM4fFlag = 1 << 1,
+ enum D32Flags {
+ kSrcIsOpaque_D32Flag = 1 << 0,
+ kSrcIsSingle_D32Flag = 1 << 1,
+ kDstIsSRGB_D32Flag = 1 << 2,
};
- struct PM4fState {
- const SkXfermode* fXfer;
- uint32_t fFlags;
+ typedef void (*D32Proc)(const SkXfermode*, uint32_t dst[], const SkPM4f src[],
+ int count, const SkAlpha coverage[]);
+ static D32Proc GetD32Proc(SkXfermode*, uint32_t flags);
+
+ enum D64Flags {
+ kSrcIsOpaque_D64Flag = 1 << 0,
+ kSrcIsSingle_D64Flag = 1 << 1,
+ kDstIsFloat16_D64Flag = 1 << 2, // else U16 bit components
};
- 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;
-
- enum U64Flags {
- kSrcIsOpaque_U64Flag = 1 << 0,
- kDstIsFloat16_U64Flag = 1 << 1, // else U16 bit components
- };
- struct U64State {
- const SkXfermode* fXfer;
- uint32_t fFlags;
- };
- typedef void (*U64Proc1)(const U64State&, uint64_t dst[], const SkPM4f& src, int count,
- const SkAlpha coverage[]);
- typedef void (*U64ProcN)(const U64State&, uint64_t dst[], const SkPM4f src[], int count,
- const SkAlpha coverage[]);
- static U64Proc1 GetU64Proc1(Mode, uint32_t flags);
- static U64ProcN GetU64ProcN(Mode, uint32_t flags);
+ typedef void (*D64Proc)(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
+ const SkAlpha coverage[]);
+ static D64Proc GetD64Proc(SkXfermode*, uint32_t flags);
enum LCDFlags {
kSrcIsOpaque_LCDFlag = 1 << 0, // else src(s) may have alpha < 1
@@ -275,6 +260,9 @@ protected:
*/
virtual SkPMColor xferColor(SkPMColor src, SkPMColor dst) const;
+ virtual D32Proc onGetD32Proc(uint32_t flags) const;
+ virtual D64Proc onGetD64Proc(uint32_t flags) const;
+
private:
enum {
kModeCount = kLastMode + 1
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index 05c5955f35..b897c6e500 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -75,7 +75,7 @@ private:
// an Sk3DBlitter in SkDraw.cpp
// Note that some contexts may contain other contexts (e.g. for compose shaders), but we've not
// yet found a situation where the size below isn't big enough.
-typedef SkSmallAllocator<3, 1280> SkTBlitterAllocator;
+typedef SkSmallAllocator<3, 1500> SkTBlitterAllocator;
// If alloc is non-nullptr, it will be used to allocate the returned SkShader, and MUST outlive
// the SkShader.
diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp
index 24fc4a39dd..179aec3557 100644
--- a/src/core/SkBlitter_PM4f.cpp
+++ b/src/core/SkBlitter_PM4f.cpp
@@ -27,7 +27,8 @@ public:
void blitH(int x, int y, int width) override {
SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());
- fState.fProc1(fState, State::WritableAddr(fDevice, x, y), fState.fPM4f, width, nullptr);
+ fState.fProc1(fState.fXfer, State::WritableAddr(fDevice, x, y),
+ &fState.fPM4f, width, nullptr);
}
void blitV(int x, int y, int height, SkAlpha alpha) override {
@@ -37,7 +38,7 @@ public:
size_t deviceRB = fDevice.rowBytes();
for (int i = 0; i < height; ++i) {
- fState.fProc1(fState, device, fState.fPM4f, 1, &alpha);
+ fState.fProc1(fState.fXfer, device, &fState.fPM4f, 1, &alpha);
device = (typename State::DstType*)((char*)device + deviceRB);
}
}
@@ -50,7 +51,7 @@ public:
size_t deviceRB = fDevice.rowBytes();
do {
- fState.fProc1(fState, device, fState.fPM4f, width, nullptr);
+ fState.fProc1(fState.fXfer, device, &fState.fPM4f, width, nullptr);
y += 1;
device = (typename State::DstType*)((char*)device + deviceRB);
} while (--height > 0);
@@ -67,10 +68,10 @@ public:
int aa = *antialias;
if (aa) {
if (aa == 255) {
- fState.fProc1(fState, device, fState.fPM4f, count, nullptr);
+ fState.fProc1(fState.fXfer, device, &fState.fPM4f, count, nullptr);
} else {
for (int i = 0; i < count; ++i) {
- fState.fProc1(fState, &device[i], fState.fPM4f, 1, antialias);
+ fState.fProc1(fState.fXfer, &device[i], &fState.fPM4f, 1, antialias);
}
}
}
@@ -124,7 +125,7 @@ public:
const size_t maskRB = mask.fRowBytes;
for (int i = 0; i < height; ++i) {
- fState.fProc1(fState, device, fState.fPM4f, width, maskRow);
+ fState.fProc1(fState.fXfer, device, &fState.fPM4f, width, maskRow);
device = (typename State::DstType*)((char*)device + dstRB);
maskRow += maskRB;
}
@@ -146,7 +147,7 @@ public:
typename State::DstType* device = State::WritableAddr(fDevice, x, y);
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
- fState.fProcN(fState, device, fState.fBuffer, width, nullptr);
+ fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr);
}
void blitV(int x, int y, int height, SkAlpha alpha) override {
@@ -163,7 +164,7 @@ public:
if (!fConstInY) {
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, 1);
}
- fState.fProcN(fState, device, fState.fBuffer, 1, &alpha);
+ fState.fProcN(fState.fXfer, device, fState.fBuffer, 1, &alpha);
device = (typename State::DstType*)((char*)device + deviceRB);
}
}
@@ -183,7 +184,7 @@ public:
if (!fConstInY) {
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
}
- fState.fProcN(fState, device, fState.fBuffer, width, nullptr);
+ fState.fProcN(fState.fXfer, device, fState.fBuffer, width, nullptr);
device = (typename State::DstType*)((char*)device + deviceRB);
}
}
@@ -200,10 +201,10 @@ public:
if (aa) {
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, count);
if (aa == 255) {
- fState.fProcN(fState, device, fState.fBuffer, count, nullptr);
+ fState.fProcN(fState.fXfer, device, fState.fBuffer, count, nullptr);
} else {
for (int i = 0; i < count; ++i) {
- fState.fProcN(fState, &device[i], &fState.fBuffer[i], 1, antialias);
+ fState.fProcN(fState.fXfer, &device[i], &fState.fBuffer[i], 1, antialias);
}
}
}
@@ -267,7 +268,7 @@ public:
if (!fConstInY) {
fShaderContext->shadeSpan4f(x, y, fState.fBuffer, width);
}
- fState.fProcN(fState, device, fState.fBuffer, width, maskRow);
+ fState.fProcN(fState.fXfer, device, fState.fBuffer, width, maskRow);
device = (typename State::DstType*)((char*)device + deviceRB);
maskRow += maskRB;
}
@@ -286,47 +287,45 @@ static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderConte
: 0xFF == paint.getAlpha();
}
-struct State32 : SkXfermode::PM4fState {
- typedef uint32_t DstType;
-
- SkXfermode::PM4fProc1 fProc1;
- SkXfermode::PM4fProcN fProcN;
+struct State4f {
+ State4f(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
+ fXfer = paint.getXfermode();
+ if (shaderContext) {
+ fBuffer.reset(info.width());
+ } else {
+ fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
+ }
+ fFlags = 0;
+ }
+
+ SkXfermode* fXfer;
SkPM4f fPM4f;
- SkPM4f* fBuffer;
+ SkAutoTMalloc<SkPM4f> fBuffer;
+ uint32_t fFlags;
+};
+
+struct State32 : State4f {
+ typedef uint32_t DstType;
- State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
- fXfer = SkSafeRef(paint.getXfermode());
- fFlags = 0;
+ SkXfermode::D32Proc fProc1;
+ SkXfermode::D32Proc fProcN;
+
+ State32(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
+ : State4f(info, paint, shaderContext)
+ {
if (is_opaque(paint, shaderContext)) {
- fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
+ fFlags |= SkXfermode::kSrcIsOpaque_D32Flag;
}
if (info.isSRGB()) {
- fFlags |= SkXfermode::kDstIsSRGB_PM4fFlag;
- }
- if (fXfer) {
- fProc1 = fXfer->getPM4fProc1(fFlags);
- fProcN = fXfer->getPM4fProcN(fFlags);
- } else {
- fProc1 = SkXfermode::GetPM4fProc1(SkXfermode::kSrcOver_Mode, fFlags);
- fProcN = SkXfermode::GetPM4fProcN(SkXfermode::kSrcOver_Mode, fFlags);
- }
-
- fBuffer = nullptr;
- if (shaderContext) {
- fBuffer = new SkPM4f[info.width()];
- } else {
- fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
+ fFlags |= SkXfermode::kDstIsSRGB_D32Flag;
}
+ fProc1 = SkXfermode::GetD32Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D32Flag);
+ fProcN = SkXfermode::GetD32Proc(fXfer, fFlags);
}
- ~State32() {
- SkSafeUnref(fXfer);
- delete[] fBuffer;
- }
-
SkXfermode::LCD32Proc getLCDProc(uint32_t oneOrManyFlag) const {
uint32_t flags = fFlags & 1;
- if (!(fFlags & SkXfermode::kDstIsSRGB_PM4fFlag)) {
+ if (!(fFlags & SkXfermode::kDstIsSRGB_D32Flag)) {
flags |= SkXfermode::kDstIsLinearInt_LCDFlag;
}
return SkXfermode::GetLCD32Proc(flags | oneOrManyFlag);
@@ -337,47 +336,28 @@ struct State32 : SkXfermode::PM4fState {
}
};
-struct State64 : SkXfermode::U64State {
- typedef uint64_t DstType;
+struct State64 : State4f {
+ typedef uint64_t DstType;
- SkXfermode::U64Proc1 fProc1;
- SkXfermode::U64ProcN fProcN;
- SkPM4f fPM4f;
- SkPM4f* fBuffer;
+ SkXfermode::D64Proc fProc1;
+ SkXfermode::D64Proc fProcN;
- State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) {
- fXfer = SkSafeRef(paint.getXfermode());
- fFlags = 0;
+ State64(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext)
+ : State4f(info, paint, shaderContext)
+ {
if (is_opaque(paint, shaderContext)) {
- fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
+ fFlags |= SkXfermode::kSrcIsOpaque_D64Flag;
}
if (kRGBA_F16_SkColorType == info.colorType()) {
- fFlags |= SkXfermode::kDstIsFloat16_U64Flag;
- }
-
- SkXfermode::Mode mode;
- if (!SkXfermode::AsMode(fXfer, &mode)) {
- mode = SkXfermode::kSrcOver_Mode;
- }
- fProc1 = SkXfermode::GetU64Proc1(mode, fFlags);
- fProcN = SkXfermode::GetU64ProcN(mode, fFlags);
-
- fBuffer = nullptr;
- if (shaderContext) {
- fBuffer = new SkPM4f[info.width()];
- } else {
- fPM4f = SkColor4f::FromColor(paint.getColor()).premul();
+ fFlags |= SkXfermode::kDstIsFloat16_D64Flag;
}
+ fProc1 = SkXfermode::GetD64Proc(fXfer, fFlags | SkXfermode::kSrcIsSingle_D64Flag);
+ fProcN = SkXfermode::GetD64Proc(fXfer, fFlags);
}
-
- ~State64() {
- SkSafeUnref(fXfer);
- delete[] fBuffer;
- }
-
+
SkXfermode::LCD64Proc getLCDProc(uint32_t oneOrManyFlag) const {
uint32_t flags = fFlags & 1;
- if (!(fFlags & SkXfermode::kDstIsFloat16_U64Flag)) {
+ if (!(fFlags & SkXfermode::kDstIsFloat16_D64Flag)) {
flags |= SkXfermode::kDstIsLinearInt_LCDFlag;
}
return SkXfermode::GetLCD64Proc(flags | oneOrManyFlag);
diff --git a/src/core/SkSpriteBlitter4f.cpp b/src/core/SkSpriteBlitter4f.cpp
index fc4b480951..474bf4d0f6 100644
--- a/src/core/SkSpriteBlitter4f.cpp
+++ b/src/core/SkSpriteBlitter4f.cpp
@@ -13,12 +13,14 @@
class Sprite_4f : public SkSpriteBlitter {
public:
Sprite_4f(const SkPixmap& src, const SkPaint& paint) : INHERITED(src) {
+ fXfer = paint.getXfermode();
fLoader = SkLoadSpanProc_Choose(src.info());
fFilter = SkFilterSpanProc_Choose(paint);
fBuffer.reset(src.width());
}
protected:
+ SkXfermode* fXfer;
SkLoadSpanProc fLoader;
SkFilterSpanProc fFilter;
SkAutoTMalloc<SkPM4f> fBuffer;
@@ -29,22 +31,14 @@ private:
///////////////////////////////////////////////////////////////////////////////////////////////////
-static SkXfermode::Mode get_mode(const SkXfermode* xfer) {
- SkXfermode::Mode mode;
- if (!SkXfermode::AsMode(xfer, &mode)) {
- mode = SkXfermode::kSrcOver_Mode;
- }
- return mode;
-}
-
class Sprite_F16 : public Sprite_4f {
public:
Sprite_F16(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) {
- fState = { paint.getXfermode(), SkXfermode::kDstIsFloat16_U64Flag };
+ uint32_t flags = SkXfermode::kDstIsFloat16_D64Flag;
if (src.isOpaque()) {
- fState.fFlags |= SkXfermode::kSrcIsOpaque_U64Flag;
+ flags |= SkXfermode::kSrcIsOpaque_D64Flag;
}
- fXfer = SkXfermode::GetU64ProcN(get_mode(fState.fXfer), fState.fFlags);
+ fWriter = SkXfermode::GetD64Proc(fXfer, flags);
}
void blitRect(int x, int y, int width, int height) override {
@@ -55,14 +49,13 @@ public:
for (int bottom = y + height; y < bottom; ++y) {
fLoader(fSource, x - fLeft, y - fTop, fBuffer, width);
fFilter(*fPaint, fBuffer, width);
- fXfer(fState, dst, fBuffer, width, nullptr);
+ fWriter(fXfer, dst, fBuffer, width, nullptr);
dst = (uint64_t* SK_RESTRICT)((char*)dst + dstRB);
}
}
private:
- SkXfermode::U64State fState;
- SkXfermode::U64ProcN fXfer;
+ SkXfermode::D64Proc fWriter;
typedef Sprite_4f INHERITED;
};
@@ -90,11 +83,11 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseF16(const SkPixmap& source, const SkPain
class Sprite_sRGB : public Sprite_4f {
public:
Sprite_sRGB(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) {
- fState = { paint.getXfermode(), SkXfermode::kDstIsSRGB_PM4fFlag };
+ uint32_t flags = SkXfermode::kDstIsSRGB_D32Flag;
if (src.isOpaque()) {
- fState.fFlags |= SkXfermode::kSrcIsOpaque_PM4fFlag;
+ flags |= SkXfermode::kSrcIsOpaque_D32Flag;
}
- fXfer = SkXfermode::GetPM4fProcN(get_mode(fState.fXfer), fState.fFlags);
+ fWriter = SkXfermode::GetD32Proc(fXfer, flags);
}
void blitRect(int x, int y, int width, int height) override {
@@ -105,14 +98,13 @@ public:
for (int bottom = y + height; y < bottom; ++y) {
fLoader(fSource, x - fLeft, y - fTop, fBuffer, width);
fFilter(*fPaint, fBuffer, width);
- fXfer(fState, dst, fBuffer, width, nullptr);
+ fWriter(fXfer, dst, fBuffer, width, nullptr);
dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
}
}
protected:
- SkXfermode::PM4fState fState;
- SkXfermode::PM4fProcN fXfer;
+ SkXfermode::D32Proc fWriter;
private:
typedef Sprite_4f INHERITED;
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 7002e9a533..262e5265c7 100644
--- a/src/core/SkXfermode.cpp
+++ b/src/core/SkXfermode.cpp
@@ -928,8 +928,9 @@ static Sk4f as_4f(const SkPM4f& pm4) {
static void assert_unit(const SkPM4f& r) {
#ifdef SK_DEBUG
- const float min = 0;
- const float max = 1;
+ const float eps = 0.00001f;
+ const float min = 0 - eps;
+ const float max = 1 + eps;
for (int i = 0; i < 4; ++i) {
SkASSERT(r.fVec[i] >= min && r.fVec[i] <= max);
}
diff --git a/src/core/SkXfermode4f.cpp b/src/core/SkXfermode4f.cpp
index 8aa2ce26a4..46eed05a19 100644
--- a/src/core/SkXfermode4f.cpp
+++ b/src/core/SkXfermode4f.cpp
@@ -9,11 +9,6 @@
#include "SkUtils.h"
#include "SkXfermode.h"
-struct XferProcPair {
- SkXfermode::PM4fProc1 fP1;
- SkXfermode::PM4fProcN fPN;
-};
-
enum DstType {
kLinear_Dst,
kSRGB_Dst,
@@ -45,29 +40,29 @@ static Sk4f linear_unit_to_srgb_255f(const Sk4f& l4) {
///////////////////////////////////////////////////////////////////////////////////////////////////
-template <DstType D> void general_1(const SkXfermode::PM4fState& state, uint32_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- SkXfermodeProc4f proc = state.fXfer->getProc4f();
+template <DstType D> void general_1(const SkXfermode* xfer, uint32_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ SkXfermodeProc4f proc = xfer->getProc4f();
SkPM4f d;
if (aa) {
for (int i = 0; i < count; ++i) {
Sk4f d4 = load_dst<D>(dst[i]);
d4.store(d.fVec);
- Sk4f r4 = Sk4f::Load(proc(src, d).fVec);
+ Sk4f r4 = Sk4f::Load(proc(*src, d).fVec);
dst[i] = store_dst<D>(lerp(r4, d4, aa[i]));
}
} else {
for (int i = 0; i < count; ++i) {
load_dst<D>(dst[i]).store(d.fVec);
- Sk4f r4 = Sk4f::Load(proc(src, d).fVec);
+ Sk4f r4 = Sk4f::Load(proc(*src, d).fVec);
dst[i] = store_dst<D>(r4);
}
}
}
-template <DstType D> void general_n(const SkXfermode::PM4fState& state, uint32_t dst[],
+template <DstType D> void general_n(const SkXfermode* xfer, uint32_t dst[],
const SkPM4f src[], int count, const SkAlpha aa[]) {
- SkXfermodeProc4f proc = state.fXfer->getProc4f();
+ SkXfermodeProc4f proc = xfer->getProc4f();
SkPM4f d;
if (aa) {
for (int i = 0; i < count; ++i) {
@@ -85,16 +80,16 @@ template <DstType D> void general_n(const SkXfermode::PM4fState& state, uint32_t
}
}
-const XferProcPair gProcs_General[] = {
- { general_1<kLinear_Dst>, general_n<kLinear_Dst> }, // linear alpha
- { general_1<kLinear_Dst>, general_n<kLinear_Dst> }, // linear opaque
- { general_1<kSRGB_Dst>, general_n<kSRGB_Dst> }, // srgb alpha
- { general_1<kSRGB_Dst>, general_n<kSRGB_Dst> }, // srgb opaque
+const SkXfermode::D32Proc gProcs_General[] = {
+ general_n<kLinear_Dst>, general_n<kLinear_Dst>,
+ general_1<kLinear_Dst>, general_1<kLinear_Dst>,
+ general_n<kSRGB_Dst>, general_n<kSRGB_Dst>,
+ general_1<kSRGB_Dst>, general_1<kSRGB_Dst>,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-static void clear_linear_n(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f[],
+static void clear_linear(const SkXfermode*, uint32_t dst[], const SkPM4f[],
int count, const SkAlpha aa[]) {
if (aa) {
for (int i = 0; i < count; ++i) {
@@ -109,45 +104,34 @@ static void clear_linear_n(const SkXfermode::PM4fState& state, uint32_t dst[], c
}
}
} else {
- sk_bzero(dst, count * sizeof(SkPMColor));
+ sk_memset32(dst, 0, count);
}
}
-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[]) {
+static void clear_srgb(const SkXfermode*, 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));
+ if (aa[i]) {
+ Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - aa[i]) * (1/255.0f));
dst[i] = Sk4f_toS32(d);
}
}
} else {
- sk_bzero(dst, count * sizeof(SkPMColor));
+ sk_memset32(dst, 0, count);
}
}
-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]
+const SkXfermode::D32Proc gProcs_Clear[] = {
+ clear_linear, clear_linear,
+ clear_linear, clear_linear,
+ clear_srgb, clear_srgb,
+ clear_srgb, clear_srgb,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-template <DstType D> void src_n(const SkXfermode::PM4fState& state, uint32_t dst[],
+template <DstType D> void src_n(const SkXfermode*, uint32_t dst[],
const SkPM4f src[], int count, const SkAlpha aa[]) {
for (int i = 0; i < count; ++i) {
unsigned a = 0xFF;
@@ -170,9 +154,9 @@ static Sk4f lerp(const Sk4f& src, const Sk4f& dst, const Sk4f& src_scale) {
return dst + (src - dst) * src_scale;
}
-template <DstType D> void src_1(const SkXfermode::PM4fState& state, uint32_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- const Sk4f s4 = Sk4f::Load(src.fVec);
+template <DstType D> void src_1(const SkXfermode*, uint32_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ const Sk4f s4 = Sk4f::Load(src->fVec);
if (aa) {
if (D == kLinear_Dst) {
@@ -223,31 +207,24 @@ template <DstType D> void src_1(const SkXfermode::PM4fState& state, uint32_t dst
}
}
-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]
+const SkXfermode::D32Proc gProcs_Src[] = {
+ src_n<kLinear_Dst>, src_n<kLinear_Dst>,
+ src_1<kLinear_Dst>, src_1<kLinear_Dst>,
+ src_n<kSRGB_Dst>, src_n<kSRGB_Dst>,
+ src_1<kSRGB_Dst>, src_1<kSRGB_Dst>,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-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[]) {}
+static void dst(const SkXfermode*, uint32_t dst[], const SkPM4f[], int count, const SkAlpha aa[]) {}
-const XferProcPair gProcs_Dst[] = {
- { dst_1, dst_n },
- { dst_1, dst_n },
- { dst_1, dst_n },
- { dst_1, dst_n },
+const SkXfermode::D32Proc gProcs_Dst[] = {
+ dst, dst, dst, dst, dst, dst, dst, dst,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-template <DstType D> void srcover_n(const SkXfermode::PM4fState& state, uint32_t dst[],
+template <DstType D> void srcover_n(const SkXfermode*, uint32_t dst[],
const SkPM4f src[], int count, const SkAlpha aa[]) {
if (aa) {
for (int i = 0; i < count; ++i) {
@@ -273,9 +250,9 @@ template <DstType D> void srcover_n(const SkXfermode::PM4fState& state, uint32_t
}
}
-static void srcover_linear_dst_1(const SkXfermode::PM4fState& state, uint32_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- const Sk4f s4 = Sk4f::Load(src.fVec);
+static void srcover_linear_dst_1(const SkXfermode*, uint32_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ const Sk4f s4 = Sk4f::Load(src->fVec);
const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
if (aa) {
@@ -316,9 +293,9 @@ static void srcover_linear_dst_1(const SkXfermode::PM4fState& state, uint32_t ds
}
}
-static void srcover_srgb_dst_1(const SkXfermode::PM4fState& state, uint32_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- Sk4f s4 = Sk4f::Load(src.fVec);
+static void srcover_srgb_dst_1(const SkXfermode*, uint32_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ Sk4f s4 = Sk4f::Load(src->fVec);
Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
if (aa) {
@@ -358,18 +335,19 @@ static void srcover_srgb_dst_1(const SkXfermode::PM4fState& state, uint32_t dst[
}
}
-const XferProcPair gProcs_SrcOver[] = {
- { srcover_linear_dst_1, srcover_n<kLinear_Dst> }, // linear alpha
- { src_1<kLinear_Dst>, src_n<kLinear_Dst> }, // linear opaque [ we are src-mode ]
- { srcover_srgb_dst_1, srcover_n<kSRGB_Dst> }, // srgb alpha
- { src_1<kSRGB_Dst>, src_n<kSRGB_Dst> }, // srgb opaque [ we are src-mode ]
+const SkXfermode::D32Proc gProcs_SrcOver[] = {
+ srcover_n<kLinear_Dst>, src_n<kLinear_Dst>,
+ srcover_linear_dst_1, src_1<kLinear_Dst>,
+
+ srcover_n<kSRGB_Dst>, src_n<kSRGB_Dst>,
+ srcover_srgb_dst_1, src_1<kSRGB_Dst>,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-static XferProcPair find_procs(SkXfermode::Mode mode, uint32_t flags) {
- SkASSERT(0 == (flags & ~3));
- flags &= 3;
+static SkXfermode::D32Proc find_proc(SkXfermode::Mode mode, uint32_t flags) {
+ SkASSERT(0 == (flags & ~7));
+ flags &= 7;
switch (mode) {
case SkXfermode::kClear_Mode: return gProcs_Clear[flags];
@@ -382,28 +360,16 @@ static XferProcPair find_procs(SkXfermode::Mode mode, uint32_t flags) {
return gProcs_General[flags];
}
-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 {
- SkASSERT(0 == (flags & ~3));
- flags &= 3;
+SkXfermode::D32Proc SkXfermode::onGetD32Proc(uint32_t flags) const {
+ SkASSERT(0 == (flags & ~7));
+ flags &= 7;
Mode mode;
- return this->asMode(&mode) ? GetPM4fProc1(mode, flags) : gProcs_General[flags].fP1;
+ return this->asMode(&mode) ? find_proc(mode, flags) : gProcs_General[flags];
}
-SkXfermode::PM4fProcN SkXfermode::getPM4fProcN(uint32_t flags) const {
- SkASSERT(0 == (flags & ~3));
- flags &= 3;
-
- Mode mode;
- return this->asMode(&mode) ? GetPM4fProcN(mode, flags) : gProcs_General[flags].fPN;
+SkXfermode::D32Proc SkXfermode::GetD32Proc(SkXfermode* xfer, uint32_t flags) {
+ return xfer ? xfer->onGetD32Proc(flags) : find_proc(SkXfermode::kSrcOver_Mode, flags);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkXfermodeU64.cpp b/src/core/SkXfermodeU64.cpp
index 5d260c1713..2609f89a2f 100644
--- a/src/core/SkXfermodeU64.cpp
+++ b/src/core/SkXfermodeU64.cpp
@@ -16,11 +16,6 @@ static void sk_memset64(uint64_t dst[], uint64_t value, int count) {
}
}
-struct U64ProcPair {
- SkXfermode::U64Proc1 fP1;
- SkXfermode::U64ProcN fPN;
-};
-
enum DstType {
kU16_Dst,
kF16_Dst,
@@ -72,29 +67,29 @@ static inline Sk4f pm_to_rgba_order(const Sk4f& x) {
///////////////////////////////////////////////////////////////////////////////////////////////////
-template <DstType D> void xfer_u64_1(const SkXfermode::U64State& state, uint64_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- SkXfermodeProc4f proc = state.fXfer->getProc4f();
+template <DstType D> void xfer_u64_1(const SkXfermode* xfer, uint64_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ SkXfermodeProc4f proc = xfer->getProc4f();
SkPM4f d;
if (aa) {
for (int i = 0; i < count; ++i) {
Sk4f d4 = bias_to_unit<D>(load_from_dst<D>(dst[i]));
d4.store(d.fVec);
- Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(src, d).fVec));
+ Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(*src, d).fVec));
dst[i] = store_to_dst<D>(lerp_by_coverage(r4, d4, aa[i]));
}
} else {
for (int i = 0; i < count; ++i) {
bias_to_unit<D>(load_from_dst<D>(dst[i])).store(d.fVec);
- Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(src, d).fVec));
+ Sk4f r4 = unit_to_bias<D>(Sk4f::Load(proc(*src, d).fVec));
dst[i] = store_to_dst<D>(r4);
}
}
}
-template <DstType D> void xfer_u64_n(const SkXfermode::U64State& state, uint64_t dst[],
+template <DstType D> void xfer_u64_n(const SkXfermode* xfer, uint64_t dst[],
const SkPM4f src[], int count, const SkAlpha aa[]) {
- SkXfermodeProc4f proc = state.fXfer->getProc4f();
+ SkXfermodeProc4f proc = xfer->getProc4f();
SkPM4f d;
if (aa) {
for (int i = 0; i < count; ++i) {
@@ -112,18 +107,41 @@ template <DstType D> void xfer_u64_n(const SkXfermode::U64State& state, uint64_t
}
}
-const U64ProcPair gU64Procs_General[] = {
- { xfer_u64_1<kU16_Dst>, xfer_u64_n<kU16_Dst> }, // U16 alpha
- { xfer_u64_1<kU16_Dst>, xfer_u64_n<kU16_Dst> }, // U16 opaque
- { xfer_u64_1<kF16_Dst>, xfer_u64_n<kF16_Dst> }, // F16 alpha
- { xfer_u64_1<kF16_Dst>, xfer_u64_n<kF16_Dst> }, // F16 opaque
+const SkXfermode::D64Proc gProcs_General[] = {
+ xfer_u64_n<kU16_Dst>, xfer_u64_n<kU16_Dst>,
+ xfer_u64_1<kU16_Dst>, xfer_u64_1<kU16_Dst>,
+ xfer_u64_n<kF16_Dst>, xfer_u64_n<kF16_Dst>,
+ xfer_u64_1<kF16_Dst>, xfer_u64_1<kF16_Dst>,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-template <DstType D> void src_1(const SkXfermode::U64State& state, uint64_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src.fVec)));
+template <DstType D> void clear(const SkXfermode*, uint64_t dst[],
+ const SkPM4f*, int count, const SkAlpha aa[]) {
+ if (aa) {
+ for (int i = 0; i < count; ++i) {
+ if (aa[i]) {
+ const Sk4f d4 = load_from_dst<D>(dst[i]);
+ dst[i] = store_to_dst<D>(d4 * Sk4f((255 - aa[i]) * 1.0f/255));
+ }
+ }
+ } else {
+ sk_memset64(dst, 0, count);
+ }
+}
+
+const SkXfermode::D64Proc gProcs_Clear[] = {
+ clear<kU16_Dst>, clear<kU16_Dst>,
+ clear<kU16_Dst>, clear<kU16_Dst>,
+ clear<kF16_Dst>, clear<kF16_Dst>,
+ clear<kF16_Dst>, clear<kF16_Dst>,
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DstType D> void src_1(const SkXfermode*, uint64_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ const Sk4f s4 = pm_to_rgba_order(unit_to_bias<D>(Sk4f::Load(src->fVec)));
if (aa) {
for (int i = 0; i < count; ++i) {
const Sk4f d4 = load_from_dst<D>(dst[i]);
@@ -134,7 +152,7 @@ template <DstType D> void src_1(const SkXfermode::U64State& state, uint64_t dst[
}
}
-template <DstType D> void src_n(const SkXfermode::U64State& state, uint64_t dst[],
+template <DstType D> void src_n(const SkXfermode*, uint64_t dst[],
const SkPM4f src[], int count, const SkAlpha aa[]) {
if (aa) {
for (int i = 0; i < count; ++i) {
@@ -150,18 +168,26 @@ template <DstType D> void src_n(const SkXfermode::U64State& state, uint64_t dst[
}
}
-const U64ProcPair gU64Procs_Src[] = {
- { src_1<kU16_Dst>, src_n<kU16_Dst> }, // U16 alpha
- { src_1<kU16_Dst>, src_n<kU16_Dst> }, // U16 opaque
- { src_1<kF16_Dst>, src_n<kF16_Dst> }, // F16 alpha
- { src_1<kF16_Dst>, src_n<kF16_Dst> }, // F16 opaque
+const SkXfermode::D64Proc gProcs_Src[] = {
+ src_n<kU16_Dst>, src_n<kU16_Dst>,
+ src_1<kU16_Dst>, src_1<kU16_Dst>,
+ src_n<kF16_Dst>, src_n<kF16_Dst>,
+ src_1<kF16_Dst>, src_1<kF16_Dst>,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-template <DstType D> void srcover_1(const SkXfermode::U64State& state, uint64_t dst[],
- const SkPM4f& src, int count, const SkAlpha aa[]) {
- const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src.fVec));
+static void dst(const SkXfermode*, uint64_t*, const SkPM4f*, int count, const SkAlpha[]) {}
+
+const SkXfermode::D64Proc gProcs_Dst[] = {
+ dst, dst, dst, dst, dst, dst, dst, dst,
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+template <DstType D> void srcover_1(const SkXfermode*, uint64_t dst[],
+ const SkPM4f* src, int count, const SkAlpha aa[]) {
+ const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src->fVec));
const Sk4f dst_scale = Sk4f(1 - get_alpha(s4));
const Sk4f s4bias = unit_to_bias<D>(s4);
for (int i = 0; i < count; ++i) {
@@ -175,7 +201,7 @@ template <DstType D> void srcover_1(const SkXfermode::U64State& state, uint64_t
}
}
-template <DstType D> void srcover_n(const SkXfermode::U64State& state, uint64_t dst[],
+template <DstType D> void srcover_n(const SkXfermode*, uint64_t dst[],
const SkPM4f src[], int count, const SkAlpha aa[]) {
for (int i = 0; i < count; ++i) {
const Sk4f s4 = pm_to_rgba_order(Sk4f::Load(src[i].fVec));
@@ -191,32 +217,39 @@ template <DstType D> void srcover_n(const SkXfermode::U64State& state, uint64_t
}
}
-const U64ProcPair gU64Procs_SrcOver[] = {
- { srcover_1<kU16_Dst>, srcover_n<kU16_Dst> }, // U16 alpha
- { src_1<kU16_Dst>, src_n<kU16_Dst> }, // U16 opaque
- { srcover_1<kF16_Dst>, srcover_n<kF16_Dst> }, // F16 alpha
- { src_1<kF16_Dst>, src_n<kF16_Dst> }, // F16 opaque
+const SkXfermode::D64Proc gProcs_SrcOver[] = {
+ srcover_n<kU16_Dst>, src_n<kU16_Dst>,
+ srcover_1<kU16_Dst>, src_1<kU16_Dst>,
+ srcover_n<kF16_Dst>, src_n<kF16_Dst>,
+ srcover_1<kF16_Dst>, src_1<kF16_Dst>,
};
///////////////////////////////////////////////////////////////////////////////////////////////////
-static U64ProcPair find_procs(SkXfermode::Mode mode, uint32_t flags) {
- SkASSERT(0 == (flags & ~3));
- flags &= 3;
+static SkXfermode::D64Proc find_proc(SkXfermode::Mode mode, uint32_t flags) {
+ SkASSERT(0 == (flags & ~7));
+ flags &= 7;
switch (mode) {
- case SkXfermode::kSrc_Mode: return gU64Procs_Src[flags];
- case SkXfermode::kSrcOver_Mode: return gU64Procs_SrcOver[flags];
+ 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 gU64Procs_General[flags];
+ return gProcs_General[flags];
}
-SkXfermode::U64Proc1 SkXfermode::GetU64Proc1(Mode mode, uint32_t flags) {
- return find_procs(mode, flags).fP1;
+SkXfermode::D64Proc SkXfermode::onGetD64Proc(uint32_t flags) const {
+ SkASSERT(0 == (flags & ~7));
+ flags &= 7;
+
+ Mode mode;
+ return this->asMode(&mode) ? find_proc(mode, flags) : gProcs_General[flags];
}
-SkXfermode::U64ProcN SkXfermode::GetU64ProcN(Mode mode, uint32_t flags) {
- return find_procs(mode, flags).fPN;
+SkXfermode::D64Proc SkXfermode::GetD64Proc(SkXfermode* xfer, uint32_t flags) {
+ return xfer ? xfer->onGetD64Proc(flags) : find_proc(SkXfermode::kSrcOver_Mode, flags);
}
+