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

#include "src/gpu/ops/GrDrawAtlasPathOp.h"

#include "src/gpu/GrOpFlushState.h"
#include "src/gpu/GrOpsRenderPass.h"
#include "src/gpu/GrProgramInfo.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrVertexWriter.h"
#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
#include "src/gpu/glsl/GrGLSLVarying.h"
#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"

namespace {

class DrawAtlasPathShader : public GrGeometryProcessor {
public:
    DrawAtlasPathShader(bool usesLocalCoords, const GrAtlasInstancedHelper* atlasHelper,
                        const GrShaderCaps& shaderCaps)
            : GrGeometryProcessor(kDrawAtlasPathShader_ClassID)
            , fUsesLocalCoords(usesLocalCoords)
            , fAtlasHelper(atlasHelper)
            , fAtlasAccess(GrSamplerState::Filter::kNearest, fAtlasHelper->proxy()->backendFormat(),
                           fAtlasHelper->atlasSwizzle()) {
        if (!shaderCaps.vertexIDSupport()) {
            constexpr static Attribute kUnitCoordAttrib("unitCoord", kFloat2_GrVertexAttribType,
                                                        kFloat2_GrSLType);
            this->setVertexAttributes(&kUnitCoordAttrib, 1);
        }
        fAttribs.emplace_back("fillBounds", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
        if (fUsesLocalCoords) {
            fAttribs.emplace_back("affineMatrix", kFloat4_GrVertexAttribType, kFloat4_GrSLType);
            fAttribs.emplace_back("translate", kFloat2_GrVertexAttribType, kFloat2_GrSLType);
        }
        SkASSERT(fAttribs.count() == this->colorAttribIdx());
        fAttribs.emplace_back("color", kFloat4_GrVertexAttribType, kHalf4_GrSLType);
        fAtlasHelper->appendInstanceAttribs(&fAttribs);
        SkASSERT(fAttribs.count() <= kMaxInstanceAttribs);
        this->setInstanceAttributes(fAttribs.data(), fAttribs.count());
        this->setTextureSamplerCnt(1);
    }

private:
    int colorAttribIdx() const { return fUsesLocalCoords ? 3 : 1; }
    const char* name() const override { return "DrawAtlasPathShader"; }
    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
        b->addBits(1, fUsesLocalCoords, "localCoords");
        fAtlasHelper->getKeyBits(b);
    }
    const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; }
    GrGLSLGeometryProcessor* createGLSLInstance(const GrShaderCaps&) const override;

    const bool fUsesLocalCoords;
    const GrAtlasInstancedHelper* const fAtlasHelper;
    TextureSampler fAtlasAccess;
    constexpr static int kMaxInstanceAttribs = 6;
    SkSTArray<kMaxInstanceAttribs, GrGeometryProcessor::Attribute> fAttribs;

    class Impl;
};

class DrawAtlasPathShader::Impl : public GrGLSLGeometryProcessor {
    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
        const auto& shader = args.fGeomProc.cast<DrawAtlasPathShader>();
        args.fVaryingHandler->emitAttributes(shader);

        if (args.fShaderCaps->vertexIDSupport()) {
            // If we don't have sk_VertexID support then "unitCoord" already came in as a vertex
            // attrib.
            args.fVertBuilder->codeAppendf(R"(
            float2 unitCoord = float2(sk_VertexID & 1, sk_VertexID >> 1);)");
        }

        args.fVertBuilder->codeAppendf(R"(
        float2 devCoord = mix(fillBounds.xy, fillBounds.zw, unitCoord);)");
        gpArgs->fPositionVar.set(kFloat2_GrSLType, "devCoord");

        if (shader.fUsesLocalCoords) {
            args.fVertBuilder->codeAppendf(R"(
            float2x2 M = float2x2(affineMatrix);
            float2 localCoord = inverse(M) * (devCoord - translate);)");
            gpArgs->fLocalCoordVar.set(kFloat2_GrSLType, "localCoord");
        }

        args.fFragBuilder->codeAppendf("half4 %s = half4(1);", args.fOutputCoverage);
        shader.fAtlasHelper->injectShaderCode(args, gpArgs->fPositionVar, &fAtlasAdjustUniform);

        args.fFragBuilder->codeAppendf("half4 %s;", args.fOutputColor);
        args.fVaryingHandler->addPassThroughAttribute(
                shader.fAttribs[shader.colorAttribIdx()], args.fOutputColor,
                GrGLSLVaryingHandler::Interpolation::kCanBeFlat);
    }

    void setData(const GrGLSLProgramDataManager& pdman,
                 const GrShaderCaps&,
                 const GrGeometryProcessor& geomProc) override {
        auto* atlasHelper = geomProc.cast<DrawAtlasPathShader>().fAtlasHelper;
        atlasHelper->setUniformData(pdman, fAtlasAdjustUniform);
    }

    GrGLSLUniformHandler::UniformHandle fAtlasAdjustUniform;
};

GrGLSLGeometryProcessor* DrawAtlasPathShader::createGLSLInstance(const GrShaderCaps&) const {
    return new Impl();
}

}  // namespace

GrProcessorSet::Analysis GrDrawAtlasPathOp::finalize(const GrCaps& caps, const GrAppliedClip* clip,
                                                     GrClampType clampType) {
    const GrProcessorSet::Analysis& analysis = fProcessors.finalize(
            fHeadInstance->fColor, GrProcessorAnalysisCoverage::kSingleChannel, clip,
            &GrUserStencilSettings::kUnused, caps, clampType, &fHeadInstance->fColor);
    fUsesLocalCoords = analysis.usesLocalCoords();
    return analysis;
}

