/*
 * Copyright 2020 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/ganesh/StencilMaskHelper.h"

#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkRect.h"
#include "include/core/SkRegion.h"
#include "include/gpu/ganesh/GrRecordingContext.h"
#include "include/private/base/SkAssert.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/base/SkTLazy.h"
#include "src/gpu/ganesh/GrClip.h"
#include "src/gpu/ganesh/GrDrawingManager.h"
#include "src/gpu/ganesh/GrFixedClip.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrStencilSettings.h"
#include "src/gpu/ganesh/GrStyle.h"
#include "src/gpu/ganesh/GrUserStencilSettings.h"
#include "src/gpu/ganesh/GrWindowRectangles.h"
#include "src/gpu/ganesh/GrWindowRectsState.h"
#include "src/gpu/ganesh/PathRenderer.h"
#include "src/gpu/ganesh/PathRendererChain.h"
#include "src/gpu/ganesh/SurfaceDrawContext.h"
#include "src/gpu/ganesh/effects/GrDisableColorXP.h"
#include "src/gpu/ganesh/geometry/GrShape.h"
#include "src/gpu/ganesh/geometry/GrStyledShape.h"

#include <utility>

namespace {

////////////////////////////////////////////////////////////////////////////////
// Stencil Rules for Merging user stencil space into clip
//

///////
// Replace
static constexpr GrUserStencilSettings gUserToClipReplace(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kNotEqual,
        0xffff,
        GrUserStencilOp::kSetClipAndReplaceUserBits,
        GrUserStencilOp::kZeroClipAndUserBits,
        0xffff>()
);

static constexpr GrUserStencilSettings gInvUserToClipReplace(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kEqual,
        0xffff,
        GrUserStencilOp::kSetClipAndReplaceUserBits,
        GrUserStencilOp::kZeroClipAndUserBits,
        0xffff>()
);

///////
// Intersect
static constexpr GrUserStencilSettings gUserToClipIsect(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0 != userBits".
        0xffff,
        GrUserStencilOp::kSetClipAndReplaceUserBits,
        GrUserStencilOp::kZeroClipAndUserBits,
        0xffff>()
);

///////
// Difference
static constexpr GrUserStencilSettings gUserToClipDiff(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kEqualIfInClip,
        0xffff,
        GrUserStencilOp::kSetClipAndReplaceUserBits,
        GrUserStencilOp::kZeroClipAndUserBits,
        0xffff>()
);

///////
// Union
static constexpr GrUserStencilSettings gUserToClipUnion(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kNotEqual,
        0xffff,
        GrUserStencilOp::kSetClipAndReplaceUserBits,
        GrUserStencilOp::kKeep,
        0xffff>()
);

static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zero user bits.
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kEqual,
        0xffff,
        GrUserStencilOp::kSetClipBit,
        GrUserStencilOp::kKeep,
        0x0000>()
);

///////
// Xor
static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero user bits.
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kNotEqual,
        0xffff,
        GrUserStencilOp::kInvertClipBit,
        GrUserStencilOp::kKeep,
        0x0000>()
);

static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero user bits.
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kEqual,
        0xffff,
        GrUserStencilOp::kInvertClipBit,
        GrUserStencilOp::kKeep,
        0x0000>()
);

///////
// Reverse Diff
static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero user bits.
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kNotEqual,
        0xffff,
        GrUserStencilOp::kInvertClipBit,
        GrUserStencilOp::kZeroClipBit,
        0x0000>()
);

static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zero user bits.
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kEqual,
        0xffff,
        GrUserStencilOp::kInvertClipBit,
        GrUserStencilOp::kZeroClipBit,
        0x0000>()
);

///////
// Second pass to clear user bits (only needed sometimes)
static constexpr GrUserStencilSettings gZeroUserBits(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kNotEqual,
        0xffff,
        GrUserStencilOp::kZero,
        GrUserStencilOp::kKeep,
        0xffff>()
);

static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion::kLastOp][3] = {
    {  /* Normal fill. */
        {&gUserToClipDiff,           nullptr,         nullptr},  // kDifference_Op.
        {&gUserToClipIsect,          nullptr,         nullptr},  // kIntersect_Op.
        {&gUserToClipUnion,          nullptr,         nullptr},  // kUnion_Op.
        {&gUserToClipXorPass0,       &gZeroUserBits,  nullptr},  // kXOR_Op.
        {&gUserToClipRDiffPass0,     &gZeroUserBits,  nullptr},  // kReverseDifference_Op.
        {&gUserToClipReplace,        nullptr,         nullptr}   // kReplace_Op.

    }, /* Inverse fill. */ {
        {&gUserToClipIsect,          nullptr,         nullptr},  // ~diff (aka isect).
        {&gUserToClipDiff,           nullptr,         nullptr},  // ~isect (aka diff).
        {&gInvUserToClipUnionPass0,  &gZeroUserBits,  nullptr},  // ~union.
        {&gInvUserToClipXorPass0,    &gZeroUserBits,  nullptr},  // ~xor.
        {&gInvUserToClipRDiffPass0,  &gZeroUserBits,  nullptr},  // ~reverse diff.
        {&gInvUserToClipReplace,     nullptr,         nullptr}   // ~replace.
    }
};

