/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkColorFilter.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRSXform.h"
#include "src/core/SkBlendModePriv.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkColorSpaceXformSteps.h"
#include "src/core/SkCoreBlitters.h"
#include "src/core/SkDraw.h"
#include "src/core/SkMatrixProvider.h"
#include "src/core/SkRasterClip.h"
#include "src/core/SkRasterPipeline.h"
#include "src/core/SkScan.h"
#include "src/core/SkScan.h"
#include "src/core/SkVM.h"
#include "src/core/SkVMBlitter.h"
#include "src/shaders/SkComposeShader.h"
#include "src/shaders/SkShaderBase.h"

static void fill_rect(const SkMatrix& ctm, const SkRasterClip& rc,
                      const SkRect& r, SkBlitter* blitter, SkPath* scratchPath) {
    if (ctm.rectStaysRect()) {
        SkRect dr;
        ctm.mapRect(&dr, r);
        SkScan::FillRect(dr, rc, blitter);
    } else {
        SkPoint pts[4];
        r.toQuad(pts);
        ctm.mapPoints(pts, pts, 4);

        scratchPath->rewind();
        scratchPath->addPoly(pts, 4, true);
        SkScan::FillPath(*scratchPath, rc, blitter);
    }
}

static void load_color(SkRasterPipeline_UniformColorCtx* ctx, const float rgba[]) {
    // only need one of these. can I query the pipeline to know if its lowp or highp?
    ctx->rgba[0] = SkScalarRoundToInt(rgba[0]*255); ctx->r = rgba[0];
    ctx->rgba[1] = SkScalarRoundToInt(rgba[1]*255); ctx->g = rgba[1];
    ctx->rgba[2] = SkScalarRoundToInt(rgba[2]*255); ctx->b = rgba[2];
    ctx->rgba[3] = SkScalarRoundToInt(rgba[3]*255); ctx->a = rgba[3];
}

extern bool gUseSkVMBlitter;

