/*
 * 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 "SkHalf.h"
#include "SkPM4fPriv.h"
#include "SkUtils.h"
#include "SkXfermode.h"

static Sk4f lerp_by_coverage(const Sk4f& src, const Sk4f& dst, uint8_t srcCoverage) {
    return dst + (src - dst) * Sk4f(srcCoverage * (1/255.0f));
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static void xfer_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 = SkHalfToFloat_finite(dst[i]);
            d4.store(d.fVec);
            Sk4f r4 = Sk4f::Load(proc(*src, d).fVec);
            SkFloatToHalf_finite(lerp_by_coverage(r4, d4, aa[i])).store(&dst[i]);
        }
    } else {
        for (int i = 0; i < count; ++i) {
            SkHalfToFloat_finite(dst[i]).store(d.fVec);
            Sk4f r4 = Sk4f::Load(proc(*src, d).fVec);
            SkFloatToHalf_finite(r4).store(&dst[i]);
        }
    }
}

static void xfer_n(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 = SkHalfToFloat_finite(dst[i]);
            d4.store(d.fVec);
            Sk4f r4 = Sk4f::Load(proc(src[i], d).fVec);
            SkFloatToHalf_finite(lerp_by_coverage(r4, d4, aa[i])).store(&dst[i]);
        }
    } else {
        for (int i = 0; i < count; ++i) {
            SkHalfToFloat_finite(dst[i]).store(d.fVec);
            Sk4f r4 = Sk4f::Load(proc(src[i], d).fVec);
            SkFloatToHalf_finite(r4).store(&dst[i]);
        }
    }
}

const SkXfermode::F16Proc gProcs_General[] = { xfer_n, xfer_n, xfer_1, xfer_1 };

///////////////////////////////////////////////////////////////////////////////////////////////////

static 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 = SkHalfToFloat_finite(dst[i]);
                SkFloatToHalf_finite(d4 * Sk4f((255 - aa[i]) * 1.0f/255)).store(&dst[i]);
            }
        }
    } else {
        sk_memset64(dst, 0, count);
    }
}

const SkXfermode::F16Proc gProcs_Clear[] = { clear, clear, clear, clear };

///////////////////////////////////////////////////////////////////////////////////////////////////

static void src_1(const SkXfermode*, uint64_t dst[], const SkPM4f* src, int count,
                  const SkAlpha aa[]) {
    const Sk4f s4 = Sk4f::Load(src->fVec);
    if (aa) {
        for (int i = 0; i < count; ++i) {
            const Sk4f d4 = SkHalfToFloat_finite(dst[i]);
            SkFloatToHalf_finite(lerp_by_coverage(s4, d4, aa[i])).store(&dst[i]);
        }
    } else {
        uint64_t s4h;
        SkFloatToHalf_finite(s4).store(&s4h);
        sk_memset64(dst, s4h, count);
    }
}

static 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) {
            const Sk4f s4 = Sk4f::Load(src[i].fVec);
            const Sk4f d4 = SkHalfToFloat_finite(dst[i]);
            SkFloatToHalf_finite(lerp_by_coverage(s4, d4, aa[i])).store(&dst[i]);
        }
    } else {
        for (int i = 0; i < count; ++i) {
            const Sk4f s4 = Sk4f::Load(src[i].fVec);
            SkFloatToHalf_finite(s4).store(&dst[i]);
        }
    }
}

const SkXfermode::F16Proc gProcs_Src[] = { src_n, src_n, src_1,  src_1 };

///////////////////////////////////////////////////////////////////////////////////////////////////

static void dst(const SkXfermode*, uint64_t*, const SkPM4f*, int count, const SkAlpha[]) {}

const SkXfermode::F16Proc gProcs_Dst[] = { dst, dst, dst, dst };

///////////////////////////////////////////////////////////////////////////////////////////////////

static void srcover_1(const SkXfermode*, uint64_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));
    for (int i = 0; i < count; ++i) {
        const Sk4f d4 = SkHalfToFloat_finite(dst[i]);
        const Sk4f r4 = s4 + d4 * dst_scale;
        if (aa) {
            SkFloatToHalf_finite(lerp_by_coverage(r4, d4, aa[i])).store(&dst[i]);
        } else {
            SkFloatToHalf_finite(r4).store(&dst[i]);
        }
    }
}

static void srcover_n(const SkXfermode*, uint64_t dst[], const SkPM4f src[], int count,
                      const SkAlpha aa[]) {
    for (int i = 0; i < count; ++i) {
        Sk4f s = Sk4f::Load(src+i),
             d = SkHalfToFloat_finite(dst[i]),
             r = s + d*(1.0f - SkNx_shuffle<3,3,3,3>(s));
        if (aa) {
            r = lerp_by_coverage(r, d, aa[i]);
        }
        SkFloatToHalf_finite(r).store(&dst[i]);
    }
}

const SkXfermode::F16Proc gProcs_SrcOver[] = { srcover_n, src_n, srcover_1, src_1 };

///////////////////////////////////////////////////////////////////////////////////////////////////

static SkXfermode::F16Proc find_proc(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 gProcs_General[flags];
}

SkXfermode::F16Proc SkXfermode::onGetF16Proc(uint32_t flags) const {
    SkASSERT(0 == (flags & ~3));
    flags &= 3;

    Mode mode;
    return this->asMode(&mode) ? find_proc(mode, flags) : gProcs_General[flags];
}

SkXfermode::F16Proc SkXfermode::GetF16Proc(SkXfermode* xfer, uint32_t flags) {
    return xfer ? xfer->onGetF16Proc(flags) : find_proc(SkXfermode::kSrcOver_Mode, flags);
}
