 Chromium Code Reviews
 Chromium Code Reviews Issue 1642703003:
  starter procs for blending with pm4f  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master
    
  
    Issue 1642703003:
  starter procs for blending with pm4f  (Closed) 
  Base URL: https://skia.googlesource.com/skia.git@master| Index: src/core/SkXfer4f.cpp | 
| diff --git a/src/core/SkXfer4f.cpp b/src/core/SkXfer4f.cpp | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..b177e49b18d972d6cd325096f9a7c4948604aa04 | 
| --- /dev/null | 
| +++ b/src/core/SkXfer4f.cpp | 
| @@ -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) { | 
| 
mtklein
2016/01/29 15:23:00
pm41p / pm4np is a bit beyond my readability decry
 | 
| + 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); | 
| 
mtklein
2016/01/29 15:41:31
I think if we break these problems apart into inde
 | 
| + } | 
| + | 
| + 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)); | 
| 
mtklein
2016/01/29 15:23:00
Add the half to s4 outside the loop too?
 | 
| + } | 
| + } | 
| +} | 
| + | 
| +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 { | 
| 
mtklein
2016/01/29 15:23:00
This struct seems a little dangerous without an an
 | 
| + SkPM4fXfer1Proc fProc1; | 
| + SkPM4fXferNProc fProcN; | 
| +}; | 
| + | 
| +const Pair gClearPairs[] = { | 
| 
mtklein
2016/01/29 15:23:00
static for all these too?
 | 
| + { 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; | 
| 
mtklein
2016/01/29 15:23:00
I think you've missed some breaks?
 | 
| + 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]; | 
| 
mtklein
2016/01/29 15:23:00
I think this could be a lot simpler if we return P
 | 
| +} | 
| + | 
| +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; | 
| +} |