starter procs for blending with pm4f
curr/maxrss loops min median mean max stddev samples config bench 8/8 MB 4 87.1µs 91µs 89.8µs 92µs 2% ▇▇▇▇█▇▅▁▁▁ nonrendering xfer4f_srcover_N_opaque_linear 9/9 MB 2 196µs 196µs 215µs 383µs 27% ▁▁▁▁█▁▁▁▁▁ nonrendering xfer4f_srcover_N_opaque_srgb 9/9 MB 1 313µs 313µs 313µs 313µs 0% ▁▄▅▅▅▂████ nonrendering xfer4f_srcover_N_alpha_linear 9/9 MB 1 580µs 580µs 582µs 602µs 1% ▁▁▁▁▁▁▂▁▁█ nonrendering xfer4f_srcover_N_alpha_srgb 9/9 MB 23 13.1µs 13.1µs 13.1µs 13.1µs 0% ▆▄▄█▂▂▂▁▂▁ nonrendering xfer4f_srcover_1_opaque_linear 9/9 MB 23 13.2µs 13.2µs 13.2µs 13.2µs 0% █▄▂▁▃▁▂▂▂▂ nonrendering xfer4f_srcover_1_opaque_srgb 9/9 MB 2 178µs 183µs 183µs 185µs 1% ▇▇▇█▇▇▇▇▇▁ nonrendering xfer4f_srcover_1_alpha_linear 9/9 MB 1 517µs 517µs 517µs 517µs 0% ▇█▄▃▄▁▂▁▂▄ nonrendering xfer4f_srcover_1_alpha_srgb BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1642703003 TBR= landing now so these incremental types/functions can be used to collaborate with herb's work. nothing is active at this point Review URL: https://codereview.chromium.org/1642703003
This commit is contained in:
parent
aa9cb62901
commit
fbc1e296b2
73
bench/Xfer4fBench.cpp
Normal file
73
bench/Xfer4fBench.cpp
Normal file
@ -0,0 +1,73 @@
|
||||
|
||||
/*
|
||||
* 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 "Benchmark.h"
|
||||
#include "SkString.h"
|
||||
#include "SkXfer4f.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);
|
||||
fName.printf("xfer4f_%s_%c_%s_%s", name, fDoN ? 'N' : '1',
|
||||
(flags & kSrcIsOpaque_SkXfer4fFlag) ? "opaque" : "alpha",
|
||||
(flags & kDstIsSRGB_SkXfer4fFlag) ? "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;
|
||||
fDst[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
SkString fName;
|
||||
SkPM4fXfer1Proc fProc1;
|
||||
SkPM4fXferNProc fProcN;
|
||||
bool fDoN;
|
||||
|
||||
enum {
|
||||
N = 1000,
|
||||
};
|
||||
SkPM4f fSrc[N];
|
||||
SkPMColor fDst[N];
|
||||
|
||||
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); )
|
||||
|
||||
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); )
|
83
gm/xfer4f.cpp
Normal file
83
gm/xfer4f.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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 "SkXfer4f.h"
|
||||
|
||||
static void draw_rect(SkCanvas* canvas, const SkRect& r, SkColor c, SkColorProfileType profile) {
|
||||
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 |= kSrcIsOpaque_SkXfer4fFlag;
|
||||
}
|
||||
if (kSRGB_SkColorProfileType == profile) {
|
||||
flags |= kDstIsSRGB_SkXfer4fFlag;
|
||||
}
|
||||
|
||||
const SkPM4f src = SkPM4f::FromPMColor(SkPreMultiplyColor(c));
|
||||
auto proc1 = SkPM4fXfer1ProcFactory(SkXfermode::kSrcOver_Mode, flags);
|
||||
for (int y = 0; y < ir.height()/2; ++y) {
|
||||
proc1(pm.writable_addr32(0, y), src, ir.width());
|
||||
}
|
||||
|
||||
SkPM4f srcRow[1000];
|
||||
for (int i = 0; i < ir.width(); ++i) {
|
||||
srcRow[i] = src;
|
||||
}
|
||||
auto procN = SkPM4fXferNProcFactory(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());
|
||||
}
|
||||
|
||||
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, 380) {
|
||||
const SkScalar W = 50;
|
||||
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
|
||||
};
|
||||
canvas->translate(20, 20);
|
||||
|
||||
const SkRect r = SkRect::MakeWH(W, H);
|
||||
for (auto profile : profiles) {
|
||||
canvas->save();
|
||||
for (SkColor c : colors) {
|
||||
if (profile < 0) {
|
||||
SkPaint p;
|
||||
p.setColor(c);
|
||||
canvas->drawRect(r, p);
|
||||
} else {
|
||||
draw_rect(canvas, r, c, (SkColorProfileType)profile);
|
||||
}
|
||||
canvas->translate(W + 20, 0);
|
||||
}
|
||||
canvas->restore();
|
||||
canvas->translate(0, H + 20);
|
||||
}
|
||||
}
|
@ -293,6 +293,7 @@
|
||||
'<(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/SkXfermode_proccoeff.h',
|
||||
'<(skia_src_path)/core/SkXfermodeInterpretation.cpp',
|
||||
|
@ -110,8 +110,7 @@ SK_API void SkRGBToHSV(U8CPU red, U8CPU green, U8CPU blue, SkScalar hsv[3]);
|
||||
@param color the argb color to convert. Note: the alpha component is ignored.
|
||||
@param hsv 3 element array which holds the resulting HSV components.
|
||||
*/
|
||||
static inline void SkColorToHSV(SkColor color, SkScalar hsv[3])
|
||||
{
|
||||
static inline void SkColorToHSV(SkColor color, SkScalar hsv[3]) {
|
||||
SkRGBToHSV(SkColorGetR(color), SkColorGetG(color), SkColorGetB(color), hsv);
|
||||
}
|
||||
|
||||
@ -134,8 +133,7 @@ SK_API SkColor SkHSVToColor(U8CPU alpha, const SkScalar hsv[3]);
|
||||
@param hsv 3 element array which holds the input HSV components.
|
||||
@return the resulting argb color
|
||||
*/
|
||||
static inline SkColor SkHSVToColor(const SkScalar hsv[3])
|
||||
{
|
||||
static inline SkColor SkHSVToColor(const SkScalar hsv[3]) {
|
||||
return SkHSVToColor(0xFF, hsv);
|
||||
}
|
||||
|
||||
@ -166,11 +164,19 @@ typedef SkPMColor (*SkXfermodeProc)(SkPMColor src, SkPMColor dst);
|
||||
* The float values are 0...1 premultiplied
|
||||
*/
|
||||
struct SkPM4f {
|
||||
enum {
|
||||
A = SK_A32_SHIFT/8,
|
||||
R = SK_R32_SHIFT/8,
|
||||
G = SK_G32_SHIFT/8,
|
||||
B = SK_B32_SHIFT/8,
|
||||
};
|
||||
float fVec[4];
|
||||
|
||||
float a() const { return fVec[SK_A32_SHIFT/8]; }
|
||||
float a() const { return fVec[3]; }
|
||||
|
||||
static SkPM4f FromPMColor(SkPMColor);
|
||||
|
||||
bool isUnit() const;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -141,3 +141,8 @@ SkPM4f SkColor4f::premul() const {
|
||||
dst.store(pm4.fVec);
|
||||
return pm4;
|
||||
}
|
||||
|
||||
bool SkPM4f::isUnit() const {
|
||||
auto c4 = Sk4f::Load(fVec);
|
||||
return (c4 >= Sk4f(0)).allTrue() && (c4 <= Sk4f(1)).allTrue();
|
||||
}
|
||||
|
121
src/core/SkPM4fPriv.h
Normal file
121
src/core/SkPM4fPriv.h
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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 "SkColorPriv.h"
|
||||
#include "SkNx.h"
|
||||
|
||||
static inline float get_alpha(const Sk4f& f4) {
|
||||
return f4.kth<SkPM4f::A>();
|
||||
}
|
||||
|
||||
static inline Sk4f set_alpha(const Sk4f& f4, float alpha) {
|
||||
static_assert(3 == SkPM4f::A, "");
|
||||
return Sk4f(f4.kth<0>(), f4.kth<1>(), f4.kth<2>(), alpha);
|
||||
}
|
||||
|
||||
static inline uint32_t to_4b(const Sk4f& f4) {
|
||||
uint32_t b4;
|
||||
SkNx_cast<uint8_t>(f4).store((uint8_t*)&b4);
|
||||
return b4;
|
||||
}
|
||||
|
||||
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) {
|
||||
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 Sk4f_fromL32(uint32_t src) {
|
||||
return to_4f(src) * Sk4f(1.0f/255);
|
||||
}
|
||||
|
||||
static inline Sk4f Sk4f_fromS32(uint32_t src) {
|
||||
return s2l(to_4f(src) * Sk4f(1.0f/255));
|
||||
}
|
||||
|
||||
static inline uint32_t Sk4f_toL32(const Sk4f& x4) {
|
||||
return to_4b(x4 * Sk4f(255) + Sk4f(0.5f));
|
||||
}
|
||||
|
||||
static inline uint32_t Sk4f_toS32(const Sk4f& x4) {
|
||||
return to_4b(l2s(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)));
|
||||
}
|
||||
}
|
||||
|
134
src/core/SkXfer4f.cpp
Normal file
134
src/core/SkXfer4f.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
24
src/core/SkXfer4f.h
Normal file
24
src/core/SkXfer4f.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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
|
Loading…
Reference in New Issue
Block a user