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

#ifndef GrReducedClip_DEFINED
#define GrReducedClip_DEFINED

#include "GrFragmentProcessor.h"
#include "GrWindowRectangles.h"
#include "SkClipStack.h"
#include "SkTLList.h"

class GrContext;
class GrCoverageCountingPathRenderer;
class GrRenderTargetContext;

/**
 * This class takes a clip stack and produces a reduced set of elements that are equivalent to
 * applying that full stack within a specified query rectangle.
 */
class SK_API GrReducedClip {
public:
    using Element = SkClipStack::Element;
    using ElementList = SkTLList<SkClipStack::Element, 16>;

    GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrShaderCaps* caps,
                  int maxWindowRectangles = 0, int maxAnalyticFPs = 0, int maxCCPRClipPaths = 0);

    enum class InitialState : bool {
        kAllIn,
        kAllOut
    };

    InitialState initialState() const { return fInitialState; }

    /**
     * If hasScissor() is true, the clip mask is not valid outside this rect and the caller must
     * enforce this scissor during draw.
     */
    const SkIRect& scissor() const { SkASSERT(fHasScissor); return fScissor; }
    int left() const { return this->scissor().left(); }
    int top() const { return this->scissor().top(); }
    int width() const { return this->scissor().width(); }
    int height() const { return this->scissor().height(); }

    /**
     * Indicates whether scissor() is defined. It will always be defined if the maskElements() are
     * nonempty.
     */
    bool hasScissor() const { return fHasScissor; }

    /**
     * If nonempty, the clip mask is not valid inside these windows and the caller must clip them
     * out using the window rectangles GPU extension.
     */
    const GrWindowRectangles& windowRectangles() const { return fWindowRects; }

    /**
     * An ordered list of clip elements that could not be skipped or implemented by other means. If
     * nonempty, the caller must create an alpha and/or stencil mask for these elements and apply it
     * during draw.
     */
    const ElementList& maskElements() const { return fMaskElements; }

    /**
     * If maskElements() are nonempty, uniquely identifies the region of the clip mask that falls
     * inside of scissor().
     *
     * NOTE: since clip elements might fall outside the query bounds, different regions of the same
     * clip stack might have more or less restrictive IDs.
     *
     * FIXME: this prevents us from reusing a sub-rect of a perfectly good mask when that rect has
     * been assigned a less restrictive ID.
     */
    uint32_t maskGenID() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskGenID; }

    /**
     * Indicates whether antialiasing is required to process any of the mask elements.
     */
    bool maskRequiresAA() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskRequiresAA; }

    bool drawAlphaClipMask(GrRenderTargetContext*) const;
    bool drawStencilClipMask(GrContext*, GrRenderTargetContext*) const;

    int numAnalyticFPs() const { return fAnalyticFPs.count() + fCCPRClipPaths.count(); }

    /**
     * Called once the client knows the ID of the opList that the clip FPs will operate in. This
     * method finishes any outstanding work that was waiting for the opList ID, then detaches and
     * returns this class's list of FPs that complete the clip.
     *
     * NOTE: this must be called AFTER producing the clip mask (if any) because draw calls on
     * the render target context, surface allocations, and even switching render targets (pre MDB)
     * may cause flushes or otherwise change which opList the actual draw is going into.
     */
    std::unique_ptr<GrFragmentProcessor> finishAndDetachAnalyticFPs(GrCoverageCountingPathRenderer*,
                                                                    GrProxyProvider*,
                                                                    uint32_t opListID,
                                                                    int rtWidth, int rtHeight);

private:
    void walkStack(const SkClipStack&, const SkRect& queryBounds);

    enum class ClipResult {
        kNotClipped,
        kClipped,
        kMadeEmpty
    };

    // Intersects the clip with the element's interior, regardless of inverse fill type.
    // NOTE: do not call for elements followed by ops that can grow the clip.
    ClipResult clipInsideElement(const Element*);

    // Intersects the clip with the element's exterior, regardless of inverse fill type.
    // NOTE: do not call for elements followed by ops that can grow the clip.
    ClipResult clipOutsideElement(const Element*);

    void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);

    enum class Invert : bool {
        kNo = false,
        kYes = true
    };

    static GrClipEdgeType GetClipEdgeType(Invert, GrAA);
    ClipResult addAnalyticFP(const SkRect& deviceSpaceRect, Invert, GrAA);
    ClipResult addAnalyticFP(const SkRRect& deviceSpaceRRect, Invert, GrAA);
    ClipResult addAnalyticFP(const SkPath& deviceSpacePath, Invert, GrAA);

    void makeEmpty();

    const GrShaderCaps* fCaps;
    const int fMaxWindowRectangles;
    const int fMaxAnalyticFPs;
    const int fMaxCCPRClipPaths;

    InitialState fInitialState;
    SkIRect fScissor;
    bool fHasScissor;
    SkRect fAAClipRect;
    uint32_t fAAClipRectGenID; // GenID the mask will have if includes the AA clip rect.
    GrWindowRectangles fWindowRects;
    ElementList fMaskElements;
    uint32_t fMaskGenID;
    bool fMaskRequiresAA;
    SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fAnalyticFPs;
    SkSTArray<4, SkPath> fCCPRClipPaths; // Will convert to FPs once we have an opList ID for CCPR.
};

#endif