GrOp::CombineResult GrDrawAtlasPathOp::onCombineIfPossible(GrOp* op, SkArenaAlloc*, const GrCaps&) {
    auto* that = op->cast<GrDrawAtlasPathOp>();

    if (!fAtlasHelper.isCompatible(that->fAtlasHelper) ||
        fProcessors != that->fProcessors) {
        return CombineResult::kCannotCombine;
    }

    SkASSERT(fUsesLocalCoords == that->fUsesLocalCoords);
    *fTailInstance = that->fHeadInstance;
    fTailInstance = that->fTailInstance;
    fInstanceCount += that->fInstanceCount;
    return CombineResult::kMerged;
}

void GrDrawAtlasPathOp::prepareProgram(const GrCaps& caps, SkArenaAlloc* arena,
                                       const GrSurfaceProxyView& writeView, bool usesMSAASurface,
                                       GrAppliedClip&& appliedClip,
                                       const GrDstProxyView& dstProxyView,
                                       GrXferBarrierFlags renderPassXferBarriers,
                                       GrLoadOp colorLoadOp) {
    SkASSERT(!fProgram);
    GrPipeline::InitArgs initArgs;
    if (usesMSAASurface) {
        initArgs.fInputFlags |= GrPipeline::InputFlags::kHWAntialias;
    }
    initArgs.fCaps = &caps;
    initArgs.fDstProxyView = dstProxyView;
    initArgs.fWriteSwizzle = writeView.swizzle();
    auto pipeline = arena->make<GrPipeline>(initArgs, std::move(fProcessors),
                                            std::move(appliedClip));
    auto shader = arena->make<DrawAtlasPathShader>(fUsesLocalCoords, &fAtlasHelper,
                                                   *caps.shaderCaps());
    fProgram = arena->make<GrProgramInfo>(writeView, pipeline, &GrUserStencilSettings::kUnused,
                                          shader, GrPrimitiveType::kTriangleStrip, 0,
                                          renderPassXferBarriers, colorLoadOp);
}

void GrDrawAtlasPathOp::onPrePrepare(GrRecordingContext* rContext,
                                     const GrSurfaceProxyView& writeView,
                                     GrAppliedClip* appliedClip, const GrDstProxyView& dstProxyView,
                                     GrXferBarrierFlags renderPassXferBarriers,
                                     GrLoadOp colorLoadOp) {
    this->prepareProgram(*rContext->priv().caps(), rContext->priv().recordTimeAllocator(),
                         writeView, writeView.asRenderTargetProxy()->numSamples() > 1,
                         std::move(*appliedClip), dstProxyView, renderPassXferBarriers,
                         colorLoadOp);
    SkASSERT(fProgram);
    rContext->priv().recordProgramInfo(fProgram);
}

GR_DECLARE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);

void GrDrawAtlasPathOp::onPrepare(GrOpFlushState* flushState) {
    if (!fProgram) {
        this->prepareProgram(flushState->caps(), flushState->allocator(), flushState->writeView(),
                             flushState->usesMSAASurface(), flushState->detachAppliedClip(),
                             flushState->dstProxyView(), flushState->renderPassBarriers(),
                             flushState->colorLoadOp());
        SkASSERT(fProgram);
    }

    // FIXME(skbug.com/12201): Our draw's MSAA state should match the render target, but DDL doesn't
    // yet communicate DMSAA state to onPrePrepare.
    SkASSERT(fProgram->pipeline().isHWAntialiasState() == flushState->usesMSAASurface());

    if (GrVertexWriter instanceWriter = flushState->makeVertexSpace(
                fProgram->geomProc().instanceStride(), fInstanceCount, &fInstanceBuffer,
                &fBaseInstance)) {
        for (const Instance* i = fHeadInstance; i; i = i->fNext) {
            instanceWriter.write(
                    SkRect::Make(i->fFillBounds),
                    GrVertexWriter::If(fUsesLocalCoords,
                                       i->fLocalToDeviceIfUsingLocalCoords),
                    i->fColor);
            fAtlasHelper.writeInstanceData(&instanceWriter, &i->fAtlasInstance);
        }
    }

    if (!flushState->caps().shaderCaps()->vertexIDSupport()) {
        constexpr static SkPoint kUnitQuad[4] = {{0,0}, {0,1}, {1,0}, {1,1}};

        GR_DEFINE_STATIC_UNIQUE_KEY(gUnitQuadBufferKey);

        fVertexBufferIfNoIDSupport = flushState->resourceProvider()->findOrMakeStaticBuffer(
                GrGpuBufferType::kVertex, sizeof(kUnitQuad), kUnitQuad, gUnitQuadBufferKey);
    }
}

void GrDrawAtlasPathOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {
    flushState->bindPipelineAndScissorClip(*fProgram, this->bounds());
    flushState->bindTextures(fProgram->geomProc(), *fAtlasHelper.proxy(), fProgram->pipeline());
    flushState->bindBuffers(nullptr, std::move(fInstanceBuffer), fVertexBufferIfNoIDSupport);
    flushState->drawInstanced(fInstanceCount, fBaseInstance, 4, 0);
}
