/*
 * Copyright 2023 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/CoverageMaskRenderStep.h"

#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSamplingOptions.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkTileMode.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "src/base/SkEnumBitMask.h"
#include "src/core/SkSLTypeShared.h"
#include "src/gpu/BufferWriter.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/DrawWriter.h"
#include "src/gpu/graphite/PipelineData.h"
#include "src/gpu/graphite/TextureProxy.h"
#include "src/gpu/graphite/geom/CoverageMaskShape.h"
#include "src/gpu/graphite/geom/Geometry.h"
#include "src/gpu/graphite/geom/Rect.h"
#include "src/gpu/graphite/geom/Transform.h"
#include "src/gpu/graphite/render/CommonDepthStencilSettings.h"

#include <cstdint>

namespace skgpu::graphite {

// The device origin is applied *before* the maskToDeviceRemainder matrix so that it can be
// combined with the mask atlas origin. This is necessary so that the mask bounds can be inset or
// outset for clamping w/o affecting the alignment of the mask sampling.
static skvx::float2 get_device_translation(const SkM44& localToDevice) {
    float m00 = localToDevice.rc(0,0), m01 = localToDevice.rc(0,1);
    float m10 = localToDevice.rc(1,0), m11 = localToDevice.rc(1,1);

    float det = m00*m11 - m01*m10;
    if (SkScalarNearlyZero(det)) {
        // We can't extract any pre-translation, since the upper 2x2 is not invertible. Return (0,0)
        // so that the maskToDeviceRemainder matrix remains the full transform.
        return {0.f, 0.f};
    }

    // Calculate inv([[m00,m01][m10,m11]])*[[m30][m31]] to get the pre-remainder device translation.
    float tx = localToDevice.rc(0,3), ty = localToDevice.rc(1,3);
    skvx::float4 invT = skvx::float4{m11, -m10, -m01, m00} * skvx::float4{tx,tx,ty,ty};
    return (invT.xy() + invT.zw()) / det;
}

CoverageMaskRenderStep::CoverageMaskRenderStep(Layout layout)
        : RenderStep(layout,
                     RenderStepID::kCoverageMask,
                     // The mask will have AA outsets baked in, but the original bounds for clipping
                     // still require the outset for analytic coverage.
                     Flags::kPerformsShading |
                     Flags::kHasTextures |
                     Flags::kEmitsCoverage |
                     Flags::kOutsetBoundsForAA |
                     Flags::kInverseFillsScissor |
                     Flags::kAppendInstances,
                     /*uniforms=*/{{"maskToDeviceRemainder", SkSLType::kFloat3x3}},
                     PrimitiveType::kTriangleStrip,
                     kDirectDepthLessPass,
                     /*staticAttrs=*/ {},
                     /*appendAttrs=*/
                     // Draw bounds and mask bounds are in normalized relative to the mask texture,
                     // but 'drawBounds' is stored in float since the coords may map outside of
                     // [0,1] for inverse-filled masks. 'drawBounds' is relative to the logical mask
                     // entry's origin, while 'maskBoundsIn' is atlas-relative. Inverse fills swap
                     // the order in 'maskBoundsIn' to be RBLT.
                     {{{"drawBounds", VertexAttribType::kFloat4 , SkSLType::kFloat4},  // ltrb
                      {"maskBoundsIn", VertexAttribType::kUShort4_norm, SkSLType::kFloat4},
                      // Remaining translation extracted from actual 'maskToDevice' transform.
                      {"deviceOrigin", VertexAttribType::kFloat2, SkSLType::kFloat2},
                      {"depth"     , VertexAttribType::kFloat, SkSLType::kFloat},
                      {"ssboIndex", VertexAttribType::kUInt, SkSLType::kUInt},
                      // localToDevice matrix for producing local coords for shader evaluation
                      {"mat0", VertexAttribType::kFloat3, SkSLType::kFloat3},
                      {"mat1", VertexAttribType::kFloat3, SkSLType::kFloat3},
                      {"mat2", VertexAttribType::kFloat3, SkSLType::kFloat3}}},
                     /*varyings=*/
                     {{// `maskBounds` are the atlas-relative, sorted bounds of the coverage mask.
                      // `textureCoords` are the atlas-relative UV coordinates of the draw, which
                      // can spill beyond `maskBounds` for inverse fills.
                      // TODO: maskBounds is constant for all fragments for a given instance,
                      // could we store them in the draw's SSBO?
                      {"maskBounds"   , SkSLType::kFloat4},
                      {"textureCoords", SkSLType::kFloat2},
                      // 'invert' is set to 0 use unmodified coverage, and set to 1 for "1-c".
                      {"invert", SkSLType::kHalf}}}) {}

