/*
 * 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 "SkLights.h"
#include "SkPoint3.h"
#include "SkRadialShadowMapShader.h"

////////////////////////////////////////////////////////////////////////////
#ifdef SK_EXPERIMENTAL_SHADOWING


/** \class SkRadialShadowMapShaderImpl
    This subclass of shader applies shadowing radially around a light
*/
class SkRadialShadowMapShaderImpl : public SkShader {
public:
    /** Create a new shadowing shader that shadows radially around a light
    */
    SkRadialShadowMapShaderImpl(sk_sp<SkShader> occluderShader,
                                sk_sp<SkLights> lights,
                                int diffuseWidth, int diffuseHeight)
        : fOccluderShader(std::move(occluderShader))
        , fLight(std::move(lights))
        , fWidth(diffuseWidth)
        , fHeight(diffuseHeight) { }

    bool isOpaque() const override;

#if SK_SUPPORT_GPU
    sk_sp<GrFragmentProcessor> asFragmentProcessor(const AsFPArgs&) const override;
#endif

    class ShadowMapRadialShaderContext : public SkShader::Context {
    public:
        // The context takes ownership of the states. It will call their destructors
        // but will NOT free the memory.
        ShadowMapRadialShaderContext(const SkRadialShadowMapShaderImpl&, const ContextRec&,
                                 SkShader::Context* occluderContext,
                                 void* heapAllocated);

        ~ShadowMapRadialShaderContext() override;

        void shadeSpan(int x, int y, SkPMColor[], int count) override;

        uint32_t getFlags() const override { return fFlags; }

    private:
        SkShader::Context*        fOccluderContext;
        uint32_t                  fFlags;

        void* fHeapAllocated;

        typedef SkShader::Context INHERITED;
    };

    SK_TO_STRING_OVERRIDE()
    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkRadialShadowMapShaderImpl)

protected:
    void flatten(SkWriteBuffer&) const override;
    size_t onContextSize(const ContextRec&) const override;
    Context* onCreateContext(const ContextRec&, void*) const override;

private:
    sk_sp<SkShader> fOccluderShader;
    sk_sp<SkLights> fLight;

    int fWidth;
    int fHeight;

    friend class SkRadialShadowMapShader;

    typedef SkShader INHERITED;
};

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

#if SK_SUPPORT_GPU

#include "GrContext.h"
#include "GrCoordTransform.h"
#include "GrFragmentProcessor.h"
#include "glsl/GrGLSLFragmentProcessor.h"
#include "glsl/GrGLSLFragmentShaderBuilder.h"
#include "SkGr.h"
#include "SkImage_Base.h"
#include "GrInvariantOutput.h"
#include "SkSpecialImage.h"

class RadialShadowMapFP : public GrFragmentProcessor {
public:
    RadialShadowMapFP(sk_sp<GrFragmentProcessor> occluder,
                      sk_sp<SkLights> light,
                      int diffuseWidth, int diffuseHeight,
                      GrContext* context) {
        fLightPos = light->light(0).pos();

        fWidth = diffuseWidth;
        fHeight = diffuseHeight;

        this->registerChildProcessor(std::move(occluder));
        this->initClassID<RadialShadowMapFP>();
    }

    class GLSLRadialShadowMapFP : public GrGLSLFragmentProcessor {
    public:
        GLSLRadialShadowMapFP() { }

        void emitCode(EmitArgs& args) override {

            GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;

            const char* lightPosUniName = nullptr;

            fLightPosUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                      kVec3f_GrSLType,
                                                      kDefault_GrSLPrecision,
                                                      "lightPos",
                                                      &lightPosUniName);

            const char* widthUniName = nullptr;
            const char* heightUniName = nullptr;

            fWidthUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                   kInt_GrSLType,
                                                   kDefault_GrSLPrecision,
                                                   "width", &widthUniName);
            fHeightUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
                                                    kInt_GrSLType,
                                                    kDefault_GrSLPrecision,
                                                    "height", &heightUniName);


            SkString occluder("occluder");
            this->emitChild(0, nullptr, &occluder, args);

            // Modify the input texture coordinates to index into our 1D output
            fragBuilder->codeAppend("float distHere;");

            // we use a max shadow distance of 2 times the max of width/height
            fragBuilder->codeAppend("float closestDistHere = 2;");
            fragBuilder->codeAppend("vec2 coords = vMatrixCoord_0_0_Stage0;");
            fragBuilder->codeAppend("coords.y = 0;");
            fragBuilder->codeAppend("vec2 destCoords = vec2(0,0);");
            fragBuilder->codeAppendf("float step = 1.0 / %s;", heightUniName);

            // assume that we are at 0, 0 light pos
            // TODO use correct light positions

            // this goes through each depth value in the final output buffer,
            // basically raycasting outwards, and finding the first collision.
            // we also increment coords.y to 2 instead 1 so our shadows stretch the whole screen.
            fragBuilder->codeAppendf("for (coords.y = 0; coords.y <= 2; coords.y += step) {");

                fragBuilder->codeAppend("float theta = (coords.x * 2.0 - 1.0) * 3.1415;");
                fragBuilder->codeAppend("float r = coords.y;");
                fragBuilder->codeAppend("destCoords = "
                        "vec2(r * cos(theta), - r * sin(theta)) /2.0 + 0.5;");
                fragBuilder->codeAppendf("vec2 lightOffset = (vec2(%s)/vec2(%s,%s) - 0.5)"
                                                            "* vec2(1.0, 1.0);",
                                         lightPosUniName, widthUniName, heightUniName);

                fragBuilder->codeAppend("distHere = texture(uTextureSampler0_Stage1,"
                                                           "destCoords + lightOffset).b;");
                fragBuilder->codeAppend("if (distHere > 0.0) {"
                                            "closestDistHere = coords.y;"
                                        "break;}");
            fragBuilder->codeAppend("}");

            fragBuilder->codeAppendf("%s = vec4(vec3(closestDistHere / 2.0),1);", args.fOutputColor);
        }

        static void GenKey(const GrProcessor& proc, const GrShaderCaps&,
                           GrProcessorKeyBuilder* b) {
            b->add32(0); // nothing to add here
        }

    protected:
        void onSetData(const GrGLSLProgramDataManager& pdman, const GrProcessor& proc) override {
            const RadialShadowMapFP &radialShadowMapFP = proc.cast<RadialShadowMapFP>();

            const SkVector3& lightPos = radialShadowMapFP.lightPos();
            if (lightPos != fLightPos) {
                pdman.set3fv(fLightPosUni, 1, &lightPos.fX);
                fLightPos = lightPos;
            }

            int width = radialShadowMapFP.width();
            if (width != fWidth) {
                pdman.set1i(fWidthUni, width);
                fWidth = width;
            }
            int height = radialShadowMapFP.height();
            if (height != fHeight) {
                pdman.set1i(fHeightUni, height);
                fHeight = height;
            }
        }

    private:
        SkVector3 fLightPos;
        GrGLSLProgramDataManager::UniformHandle fLightPosUni;

        int fWidth;
        GrGLSLProgramDataManager::UniformHandle fWidthUni;
        int fHeight;
        GrGLSLProgramDataManager::UniformHandle fHeightUni;
    };

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

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

    const SkVector3& lightPos() const {
        return fLightPos;
    }

    int width() const { return fWidth; }
    int height() const { return fHeight; }

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

    bool onIsEqual(const GrFragmentProcessor& proc) const override {
        const RadialShadowMapFP& radialShadowMapFP = proc.cast<RadialShadowMapFP>();

        if (fWidth != radialShadowMapFP.fWidth || fHeight != radialShadowMapFP.fHeight) {
            return false;
        }

        if (fLightPos != radialShadowMapFP.fLightPos) {
            return false;
        }

        return true;
    }

    SkVector3        fLightPos;

    int              fHeight;
    int              fWidth;
};

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

sk_sp<GrFragmentProcessor> SkRadialShadowMapShaderImpl::asFragmentProcessor
        (const AsFPArgs& fpargs) const {

    sk_sp<GrFragmentProcessor> occluderFP = fOccluderShader->asFragmentProcessor(fpargs);

    sk_sp<GrFragmentProcessor> shadowFP = sk_make_sp<RadialShadowMapFP>(std::move(occluderFP),
                                                                        fLight, fWidth, fHeight,
                                                                        fpargs.fContext);
    return shadowFP;
}

#endif

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

bool SkRadialShadowMapShaderImpl::isOpaque() const {
    return fOccluderShader->isOpaque();
}

SkRadialShadowMapShaderImpl::ShadowMapRadialShaderContext::ShadowMapRadialShaderContext(
        const SkRadialShadowMapShaderImpl& shader, const ContextRec& rec,
        SkShader::Context* occluderContext,
        void* heapAllocated)
        : INHERITED(shader, rec)
        , fOccluderContext(occluderContext)
        , fHeapAllocated(heapAllocated) {
    bool isOpaque = shader.isOpaque();

    // update fFlags
    uint32_t flags = 0;
    if (isOpaque && (255 == this->getPaintAlpha())) {
        flags |= kOpaqueAlpha_Flag;
    }

    fFlags = flags;
}

