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

#include "src/gpu/graphite/render/BitmapTextRenderStep.h"

#include "include/core/SkM44.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkSize.h"
#include "include/core/SkTileMode.h"
#include "include/gpu/graphite/Recorder.h"
#include "include/private/SkAssert.h"
#include "include/private/SkDebug.h"
#include "src/core/SkSLTypeShared.h"
#include "src/gpu/graphite/AtlasProvider.h"
#include "src/gpu/graphite/Attribute.h"
#include "src/gpu/graphite/ContextUtils.h"
#include "src/gpu/graphite/DrawOrder.h"
#include "src/gpu/graphite/DrawParams.h"
#include "src/gpu/graphite/DrawTypes.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/RecorderPriv.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/geom/Geometry.h"
#include "src/gpu/graphite/geom/SubRunData.h"
#include "src/gpu/graphite/geom/Transform.h"
#include "src/gpu/graphite/render/CommonDepthStencilSettings.h"
#include "src/gpu/graphite/text/GlyphData.h"
#include "src/gpu/graphite/text/TextAtlasManager.h"
#include "src/sksl/SkSLString.h"
#include "src/text/gpu/SubRunContainer.h"
#include "src/text/gpu/VertexFiller.h"

using AtlasSubRun = sktext::gpu::AtlasSubRun;

