/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkArenaAlloc.h"
#include "SkBlendModePriv.h"
#include "SkComposeShader.h"
#include "SkColorFilter.h"
#include "SkColorData.h"
#include "SkColorShader.h"
#include "SkRasterPipeline.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkString.h"

sk_sp<SkShader> SkShader::MakeCompose(sk_sp<SkShader> dst, sk_sp<SkShader> src, SkBlendMode mode,
                                      float lerpT) {
    if (!src || !dst || SkScalarIsNaN(lerpT)) {
        return nullptr;
    }
    lerpT = SkScalarPin(lerpT, 0, 1);

    if (lerpT == 0) {
        return dst;
    } else if (lerpT == 1) {
        if (mode == SkBlendMode::kSrc) {
            return src;
        }
        if (mode == SkBlendMode::kDst) {
            return dst;
        }
    }
    return sk_sp<SkShader>(new SkComposeShader(std::move(dst), std::move(src), mode, lerpT));
}

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

sk_sp<SkFlattenable> SkComposeShader::CreateProc(SkReadBuffer& buffer) {
    sk_sp<SkShader> dst(buffer.readShader());
    sk_sp<SkShader> src(buffer.readShader());
    unsigned        mode = buffer.read32();
    float           lerp = buffer.readScalar();

    // check for valid mode before we cast to the enum type
    if (!buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode)) {
        return nullptr;
    }
    return MakeCompose(std::move(dst), std::move(src), static_cast<SkBlendMode>(mode), lerp);
}

void SkComposeShader::flatten(SkWriteBuffer& buffer) const {
    buffer.writeFlattenable(fDst.get());
    buffer.writeFlattenable(fSrc.get());
    buffer.write32((int)fMode);
    buffer.writeScalar(fLerpT);
}

sk_sp<SkShader> SkComposeShader::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
    return MakeCompose(xformer->apply(fDst.get()), xformer->apply(fSrc.get()),
                       fMode, fLerpT);
}

#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
bool SkComposeShader::asACompose(ComposeRec* rec) const {
    if (!this->isJustMode()) {
        return false;
    }

    if (rec) {
        rec->fShaderA   = fDst.get();
        rec->fShaderB   = fSrc.get();
        rec->fBlendMode = fMode;
    }
    return true;
}
#endif

bool SkComposeShader::onAppendStages(const StageRec& rec) const {
    struct Storage {
        float   fRGBA[4 * SkRasterPipeline_kMaxStride];
        float   fAlpha;
    };
    auto storage = rec.fAlloc->make<Storage>();

    if (!as_SB(fSrc)->appendStages(rec)) {
        return false;
    }
    // This outputs r,g,b,a, which we'll need later when we apply the mode, but we save it off now
    // since fShaderB will overwrite them.
    rec.fPipeline->append(SkRasterPipeline::store_rgba, storage->fRGBA);

    if (!as_SB(fDst)->appendStages(rec)) {
        return false;
    }
    // We now have our logical 'dst' in r,g,b,a, but we need it in dr,dg,db,da for the mode/lerp
    // so we have to shuttle them. If we had a stage the would load_into_dst, then we could
    // reverse the two shader invocations, and avoid this move...
    rec.fPipeline->append(SkRasterPipeline::move_src_dst);
    rec.fPipeline->append(SkRasterPipeline::load_rgba, storage->fRGBA);

    if (!this->isJustLerp()) {
        SkBlendMode_AppendStages(fMode, rec.fPipeline);
    }
    if (!this->isJustMode()) {
        rec.fPipeline->append(SkRasterPipeline::lerp_1_float, &fLerpT);
    }
    return true;
}

#if SK_SUPPORT_GPU

#include "effects/GrConstColorProcessor.h"
#include "effects/GrXfermodeFragmentProcessor.h"

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

std::unique_ptr<GrFragmentProcessor> SkComposeShader::asFragmentProcessor(
        const GrFPArgs& args) const {
    if (this->isJustMode()) {
        SkASSERT(fMode != SkBlendMode::kSrc && fMode != SkBlendMode::kDst); // caught in factory
        if (fMode == SkBlendMode::kClear) {
            return GrConstColorProcessor::Make(SK_PMColor4fTRANSPARENT,
                                               GrConstColorProcessor::InputMode::kIgnore);
        }
    }

    std::unique_ptr<GrFragmentProcessor> fpA(as_SB(fDst)->asFragmentProcessor(args));
    if (!fpA) {
        return nullptr;
    }
    std::unique_ptr<GrFragmentProcessor> fpB(as_SB(fSrc)->asFragmentProcessor(args));
    if (!fpB) {
        return nullptr;
    }
    // TODO: account for fLerpT when it is < 1
    return GrXfermodeFragmentProcessor::MakeFromTwoProcessors(std::move(fpB),
                                                              std::move(fpA), fMode);
}
#endif
