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

#include "include/private/GrRecordingContext.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrFixedClip.h"
#include "src/gpu/GrGpu.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/GrRenderTargetContextPriv.h"
#include "src/gpu/GrResourceProvider.h"
#include "src/gpu/GrStencilClip.h"
#include "src/gpu/GrStyle.h"
#include "src/gpu/geometry/GrShape.h"
#include "src/gpu/ops/GrDrawPathOp.h"
#include "src/gpu/ops/GrStencilAndCoverPathRenderer.h"
#include "src/gpu/ops/GrStencilPathOp.h"

GrPathRenderer* GrStencilAndCoverPathRenderer::Create(GrResourceProvider* resourceProvider,
                                                      const GrCaps& caps) {
    if (caps.shaderCaps()->pathRenderingSupport() && !caps.avoidStencilBuffers()) {
        return new GrStencilAndCoverPathRenderer(resourceProvider);
    } else {
        return nullptr;
    }
}

GrStencilAndCoverPathRenderer::GrStencilAndCoverPathRenderer(GrResourceProvider* resourceProvider)
    : fResourceProvider(resourceProvider) {
}

GrPathRenderer::CanDrawPath
GrStencilAndCoverPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
    SkASSERT(!args.fTargetIsWrappedVkSecondaryCB);
    // GrPath doesn't support hairline paths. An arbitrary path effect could produce a hairline
    // path.
    if (args.fShape->style().strokeRec().isHairlineStyle() ||
        args.fShape->style().hasNonDashPathEffect() ||
        args.fHasUserStencilSettings) {
        return CanDrawPath::kNo;
    }
    if (GrAAType::kCoverage == args.fAAType && !args.fProxy->canUseMixedSamples(*args.fCaps)) {
        // We rely on a mixed sampled stencil buffer to implement coverage AA.
        return CanDrawPath::kNo;
    }
    return CanDrawPath::kYes;
}

static sk_sp<GrPath> get_gr_path(GrResourceProvider* resourceProvider, const GrShape& shape) {
    GrUniqueKey key;
    bool isVolatile;
    GrPath::ComputeKey(shape, &key, &isVolatile);
    sk_sp<GrPath> path;
    if (!isVolatile) {
        path = resourceProvider->findByUniqueKey<GrPath>(key);
    }
    if (!path) {
        SkPath skPath;
        shape.asPath(&skPath);
        path = resourceProvider->createPath(skPath, shape.style());
        if (!isVolatile) {
            resourceProvider->assignUniqueKeyToResource(key, path.get());
        }
    } else {
#ifdef SK_DEBUG
        SkPath skPath;
        shape.asPath(&skPath);
        SkASSERT(path->isEqualTo(skPath, shape.style()));
#endif
    }
    return path;
}

void GrStencilAndCoverPathRenderer::onStencilPath(const StencilPathArgs& args) {
    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                              "GrStencilAndCoverPathRenderer::onStencilPath");
    sk_sp<GrPath> p(get_gr_path(fResourceProvider, *args.fShape));
    args.fRenderTargetContext->priv().stencilPath(
            *args.fClip, args.fDoStencilMSAA, *args.fViewMatrix, std::move(p));
}

bool GrStencilAndCoverPathRenderer::onDrawPath(const DrawPathArgs& args) {
    GR_AUDIT_TRAIL_AUTO_FRAME(args.fRenderTargetContext->auditTrail(),
                              "GrStencilAndCoverPathRenderer::onDrawPath");
    SkASSERT(!args.fShape->style().strokeRec().isHairlineStyle());

    const SkMatrix& viewMatrix = *args.fViewMatrix;

    bool doStencilMSAA = GrAAType::kNone != args.fAAType;

    sk_sp<GrPath> path(get_gr_path(fResourceProvider, *args.fShape));

    if (args.fShape->inverseFilled()) {
        SkMatrix vmi;
        if (!viewMatrix.invert(&vmi)) {
            return true;
        }

        SkRect devBounds = SkRect::MakeIWH(args.fRenderTargetContext->width(),
                                           args.fRenderTargetContext->height()); // Inverse fill.

        // fake inverse with a stencil and cover
        GrAppliedClip appliedClip;
        if (!args.fClip->apply(
                args.fContext, args.fRenderTargetContext, doStencilMSAA, true, &appliedClip,
                &devBounds)) {
            return true;
        }
        GrStencilClip stencilClip(appliedClip.stencilStackID());
        if (appliedClip.scissorState().enabled()) {
            stencilClip.fixedClip().setScissor(appliedClip.scissorState().rect());
        }
        if (appliedClip.windowRectsState().enabled()) {
            stencilClip.fixedClip().setWindowRectangles(appliedClip.windowRectsState().windows(),
                                                        appliedClip.windowRectsState().mode());
        }
        // Just ignore the analytic FPs (if any) during the stencil pass. They will still clip the
        // final draw and it is meaningless to multiply by coverage when drawing to stencil.
        args.fRenderTargetContext->priv().stencilPath(
                stencilClip, GrAA(doStencilMSAA), viewMatrix, std::move(path));

        {
            static constexpr GrUserStencilSettings kInvertedCoverPass(
                GrUserStencilSettings::StaticInit<
                    0x0000,
                    // We know our rect will hit pixels outside the clip and the user bits will
                    // be 0 outside the clip. So we can't just fill where the user bits are 0. We
                    // also need to check that the clip bit is set.
                    GrUserStencilTest::kEqualIfInClip,
                    0xffff,
                    GrUserStencilOp::kKeep,
                    GrUserStencilOp::kZero,
                    0xffff>()
            );

            SkRect coverBounds;
            // mapRect through persp matrix may not be correct
            if (!viewMatrix.hasPerspective()) {
                vmi.mapRect(&coverBounds, devBounds);
                // theoretically could set bloat = 0, instead leave it because of matrix inversion
                // precision.
                SkScalar bloat = viewMatrix.getMaxScale() * SK_ScalarHalf;
                coverBounds.outset(bloat, bloat);
            } else {
                coverBounds = devBounds;
            }
            const SkMatrix& coverMatrix = !viewMatrix.hasPerspective() ? viewMatrix : SkMatrix::I();
            const SkMatrix& localMatrix = !viewMatrix.hasPerspective() ? SkMatrix::I() : vmi;

            // We have to suppress enabling MSAA for mixed samples or we will get seams due to
            // coverage modulation along the edge where two triangles making up the rect meet.
            GrAA doStencilMSAA = GrAA::kNo;
            if (GrAAType::kMSAA == args.fAAType) {
                doStencilMSAA = GrAA::kYes;
            }
            args.fRenderTargetContext->priv().stencilRect(
                    *args.fClip, &kInvertedCoverPass, std::move(args.fPaint), doStencilMSAA,
                    coverMatrix, coverBounds, &localMatrix);
        }
    } else {
        std::unique_ptr<GrDrawOp> op = GrDrawPathOp::Make(
                args.fContext, viewMatrix, std::move(args.fPaint), GrAA(doStencilMSAA),
                std::move(path));
        args.fRenderTargetContext->addDrawOp(*args.fClip, std::move(op));
    }

    return true;
}