///////
// Direct to Stencil

// We can render a clip element directly without first writing to the client
// portion of the clip when the fill is not inverse and the set operation will
// only modify the in/out status of samples covered by the clip element.

// this one only works if used right after stencil clip was cleared.
// Our clip mask creation code doesn't allow midstream replace ops.
static constexpr GrUserStencilSettings gReplaceClip(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlways,
        0xffff,
        GrUserStencilOp::kSetClipBit,
        GrUserStencilOp::kSetClipBit,
        0x0000>()
);

static constexpr GrUserStencilSettings gUnionClip(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlwaysIfInClip,
        0xffff,
        GrUserStencilOp::kKeep,
        GrUserStencilOp::kSetClipBit,
        0x0000>()
);

static constexpr GrUserStencilSettings gXorClip(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlways,
        0xffff,
        GrUserStencilOp::kInvertClipBit,
        GrUserStencilOp::kInvertClipBit,
        0x0000>()
);

static constexpr GrUserStencilSettings gDiffClip(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlwaysIfInClip,
        0xffff,
        GrUserStencilOp::kZeroClipBit,
        GrUserStencilOp::kKeep,
        0x0000>()
);

static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLastOp][2] = {
    {&gDiffClip,     nullptr},  // kDifference_Op.
    {nullptr,        nullptr},  // kIntersect_Op.
    {&gUnionClip,    nullptr},  // kUnion_Op.
    {&gXorClip,      nullptr},  // kXOR_Op.
    {nullptr,        nullptr},  // kReverseDifference_Op.
    {&gReplaceClip,  nullptr}   // kReplace_Op.
};

static_assert(0 == SkRegion::kDifference_Op);
static_assert(1 == SkRegion::kIntersect_Op);
static_assert(2 == SkRegion::kUnion_Op);
static_assert(3 == SkRegion::kXOR_Op);
static_assert(4 == SkRegion::kReverseDifference_Op);
static_assert(5 == SkRegion::kReplace_Op);

// Settings used to when not allowed to draw directly to the clip to fill the user stencil bits
// before applying the covering clip stencil passes.
static constexpr GrUserStencilSettings gDrawToStencil(
    GrUserStencilSettings::StaticInit<
        0x0000,
        GrUserStencilTest::kAlways,
        0xffff,
        GrUserStencilOp::kIncMaybeClamp,
        GrUserStencilOp::kIncMaybeClamp,
        0xffff>()
);

// Get the stencil settings per-pass to achieve the given fill+region op effect on the
// stencil buffer.
//
// If drawDirectToClip comes back false, the caller must first draw the element into the user
// stencil bits, and then cover the clip area with multiple passes using the returned
// stencil settings.

// If drawDirectToClip is true, the returned array will only have one pass and the
// caller should use those stencil settings while drawing the element directly.
//
// This returns a null-terminated list of const GrUserStencilSettings*
GrUserStencilSettings const* const* get_stencil_passes(
        SkRegion::Op op,
        skgpu::ganesh::PathRenderer::StencilSupport stencilSupport,
        bool fillInverted,
        bool* drawDirectToClip) {
    bool canRenderDirectToStencil =
            skgpu::ganesh::PathRenderer::kNoRestriction_StencilSupport == stencilSupport;

    // TODO: inverse fill + intersect op can be direct.
    // TODO: this can be greatly simplified when we only need intersect and difference ops and
    //       none of the paths will be inverse-filled (just toggle the op instead).
    SkASSERT((unsigned)op <= SkRegion::kLastOp);
    if (canRenderDirectToStencil && !fillInverted) {
        GrUserStencilSettings const* const* directPass = gDirectDrawTable[op];
        if (directPass[0]) {
            *drawDirectToClip = true;
            return directPass;
        }
    }
    *drawDirectToClip = false;
    return gUserToClipTable[fillInverted][op];
}

