1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrReducedClip_DEFINED
9#define GrReducedClip_DEFINED
10
11#include "GrWindowRectangles.h"
12#include "SkClipStack.h"
13#include "SkTLList.h"
14
15class GrContext;
16class GrRenderTargetContext;
17
18/**
19 * This class takes a clip stack and produces a reduced set of elements that are equivalent to
20 * applying that full stack within a specified query rectangle.
21 */
22class SK_API GrReducedClip {
23public:
24    GrReducedClip(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles = 0);
25
26    /**
27     * If hasIBounds() is true, this is the bounding box within which the clip elements are valid.
28     * The caller must not modify any pixels outside this box. Undefined if hasIBounds() is false.
29     */
30    const SkIRect& ibounds() const { SkASSERT(fHasIBounds); return fIBounds; }
31    int left() const { return this->ibounds().left(); }
32    int top() const { return this->ibounds().top(); }
33    int width() const { return this->ibounds().width(); }
34    int height() const { return this->ibounds().height(); }
35
36    /**
37     * Indicates whether ibounds() are defined. They will always be defined if the elements() are
38     * nonempty.
39     */
40    bool hasIBounds() const { return fHasIBounds; }
41
42    /**
43     * If nonempty, this is a set of "exclusive" windows within which the clip elements are NOT
44     * valid. The caller must not modify any pixels inside these windows.
45     */
46    const GrWindowRectangles& windowRectangles() const { return fWindowRects; }
47
48    typedef SkTLList<SkClipStack::Element, 16> ElementList;
49
50    /**
51     * Populated with a minimal list of elements required to fully implement the clip.
52     */
53    const ElementList& elements() const { return fElements; }
54
55    /**
56     * If elements() are nonempty, uniquely identifies the list of elements within ibounds().
57     * Otherwise undefined.
58     */
59    int32_t elementsGenID() const { SkASSERT(!fElements.isEmpty()); return fElementsGenID; }
60
61    /**
62     * Indicates whether antialiasing is required to process any of the clip elements.
63     */
64    bool requiresAA() const { return fRequiresAA; }
65
66    enum class InitialState : bool {
67        kAllIn,
68        kAllOut
69    };
70
71    InitialState initialState() const { return fInitialState; }
72
73    bool drawAlphaClipMask(GrRenderTargetContext*) const;
74    bool drawStencilClipMask(GrContext*, GrRenderTargetContext*) const;
75
76private:
77    void walkStack(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles);
78    void addInteriorWindowRectangles(int maxWindowRectangles);
79    void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
80    bool intersectIBounds(const SkIRect&);
81
82    SkIRect              fIBounds;
83    bool                 fHasIBounds;
84    GrWindowRectangles   fWindowRects;
85    ElementList          fElements;
86    int32_t              fElementsGenID;
87    bool                 fRequiresAA;
88    InitialState         fInitialState;
89};
90
91#endif
92