std::string CoverageMaskRenderStep::vertexSkSL() 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 "float4 devPosition = coverage_mask_vertex_fn("
                    "float2(sk_VertexID >> 1, sk_VertexID & 1), "
                    "maskToDeviceRemainder, drawBounds, maskBoundsIn, deviceOrigin, "
                    "depth, float3x3(mat0, mat1, mat2), "
                    "maskBounds, textureCoords, invert, stepLocalCoords);\n";
}

std::string CoverageMaskRenderStep::texturesAndSamplersSkSL(
        const ResourceBindingRequirements& bindingReqs, int* nextBindingIndex) const {
    return EmitSamplerLayout(bindingReqs, nextBindingIndex) + " sampler2D pathAtlas;";
}

const char* CoverageMaskRenderStep::fragmentCoverageSkSL() const {
    return
        "half c = sample(pathAtlas, clamp(textureCoords, maskBounds.LT, maskBounds.RB)).r;\n"
        "outputCoverage = half4(mix(c, 1 - c, invert));\n";
}

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

void CoverageMaskRenderStep::writeVertices(DrawWriter* dw,
                                           const DrawParams& params,
                                           uint32_t ssboIndex) const {
    const CoverageMaskShape& coverageMask = params.geometry().coverageMaskShape();
    const TextureProxy* proxy = coverageMask.textureProxy();
    SkASSERT(proxy);

    // A quad is a 4-vertex instance. The coordinates are derived from the vertex IDs.
    DrawWriter::Instances instances(*dw, {}, {}, 4);

    // The device origin is the  translation extracted from the mask-to-device matrix so
    // that the remaining matrix uniform has less variance between draws.
    const SkM44& maskToDevice = coverageMask.maskToDevice();
    skvx::float2 deviceOrigin = get_device_translation(maskToDevice);

    // Relative to mask space (device origin and mask-to-device remainder must be applied in shader)
    skvx::float4 maskBounds = coverageMask.bounds().ltrb();
    skvx::float4 drawBounds;

    if (coverageMask.inverted()) {
        // Only mask filters trigger complex transforms, and they are never inverse filled. Since
        // we know this is an inverted mask, then we can exactly map the draw's clip bounds to mask
        // space so that the clip is still fully covered without branching in the vertex shader.
        SkASSERT(maskToDevice == SkM44::Translate(deviceOrigin.x(), deviceOrigin.y()));
        drawBounds = params.drawBounds().makeOffset(-deviceOrigin).ltrb();

        // If the mask is fully clipped out, then the shape's mask info should be (0,0,0,0).
        // If it's not fully clipped out, then the mask info should be non-empty.
        const bool emptyMask = all(maskBounds == 0.f);
        SkDEBUGCODE(Rect clippedShapeBounds =
                    params.transformedShapeBounds().makeIntersect(params.scissor()));
        SkASSERT(!clippedShapeBounds.isEmptyNegativeOrNaN() ^ emptyMask);

        if (emptyMask) {
            // The inversion check is strict inequality, so (0,0,0,0) would not be detected. Adjust
            // to (0,0,1/2,1/2) to restrict sampling to the top-left quarter of the top-left pixel,
            // which should have a value of 0 regardless of filtering mode.
            maskBounds = skvx::float4{0.f, 0.f, 0.5f, 0.5f};
        } else {
            // Add 1/2px outset to the mask bounds so that clamped coordinates sample the texel
            // center of the padding around the atlas entry.
            maskBounds += skvx::float4{-0.5f, -0.5f, 0.5f, 0.5f};
        }

        // and store RBLT so that the 'maskBoundsIn' attribute has xy > zw to detect inverse fill.
        maskBounds = skvx::shuffle<2,3,0,1>(maskBounds);
    } else {
        // If we aren't inverted, then the originally assigned values don't need to be adjusted, but
        // also ensure the mask isn't empty (otherwise the draw should have been skipped earlier).
        SkASSERT(!coverageMask.bounds().isEmptyNegativeOrNaN());
        SkASSERT(all(maskBounds.xy() < maskBounds.zw()));

        // Since the mask bounds and draw bounds are 1-to-1 with each other, the clamping of texture
        // coords is mostly a formality. We inset the mask bounds by 1/2px so that we clamp to the
        // texel center of the outer row/column of the mask. This should be a no-op for nearest
        // sampling but prevents any linear sampling from incorporating adjacent data; for atlases
        // this would just be 0 but for non-atlas coverage masks that might not have padding this
        // avoids filtering unknown values in an approx-fit texture.
        drawBounds = maskBounds;
        maskBounds -= skvx::float4{-0.5f, -0.5f, 0.5f, 0.5f};
    }

    // Move 'drawBounds' and 'maskBounds' into the atlas coordinate space, then adjust the
    // device translation to undo the atlas origin automatically in the vertex shader.
    skvx::float2 textureOrigin = skvx::cast<float>(coverageMask.textureOrigin());
    maskBounds += textureOrigin.xyxy();
    drawBounds += textureOrigin.xyxy();
    deviceOrigin -= textureOrigin;

    // Normalize drawBounds and maskBounds after possibly correcting drawBounds for inverse fills.
    // The maskToDevice matrix uniform will handle de-normalizing drawBounds for vertex positions.
    auto atlasSizeInv = skvx::float2{1.f / proxy->dimensions().width(),
                                     1.f / proxy->dimensions().height()};
    drawBounds *= atlasSizeInv.xyxy();
    maskBounds *= atlasSizeInv.xyxy();
    deviceOrigin *= atlasSizeInv;

    // Since the mask bounds define normalized texels of the texture, we can encode them as
    // ushort_norm without losing precision to save space.
    SkASSERT(all((maskBounds >= 0.f) & (maskBounds <= 1.f)));
    maskBounds = 65535.f * maskBounds + 0.5f;

    const SkM44& m = params.transform().matrix(); // local-to-device
    instances.append(1) << drawBounds << skvx::cast<uint16_t>(maskBounds) << deviceOrigin
                        << params.order().depthAsFloat() << ssboIndex
                        << m.rc(0,0) << m.rc(1,0) << m.rc(3,0)   // mat0
                        << m.rc(0,1) << m.rc(1,1) << m.rc(3,1)   // mat1
                        << m.rc(0,3) << m.rc(1,3) << m.rc(3,3);  // mat2
}

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

    const CoverageMaskShape& coverageMask = params.geometry().coverageMaskShape();
    const TextureProxy* proxy = coverageMask.textureProxy();
    SkASSERT(proxy);

    // Most coverage masks are aligned with the device pixels, so the params' transform is an
    // integer translation matrix. This translation is extracted as an instance attribute so that
    // the remaining transform has a much lower frequency of changing (only complex-transformed
    // mask filters).
    skvx::float2 deviceOrigin = get_device_translation(coverageMask.maskToDevice());
    SkMatrix maskToDeviceRemainder = coverageMask.maskToDevice().asM33();
    maskToDeviceRemainder.preTranslate(-deviceOrigin.x(), -deviceOrigin.y());

    // Check pixel alignment before we fold in coord normalization scaling
    const bool pixelAligned = maskToDeviceRemainder.isIdentity() &&
                              all(deviceOrigin == floor(deviceOrigin + SK_ScalarNearlyZero));

    // The mask coordinates in the vertex shader will be normalized, so scale by the proxy size
    // to get back to Skia's texel-based coords.
    maskToDeviceRemainder.preScale(proxy->dimensions().width(), proxy->dimensions().height());

    // Write uniforms:
    gatherer->write(maskToDeviceRemainder);

    // Write textures and samplers:
    gatherer->add(sk_ref_sp(proxy), {pixelAligned ? SkFilterMode::kNearest : SkFilterMode::kLinear,
                                     SkTileMode::kClamp});
}

}  // namespace skgpu::graphite