void draw_stencil_rect(skgpu::ganesh::SurfaceDrawContext* sdc,
                       const GrHardClip& clip,
                       const GrUserStencilSettings* ss,
                       const SkMatrix& matrix,
                       const SkRect& rect,
                       GrAA aa) {
    GrPaint paint;
    paint.setXPFactory(GrDisableColorXPFactory::Get());
    sdc->stencilRect(&clip, ss, std::move(paint), aa, matrix, rect);
}

void draw_path(GrRecordingContext* rContext,
               skgpu::ganesh::SurfaceDrawContext* sdc,
               skgpu::ganesh::PathRenderer* pr,
               const GrHardClip& clip,
               const SkIRect& bounds,
               const GrUserStencilSettings* ss,
               const SkMatrix& matrix,
               const GrStyledShape& shape,
               GrAA aa) {
    GrPaint paint;
    paint.setXPFactory(GrDisableColorXPFactory::Get());

    // kMSAA is the only type of AA that's possible on a stencil buffer.
    GrAAType pathAAType = aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone;

    skgpu::ganesh::PathRenderer::DrawPathArgs args{rContext,
                                                   std::move(paint),
                                                   ss,
                                                   sdc,
                                                   &clip,
                                                   &bounds,
                                                   &matrix,
                                                   &shape,
                                                   pathAAType,
                                                   false};
    pr->drawPath(args);
}

void stencil_path(GrRecordingContext* rContext,
                  skgpu::ganesh::SurfaceDrawContext* sdc,
                  skgpu::ganesh::PathRenderer* pr,
                  const GrFixedClip& clip,
                  const SkMatrix& matrix,
                  const GrStyledShape& shape,
                  GrAA aa) {
    skgpu::ganesh::PathRenderer::StencilPathArgs args;
    args.fContext = rContext;
    args.fSurfaceDrawContext = sdc;
    args.fClip = &clip;
    args.fClipConservativeBounds = &clip.scissorRect();
    args.fViewMatrix = &matrix;
    args.fShape = &shape;
    args.fDoStencilMSAA = aa;

    pr->stencilPath(args);
}

GrAA supported_aa(skgpu::ganesh::SurfaceDrawContext* sdc, GrAA aa) {
    return GrAA(sdc->numSamples() > 1 || sdc->canUseDynamicMSAA());
}

}  // namespace

