/*
 * 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 "SkNormalBevelSource.h"

#include "SkNormalSource.h"
#include "SkNormalSourcePriv.h"
#include "SkPoint3.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"

#if SK_SUPPORT_GPU
#include "GrInvariantOutput.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "SkGr.h"

class NormalBevelFP : public GrFragmentProcessor {
public:
    NormalBevelFP(SkNormalSource::BevelType type, SkScalar width, SkScalar height)
        : fType(type)
        , fWidth(width)
        , fHeight(height) {
        this->initClassID<NormalBevelFP>();

        fUsesDistanceVectorField = true;
    }

    class GLSLNormalBevelFP : public GLSLNormalFP {
    public:
        GLSLNormalBevelFP() {
            fPrevWidth = SkFloatToScalar(0.0f);
            fPrevHeight = SkFloatToScalar(0.0f);
        }

        void onEmitCode(EmitArgs& args) override {
            GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

            const char* widthUniName = nullptr;
            fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
                    kDefault_GrSLPrecision, "Width", &widthUniName);

            const char* heightUniName = nullptr;
            fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType,
                    kDefault_GrSLPrecision, "Height", &heightUniName);

            fragBuilder->codeAppendf("%s = vec4(0.0, 0.0, 1.0, 0.0);", args.fOutputColor);
        }

        static void GenKey(const GrProcessor& proc, const GrGLSLCaps&,
                           GrProcessorKeyBuilder* b) {
            const NormalBevelFP& fp = proc.cast<NormalBevelFP>();
            b->add32(static_cast<int>(fp.fType));
        }

    protected:
        void setNormalData(const GrGLSLProgramDataManager& pdman,
                           const GrProcessor& proc) override {
            const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>();

            if (fPrevWidth  != normalBevelFP.fWidth) {
                pdman.set1f(fWidthUni, normalBevelFP.fWidth);
                fPrevWidth = normalBevelFP.fWidth;
            }
            if (fPrevHeight != normalBevelFP.fHeight) {
                pdman.set1f(fHeightUni, normalBevelFP.fHeight);
                fPrevHeight = normalBevelFP.fHeight;
            }
        }

    private:
        SkScalar fPrevWidth;
        GrGLSLProgramDataManager::UniformHandle fWidthUni;

        SkScalar fPrevHeight;
        GrGLSLProgramDataManager::UniformHandle fHeightUni;
    };

    void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
        GLSLNormalBevelFP::GenKey(*this, caps, b);
    }

    const char* name() const override { return "NormalBevelFP"; }

    void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
        inout->setToUnknown(GrInvariantOutput::ReadInput::kWillNot_ReadInput);
    }

private:
    GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { return new GLSLNormalBevelFP; }

    bool onIsEqual(const GrFragmentProcessor& proc) const override {
        const NormalBevelFP& normalBevelFP = proc.cast<NormalBevelFP>();
        return fType   == normalBevelFP.fType &&
               fWidth  == normalBevelFP.fWidth &&
               fHeight == normalBevelFP.fHeight;
    }

    SkNormalSource::BevelType fType;
    SkScalar fWidth;
    SkScalar fHeight;
};

sk_sp<GrFragmentProcessor> SkNormalBevelSourceImpl::asFragmentProcessor(
        const SkShader::AsFPArgs&) const {

    return sk_make_sp<NormalBevelFP>(fType, fWidth, fHeight);
}

#endif // SK_SUPPORT_GPU

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

SkNormalBevelSourceImpl::Provider::Provider() {}

SkNormalBevelSourceImpl::Provider::~Provider() {}

SkNormalSource::Provider* SkNormalBevelSourceImpl::asProvider(const SkShader::ContextRec &rec,
                                                            void *storage) const {
    return new (storage) Provider();
}

size_t SkNormalBevelSourceImpl::providerSize(const SkShader::ContextRec&) const {
    return sizeof(Provider);
}

void SkNormalBevelSourceImpl::Provider::fillScanLine(int x, int y, SkPoint3 output[],
                                                   int count) const {
    for (int i = 0; i < count; i++) {
        output[i] = {0.0f, 0.0f, 1.0f};
    }
}

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

sk_sp<SkFlattenable> SkNormalBevelSourceImpl::CreateProc(SkReadBuffer& buf) {

    auto type = static_cast<SkNormalSource::BevelType>(buf.readInt());
    SkScalar width = buf.readScalar();
    SkScalar height = buf.readScalar();

    return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height);
}

void SkNormalBevelSourceImpl::flatten(SkWriteBuffer& buf) const {
    this->INHERITED::flatten(buf);

    buf.writeInt(static_cast<int>(fType));
    buf.writeScalar(fWidth);
    buf.writeScalar(fHeight);
}

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

sk_sp<SkNormalSource> SkNormalSource::MakeBevel(BevelType type, SkScalar width, SkScalar height) {
    /* TODO make sure this checks are tolerant enough to account for loss of conversion when GPUs
       use 16-bit float types. We don't want to assume stuff is non-zero on the GPU and be wrong.*/
    SkASSERT(width > 0.0f && !SkScalarNearlyZero(width));
    if (SkScalarNearlyZero(height)) {
        return SkNormalSource::MakeFlat();
    }

    return sk_make_sp<SkNormalBevelSourceImpl>(type, width, height);
}