SkRadialShadowMapShaderImpl::ShadowMapRadialShaderContext::~ShadowMapRadialShaderContext() {
    // The dependencies have been created outside of the context on memory that was allocated by
    // the onCreateContext() method. Call the destructors and free the memory.
    fOccluderContext->~Context();

    sk_free(fHeapAllocated);
}

static inline SkPMColor convert(SkColor3f color, U8CPU a) {
    if (color.fX <= 0.0f) {
        color.fX = 0.0f;
    } else if (color.fX >= 255.0f) {
        color.fX = 255.0f;
    }

    if (color.fY <= 0.0f) {
        color.fY = 0.0f;
    } else if (color.fY >= 255.0f) {
        color.fY = 255.0f;
    }

    if (color.fZ <= 0.0f) {
        color.fZ = 0.0f;
    } else if (color.fZ >= 255.0f) {
        color.fZ = 255.0f;
    }

    return SkPreMultiplyARGB(a, (int) color.fX,  (int) color.fY, (int) color.fZ);
}

// larger is better (fewer times we have to loop), but we shouldn't
// take up too much stack-space (each one here costs 16 bytes)
#define BUFFER_MAX 16
void SkRadialShadowMapShaderImpl::ShadowMapRadialShaderContext::shadeSpan
        (int x, int y, SkPMColor result[], int count) {
    do {
        int n = SkTMin(count, BUFFER_MAX);

        // just fill with white for now
        SkPMColor accum = convert(SkColor3f::Make(1.0f, 1.0f, 1.0f), 0xFF);

        for (int i = 0; i < n; ++i) {
            result[i] = accum;
        }

        result += n;
        x += n;
        count -= n;
    } while (count > 0);
}

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

#ifndef SK_IGNORE_TO_STRING
void SkRadialShadowMapShaderImpl::toString(SkString* str) const {
    str->appendf("RadialShadowMapShader: ()");
}
#endif

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

    // Discarding SkShader flattenable params
    bool hasLocalMatrix = buf.readBool();
    SkAssertResult(!hasLocalMatrix);

    sk_sp<SkLights> light = SkLights::MakeFromBuffer(buf);

    int diffuseWidth = buf.readInt();
    int diffuseHeight = buf.readInt();

    sk_sp<SkShader> occluderShader(buf.readFlattenable<SkShader>());

    return sk_make_sp<SkRadialShadowMapShaderImpl>(std::move(occluderShader),
                                                   std::move(light),
                                                   diffuseWidth, diffuseHeight);
}

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

    fLight->flatten(buf);

    buf.writeInt(fWidth);
    buf.writeInt(fHeight);

    buf.writeFlattenable(fOccluderShader.get());
}

size_t SkRadialShadowMapShaderImpl::onContextSize(const ContextRec& rec) const {
    return sizeof(ShadowMapRadialShaderContext);
}

SkShader::Context* SkRadialShadowMapShaderImpl::onCreateContext(const ContextRec& rec,
                                                                void* storage) const {
    size_t heapRequired = fOccluderShader->contextSize(rec);

    void* heapAllocated = sk_malloc_throw(heapRequired);

    void* occluderContextStorage = heapAllocated;

    SkShader::Context* occluderContext =
            fOccluderShader->createContext(rec, occluderContextStorage);

    if (!occluderContext) {
        sk_free(heapAllocated);
        return nullptr;
    }

    return new (storage) ShadowMapRadialShaderContext(*this, rec, occluderContext, heapAllocated);
}

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

sk_sp<SkShader> SkRadialShadowMapShader::Make(sk_sp<SkShader> occluderShader,
                                              sk_sp<SkLights> light,
                                              int diffuseWidth, int diffuseHeight) {
    if (!occluderShader) {
        // TODO: Use paint's color in absence of a diffuseShader
        // TODO: Use a default implementation of normalSource instead
        return nullptr;
    }

    return sk_make_sp<SkRadialShadowMapShaderImpl>(std::move(occluderShader),
                                                   std::move(light),
                                                   diffuseWidth, diffuseHeight);
}

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

SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkRadialShadowMapShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRadialShadowMapShaderImpl)
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END

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

#endif