class UpdatableColorShader : public SkShaderBase {
public:
    explicit UpdatableColorShader(SkColorSpace* cs)
        : fSteps{sk_srgb_singleton(), kUnpremul_SkAlphaType, cs, kUnpremul_SkAlphaType} {}
    skvm::Color onProgram(
            skvm::Builder* builder, skvm::Coord device, skvm::Coord local, skvm::Color paint,
            const SkMatrixProvider& provider, const SkMatrix* localM, const SkColorInfo& dst,
            skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override {
        skvm::Uniform color = uniforms->pushPtr(fValues);
        skvm::F32 r = builder->arrayF(color, 0);
        skvm::F32 g = builder->arrayF(color, 1);
        skvm::F32 b = builder->arrayF(color, 2);
        skvm::F32 a = builder->arrayF(color, 3);

        return {r, g, b, a};
    }

    void updateColor(SkColor c) const {
        SkColor4f c4 = SkColor4f::FromColor(c);
        fSteps.apply(c4.vec());
        auto cp4 = c4.premul();
        fValues[0] = cp4.fR;
        fValues[1] = cp4.fG;
        fValues[2] = cp4.fB;
        fValues[3] = cp4.fA;
    }

private:
    // For serialization.  This will never be called.
    Factory getFactory() const override { return nullptr; }
    const char* getTypeName() const override { return nullptr; }

    SkColorSpaceXformSteps fSteps;
    mutable float fValues[4];
};

void SkDraw::drawAtlas(const SkRSXform xform[],
                       const SkRect textures[],
                       const SkColor colors[],
                       int count,
                       SkBlendMode bmode,
                       const SkPaint& paint) {
    sk_sp<SkShader> atlasShader = paint.refShader();
    if (!atlasShader) {
        return;
    }

    SkSTArenaAlloc<256> alloc;

    SkPaint p(paint);
    p.setAntiAlias(false);  // we never respect this for drawAtlas(or drawVertices)
    p.setStyle(SkPaint::kFill_Style);
    p.setShader(nullptr);
    p.setMaskFilter(nullptr);

    if (gUseSkVMBlitter) {
        auto updateShader = as_SB(atlasShader)->updatableShader(&alloc);
        UpdatableColorShader* colorShader = nullptr;
        SkShaderBase* shader = nullptr;
        if (colors) {
            colorShader = alloc.make<UpdatableColorShader>(fDst.colorSpace());
            shader = alloc.make<SkShader_Blend>(
                    bmode, sk_ref_sp(colorShader), sk_ref_sp(updateShader));
        } else {
            shader = as_SB(updateShader);
        }
        p.setShader(sk_ref_sp(shader));
        if (auto blitter = SkVMBlitter::Make(fDst, p,*fMatrixProvider, &alloc, fRC->clipShader())) {
            SkPath scratchPath;
            for (int i = 0; i < count; ++i) {
                if (colorShader) {
                    colorShader->updateColor(colors[i]);
                }

                SkMatrix mx;
                mx.setRSXform(xform[i]);
                mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
                mx.postConcat(fMatrixProvider->localToDevice());
                if (updateShader->update(mx)) {
                    fill_rect(mx, *fRC, textures[i], blitter, &scratchPath);
                }
            }
            return;
        }
    }  // gUseSkVMBlitter

    SkRasterPipeline pipeline(&alloc);
    SkStageRec rec = {
        &pipeline, &alloc, fDst.colorType(), fDst.colorSpace(), p, nullptr, *fMatrixProvider
    };

    SkStageUpdater* updator = as_SB(atlasShader.get())->appendUpdatableStages(rec);
    if (!updator) {
        SkDraw draw(*this);

        p.setShader(atlasShader);
        for (int i = 0; i < count; ++i) {
            if (colors) {
                p.setShader(SkShaders::Blend(bmode, SkShaders::Color(colors[i]), atlasShader));
            }
            SkMatrix mx;
            mx.setRSXform(xform[i]);
            mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
            SkPreConcatMatrixProvider matrixProvider(*fMatrixProvider, mx);
            draw.fMatrixProvider = &matrixProvider;
            draw.drawRect(textures[i], p);
        }
        return;
    }

    SkRasterPipeline_UniformColorCtx* uniformCtx = nullptr;
    SkColorSpaceXformSteps steps(sk_srgb_singleton(), kUnpremul_SkAlphaType,
                                 rec.fDstCS,          kUnpremul_SkAlphaType);

    if (colors) {
        // we will late-bind the values in ctx, once for each color in the loop
        uniformCtx = alloc.make<SkRasterPipeline_UniformColorCtx>();
        rec.fPipeline->append(SkRasterPipeline::uniform_color_dst, uniformCtx);
        SkBlendMode_AppendStages(bmode, rec.fPipeline);
    }

    bool isOpaque = !colors && atlasShader->isOpaque();
    if (p.getAlphaf() != 1) {
        rec.fPipeline->append(SkRasterPipeline::scale_1_float, alloc.make<float>(p.getAlphaf()));
        isOpaque = false;
    }

    if (auto blitter = SkCreateRasterPipelineBlitter(fDst, p, pipeline, isOpaque, &alloc,
                                                     fRC->clipShader())) {
        SkPath scratchPath;

        for (int i = 0; i < count; ++i) {
            if (colors) {
                SkColor4f c4 = SkColor4f::FromColor(colors[i]);
                steps.apply(c4.vec());
                load_color(uniformCtx, c4.premul().vec());
            }

            SkMatrix mx;
            mx.setRSXform(xform[i]);
            mx.preTranslate(-textures[i].fLeft, -textures[i].fTop);
            mx.postConcat(fMatrixProvider->localToDevice());

            if (updator->update(mx)) {
                fill_rect(mx, *fRC, textures[i], blitter, &scratchPath);
            }
        }
    }
}
