• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrFragmentProcessor.h"
12 #include "GrWindowRectangles.h"
13 #include "SkClipStack.h"
14 #include "SkTLList.h"
15 
16 class GrContext;
17 class GrCoverageCountingPathRenderer;
18 class GrRenderTargetContext;
19 
20 /**
21  * This class takes a clip stack and produces a reduced set of elements that are equivalent to
22  * applying that full stack within a specified query rectangle.
23  */
24 class SK_API GrReducedClip {
25 public:
26     using Element = SkClipStack::Element;
27     using ElementList = SkTLList<SkClipStack::Element, 16>;
28 
29     GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrShaderCaps* caps,
30                   int maxWindowRectangles = 0, int maxAnalyticFPs = 0,
31                   GrCoverageCountingPathRenderer* = nullptr);
32 
33     enum class InitialState : bool {
34         kAllIn,
35         kAllOut
36     };
37 
initialState()38     InitialState initialState() const { return fInitialState; }
39 
40     /**
41      * If hasScissor() is true, the clip mask is not valid outside this rect and the caller must
42      * enforce this scissor during draw.
43      */
scissor()44     const SkIRect& scissor() const { SkASSERT(fHasScissor); return fScissor; }
left()45     int left() const { return this->scissor().left(); }
top()46     int top() const { return this->scissor().top(); }
width()47     int width() const { return this->scissor().width(); }
height()48     int height() const { return this->scissor().height(); }
49 
50     /**
51      * Indicates whether scissor() is defined. It will always be defined if the maskElements() are
52      * nonempty.
53      */
hasScissor()54     bool hasScissor() const { return fHasScissor; }
55 
56     /**
57      * If nonempty, the clip mask is not valid inside these windows and the caller must clip them
58      * out using the window rectangles GPU extension.
59      */
windowRectangles()60     const GrWindowRectangles& windowRectangles() const { return fWindowRects; }
61 
62     /**
63      * An ordered list of clip elements that could not be skipped or implemented by other means. If
64      * nonempty, the caller must create an alpha and/or stencil mask for these elements and apply it
65      * during draw.
66      */
maskElements()67     const ElementList& maskElements() const { return fMaskElements; }
68 
69     /**
70      * If maskElements() are nonempty, uniquely identifies the region of the clip mask that falls
71      * inside of scissor().
72      *
73      * NOTE: since clip elements might fall outside the query bounds, different regions of the same
74      * clip stack might have more or less restrictive IDs.
75      *
76      * FIXME: this prevents us from reusing a sub-rect of a perfectly good mask when that rect has
77      * been assigned a less restrictive ID.
78      */
maskGenID()79     uint32_t maskGenID() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskGenID; }
80 
81     /**
82      * Indicates whether antialiasing is required to process any of the mask elements.
83      */
maskRequiresAA()84     bool maskRequiresAA() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskRequiresAA; }
85 
86     bool drawAlphaClipMask(GrRenderTargetContext*) const;
87     bool drawStencilClipMask(GrContext*, GrRenderTargetContext*) const;
88 
numAnalyticFPs()89     int numAnalyticFPs() const { return fAnalyticFPs.count() + fCCPRClipPaths.count(); }
90 
91     /**
92      * Called once the client knows the ID of the opList that the clip FPs will operate in. This
93      * method finishes any outstanding work that was waiting for the opList ID, then detaches and
94      * returns this class's list of FPs that complete the clip.
95      *
96      * NOTE: this must be called AFTER producing the clip mask (if any) because draw calls on
97      * the render target context, surface allocations, and even switching render targets (pre MDB)
98      * may cause flushes or otherwise change which opList the actual draw is going into.
99      */
100     std::unique_ptr<GrFragmentProcessor> finishAndDetachAnalyticFPs(GrProxyProvider*,
101                                                                     uint32_t opListID,
102                                                                     int rtWidth, int rtHeight);
103 
104 private:
105     void walkStack(const SkClipStack&, const SkRect& queryBounds);
106 
107     enum class ClipResult {
108         kNotClipped,
109         kClipped,
110         kMadeEmpty
111     };
112 
113     // Intersects the clip with the element's interior, regardless of inverse fill type.
114     // NOTE: do not call for elements followed by ops that can grow the clip.
115     ClipResult clipInsideElement(const Element*);
116 
117     // Intersects the clip with the element's exterior, regardless of inverse fill type.
118     // NOTE: do not call for elements followed by ops that can grow the clip.
119     ClipResult clipOutsideElement(const Element*);
120 
121     void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
122 
123     enum class Invert : bool {
124         kNo = false,
125         kYes = true
126     };
127 
128     static GrClipEdgeType GetClipEdgeType(Invert, GrAA);
129     ClipResult addAnalyticFP(const SkRect& deviceSpaceRect, Invert, GrAA);
130     ClipResult addAnalyticFP(const SkRRect& deviceSpaceRRect, Invert, GrAA);
131     ClipResult addAnalyticFP(const SkPath& deviceSpacePath, Invert, GrAA);
132 
133     void makeEmpty();
134 
135     const GrShaderCaps* fCaps;
136     const int fMaxWindowRectangles;
137     const int fMaxAnalyticFPs;
138     GrCoverageCountingPathRenderer* const fCCPR;
139 
140     InitialState fInitialState;
141     SkIRect fScissor;
142     bool fHasScissor;
143     SkRect fAAClipRect;
144     uint32_t fAAClipRectGenID; // GenID the mask will have if includes the AA clip rect.
145     GrWindowRectangles fWindowRects;
146     ElementList fMaskElements;
147     uint32_t fMaskGenID;
148     bool fMaskRequiresAA;
149     SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fAnalyticFPs;
150     SkSTArray<4, SkPath> fCCPRClipPaths; // Will convert to FPs once we have an opList ID for CCPR.
151 };
152 
153 #endif
154