namespace skgpu::ganesh {

StencilMaskHelper::StencilMaskHelper(GrRecordingContext* rContext,
                                     SurfaceDrawContext* sdc)
        : fContext(rContext)
        , fSDC(sdc)
        , fClip(sdc->dimensions()) {
}

bool StencilMaskHelper::init(const SkIRect& bounds, uint32_t genID,
                             const GrWindowRectangles& windowRects, int numFPs) {
    if (!fSDC->mustRenderClip(genID, bounds, numFPs)) {
        return false;
    }

    fClip.setStencilClip(genID);
    // Should have caught bounds not intersecting the render target much earlier in clip application
    SkAssertResult(fClip.fixedClip().setScissor(bounds));
    if (!windowRects.empty()) {
        fClip.fixedClip().setWindowRectangles(
                windowRects, GrWindowRectsState::Mode::kExclusive);
    }
    fNumFPs = numFPs;
    return true;
}

void StencilMaskHelper::drawRect(const SkRect& rect,
                                 const SkMatrix& matrix,
                                 SkRegion::Op op,
                                 GrAA aa) {
    if (rect.isEmpty()) {
        return;
    }

    bool drawDirectToClip;
    auto passes = get_stencil_passes(op, PathRenderer::kNoRestriction_StencilSupport,
                                     false, &drawDirectToClip);
    aa = supported_aa(fSDC, aa);

    if (!drawDirectToClip) {
        // Draw to client stencil bits first
        draw_stencil_rect(fSDC, fClip.fixedClip(), &gDrawToStencil, matrix, rect, aa);
    }

    // Now modify the clip bit (either by rendering directly), or by covering the bounding box
    // of the clip
    for (GrUserStencilSettings const* const* pass = passes; *pass; ++pass) {
        if (drawDirectToClip) {
            draw_stencil_rect(fSDC, fClip, *pass, matrix, rect, aa);
        } else {
            draw_stencil_rect(fSDC, fClip, *pass, SkMatrix::I(),
                              SkRect::Make(fClip.fixedClip().scissorRect()), aa);
        }
    }
}

bool StencilMaskHelper::drawPath(const SkPath& path,
                                 const SkMatrix& matrix,
                                 SkRegion::Op op,
                                 GrAA aa) {
    if (path.isEmpty()) {
        return true;
    }

    // drawPath follows a similar approach to drawRect(), where we either draw directly to the clip
    // bit or first draw to client bits and then apply a cover pass. The complicating factor is that
    // we rely on path rendering and how the chosen path renderer uses the stencil buffer.
    aa = supported_aa(fSDC, aa);

    GrAAType pathAAType = aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone;

    // This will be used to determine whether the clip shape can be rendered into the
    // stencil with arbitrary stencil settings.
    PathRenderer::StencilSupport stencilSupport;

    // Make path canonical with regards to fill type (inverse handled by stencil settings).
    bool fillInverted = path.isInverseFillType();
    SkTCopyOnFirstWrite<SkPath> clipPath(path);
    if (fillInverted) {
        clipPath.writable()->toggleInverseFillType();
    }

    GrStyledShape shape(*clipPath, GrStyle::SimpleFill());
    SkASSERT(!shape.inverseFilled());

    PathRenderer::CanDrawPathArgs canDrawArgs;
    canDrawArgs.fCaps = fContext->priv().caps();
    canDrawArgs.fProxy = fSDC->asRenderTargetProxy();
    canDrawArgs.fClipConservativeBounds = &fClip.fixedClip().scissorRect();
    canDrawArgs.fViewMatrix = &matrix;
    canDrawArgs.fShape = &shape;
    canDrawArgs.fPaint = nullptr;
    canDrawArgs.fSurfaceProps = &fSDC->surfaceProps();
    canDrawArgs.fAAType = pathAAType;
    canDrawArgs.fHasUserStencilSettings = false;

    auto pr =  fContext->priv().drawingManager()->getPathRenderer(
            canDrawArgs, false, PathRendererChain::DrawType::kStencil, &stencilSupport);
    if (!pr) {
        return false;
    }

    bool drawDirectToClip;
    auto passes = get_stencil_passes(op, stencilSupport, fillInverted, &drawDirectToClip);

    // Write to client bits if necessary
    if (!drawDirectToClip) {
        if (stencilSupport == PathRenderer::kNoRestriction_StencilSupport) {
            draw_path(fContext, fSDC, pr, fClip.fixedClip(), fClip.fixedClip().scissorRect(),
                      &gDrawToStencil, matrix, shape, aa);
        } else {
            stencil_path(fContext, fSDC, pr, fClip.fixedClip(), matrix, shape, aa);
        }
    }

    // Now modify the clip bit (either by rendering directly), or by covering the bounding box
    // of the clip
    for (GrUserStencilSettings const* const* pass = passes; *pass; ++pass) {
        if (drawDirectToClip) {
            draw_path(fContext, fSDC, pr, fClip, fClip.fixedClip().scissorRect(),
                      *pass, matrix, shape, aa);
        } else {
            draw_stencil_rect(fSDC, fClip, *pass, SkMatrix::I(),
                              SkRect::Make(fClip.fixedClip().scissorRect()), aa);
        }
    }

    return true;
}

bool StencilMaskHelper::drawShape(const GrShape& shape,
                                  const SkMatrix& matrix,
                                  SkRegion::Op op,
                                  GrAA aa) {
    if (shape.isRect() && !shape.inverted()) {
        this->drawRect(shape.rect(), matrix, op, aa);
        return true;
    } else {
        return this->drawPath(shape.asPath(), matrix, op, aa);
    }
}

void StencilMaskHelper::clear(bool insideStencil) {
    if (fClip.fixedClip().hasWindowRectangles()) {
        // Use a draw to benefit from window rectangles when resetting the stencil buffer; for
        // large buffers with MSAA this can be significant.
        draw_stencil_rect(fSDC, fClip.fixedClip(),
                          GrStencilSettings::SetClipBitSettings(insideStencil), SkMatrix::I(),
                          SkRect::Make(fClip.fixedClip().scissorRect()), GrAA::kNo);
    } else {
        fSDC->clearStencilClip(fClip.fixedClip().scissorRect(), insideStencil);
    }
}

void StencilMaskHelper::finish() {
    fSDC->setLastClip(fClip.stencilStackID(), fClip.fixedClip().scissorRect(), fNumFPs);
}

}  // namespace skgpu::ganesh