namespace skgpu::graphite {

namespace {

// We are expecting to sample from up to 4 textures
constexpr int kNumTextAtlasTextures = 4;

RenderStep::RenderStepID variant_id(skgpu::MaskFormat variant) {
    switch (variant) {
        case skgpu::MaskFormat::kA8:   return RenderStep::RenderStepID::kBitmapText_Mask;
        case skgpu::MaskFormat::kA565: return RenderStep::RenderStepID::kBitmapText_LCD;
        case skgpu::MaskFormat::kARGB: return RenderStep::RenderStepID::kBitmapText_Color;
    }

    SkUNREACHABLE;
}

}  // namespace

// NOTE: Sub run glyphs can emit triangles that self intersect, and we need those to produce
// double blending (although usually one glyph will have 0 coverage at that pixel), so we include
// Flags::kAllowSelfIntersection.
BitmapTextRenderStep::BitmapTextRenderStep(Layout layout, skgpu::MaskFormat variant)
        : RenderStep(layout,
                     variant_id(variant),
                     Flags(variant) | Flags::kAppendInstances
                                    | Flags::kAllowsSelfIntersection,
                     /*uniforms=*/{{"maskToDevice", SkSLType::kFloat4x4},
                                   {"localToDevice", SkSLType::kFloat4x4},
                                   {"atlasSizeInv", SkSLType::kFloat2}},
                     PrimitiveType::kTriangleStrip,
                     kDirectDepthLEqualPass,
                     /*staticAttrs=*/ {},
                     /*appendAttrs=*/
                     {{{"size", VertexAttribType::kUShort2, SkSLType::kUShort2},
                      {"uvPos", VertexAttribType::kUShort2, SkSLType::kUShort2},
                      {"xyPos", VertexAttribType::kFloat2, SkSLType::kFloat2},
                      {"indexAndFlags", VertexAttribType::kUShort2, SkSLType::kUShort2},
                      {"strikeToSourceScale", VertexAttribType::kFloat, SkSLType::kFloat},
                      {"depth", VertexAttribType::kFloat, SkSLType::kFloat},
                      {"ssboIndex", VertexAttribType::kUInt, SkSLType::kUInt}}},
                     /*storageUniforms=*/{},
                     /*varyings=*/
                     {{{"textureCoords", SkSLType::kFloat2},
#ifdef SK_DISABLE_GRAPHITE_NONINTEGRAL_VARYINGS_FLAT_INTERPOLATION
                      {"texIndex", SkSLType::kHalf},
                      {"maskFormat", SkSLType::kHalf}
#else
                      {"texIndex", SkSLType::kHalf, Interpolation::kFlat},
                      {"maskFormat", SkSLType::kHalf, Interpolation::kFlat}
#endif
                      }}) {}


BitmapTextRenderStep::~BitmapTextRenderStep() {}

SkEnumBitMask<RenderStep::Flags> BitmapTextRenderStep::Flags(skgpu::MaskFormat variant) {
    switch (variant) {
        case skgpu::MaskFormat::kA8:
            return Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage;
        case skgpu::MaskFormat::kA565:
            return Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsCoverage |
                   Flags::kLCDCoverage;
        case skgpu::MaskFormat::kARGB:
            return Flags::kPerformsShading | Flags::kHasTextures | Flags::kEmitsPrimitiveColor;
        default:
            SkUNREACHABLE;
    }
}

std::string BitmapTextRenderStep::vertexSkSL(const RootNodesInfo&) const {
    // Returns the body of a vertex function, which must define a float4 devPosition variable and
    // must write to an already-defined float2 stepLocalCoords variable.
    return "texIndex = half(indexAndFlags.x);"
           "maskFormat = half(indexAndFlags.y);"
           "float2 unormTexCoords;"
           "float4 devPosition = text_vertex_fn(float2(sk_VertexID >> 1, sk_VertexID & 1), "
                                               "maskToDevice, "
                                               "localToDevice, "
                                               "atlasSizeInv, "
                                               "float2(size), "
                                               "float2(uvPos), "
                                               "xyPos, "
                                               "strikeToSourceScale, "
                                               "depth, "
                                               "textureCoords, "
                                               "unormTexCoords, "
                                               "stepLocalCoords);";
}

std::string BitmapTextRenderStep::texturesAndSamplersSkSL(
        const ResourceBindingRequirements& bindingReqs, int* nextBindingIndex) const {
    std::string result;

    for (unsigned int i = 0; i < kNumTextAtlasTextures; ++i) {
        result += EmitSamplerLayout(bindingReqs, nextBindingIndex);
        SkSL::String::appendf(&result, " sampler2D text_atlas_%u;\n", i);
    }

    return result;
}


std::string BitmapTextRenderStep::fragmentColorSkSL(const RootNodesInfo&) const {
    // The returned SkSL must write its color into a 'half4 primitiveColor' variable
    // (defined in the calling code).
    static_assert(kNumTextAtlasTextures == 4);
    return "primitiveColor = sample_indexed_atlas(textureCoords, "
                                                 "int(texIndex), "
                                                 "text_atlas_0, "
                                                 "text_atlas_1, "
                                                 "text_atlas_2, "
                                                 "text_atlas_3);";
}

const char* BitmapTextRenderStep::fragmentCoverageSkSL() const {
    // The returned SkSL must write its coverage into a 'half4 outputCoverage' variable (defined in
    // the calling code) with the actual coverage splatted out into all four channels.
    static_assert(kNumTextAtlasTextures == 4);
    return "outputCoverage = bitmap_text_coverage_fn(sample_indexed_atlas(textureCoords, "
                                                                         "int(texIndex), "
                                                                         "text_atlas_0, "
                                                                         "text_atlas_1, "
                                                                         "text_atlas_2, "
                                                                         "text_atlas_3), "
                                                    "int(maskFormat));";
}

bool BitmapTextRenderStep::usesUniformsInFragmentSkSL() const { return false; }

void BitmapTextRenderStep::writeVertices(DrawWriter* dw,
                                         StorageContext* /*storageContext*/,
                                         const DrawParams& params,
                                         uint32_t ssboIndex) const {
    const SubRunData& subRunData = params.geometry().subRunData();
    auto& glyphData = subRunData.subRun()->glyphVector().accessBackendData<GlyphData>();
    glyphData.fillInstanceData(subRunData.subRun()->vertexFiller(),
                               subRunData.subRun()->glyphVector().accessBackendGlyphs<Glyph>(),
                               dw,
                               subRunData.startGlyphIndex(),
                               subRunData.glyphCount(),
                               subRunData.subRun()->instanceFlags(),
                               ssboIndex,
                               params.order().depthAsFloat());
}

void BitmapTextRenderStep::writeUniformsAndTextures(const DrawParams& params,
                                                    PipelineDataGatherer* gatherer) const {
    SkDEBUGCODE(gatherer->checkRewind());
    SkDEBUGCODE(UniformExpectationsValidator uev(gatherer, this->uniforms());)

    const SubRunData& subRunData = params.geometry().subRunData();
    unsigned int numProxies;
    Recorder* recorder = subRunData.recorder();
    const sk_sp<TextureProxy>* proxies =
            recorder->priv().getOrCreateAtlasProvider()->textAtlasManager()->getProxies(
                    subRunData.resolvedMaskFormat(), &numProxies);
    SkASSERT(proxies && numProxies > 0);

    // write uniforms
    // TODO(b/238753996): The maskToDevice should be adjusted similar to CoverageMaskRenderStep so
    // that the integer translation is pulled into the instance data and this uniform is less likely
    // to change.
    // TODO(b/307766179): Similarly, we should discard the local-to-device matrix uniform value (and
    // just set identity) if the paint doesn't actually require local coords.
    // TODO(b/351923375): Precompute the 3x3 inverse of the local-to-device since it's shared by all
    // instances? We can derive it from the Transform's existing 4x4 inverse.
    gatherer->write(subRunData.maskToDevice());
    gatherer->write(params.transform().matrix()); // local-to-device
    SkV2 atlasDimensionsInverse = {1.f/proxies[0]->dimensions().width(),
                                   1.f/proxies[0]->dimensions().height()};
    gatherer->write(atlasDimensionsInverse);

    // write textures and samplers
    for (unsigned int i = 0; i < numProxies; ++i) {
        gatherer->add(proxies[i], {SkFilterMode::kNearest, SkTileMode::kClamp});
    }
    // If the atlas has less than 4 active proxies we still need to set up samplers for the shader.
    for (unsigned int i = numProxies; i < kNumTextAtlasTextures; ++i) {
        gatherer->add(proxies[0], {SkFilterMode::kNearest, SkTileMode::kClamp});
    }
}

}  // namespace skgpu::graphite
