blob: fcdc66c84362813cea4e881e7ffe5b9ddfbb9277 [file] [log] [blame]
bsalomon@google.com170bd792012-12-05 22:26:11 +00001/*
csmartdalton77f2fae2016-08-08 09:55:06 -07002 * Copyright 2016 Google Inc.
bsalomon@google.com170bd792012-12-05 22:26:11 +00003 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
george9eb182a2014-06-20 12:01:06 -07008#ifndef GrReducedClip_DEFINED
9#define GrReducedClip_DEFINED
10
Chris Dalton584a79a2017-11-15 13:14:01 -070011#include "GrFragmentProcessor.h"
csmartdaltonbf4a8f92016-09-06 10:01:06 -070012#include "GrWindowRectangles.h"
bsalomon@google.com170bd792012-12-05 22:26:11 +000013#include "SkClipStack.h"
14#include "SkTLList.h"
15
csmartdaltonbde96c62016-08-31 12:54:46 -070016class GrContext;
Chris Daltona32a3c32017-12-05 10:05:21 -070017class GrCoverageCountingPathRenderer;
Brian Osman11052242016-10-27 14:47:55 -040018class GrRenderTargetContext;
csmartdaltonbde96c62016-08-31 12:54:46 -070019
csmartdalton77f2fae2016-08-08 09:55:06 -070020/**
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 */
tfarinabf54e492014-10-23 17:47:18 -070024class SK_API GrReducedClip {
25public:
Brian Salomonc3833b42018-07-09 18:23:58 +000026 using Element = SkClipStack::Element;
27 using ElementList = SkTLList<SkClipStack::Element, 16>;
Chris Dalton79471932017-10-27 01:50:57 -060028
Chris Dalton4c458b12018-06-16 17:22:59 -060029 GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrCaps* caps,
Chris Dalton1dec19a2018-04-27 13:05:19 -060030 int maxWindowRectangles = 0, int maxAnalyticFPs = 0, int maxCCPRClipPaths = 0);
Chris Daltona32a3c32017-12-05 10:05:21 -070031
32 enum class InitialState : bool {
33 kAllIn,
34 kAllOut
35 };
36
37 InitialState initialState() const { return fInitialState; }
csmartdalton77f2fae2016-08-08 09:55:06 -070038
39 /**
Chris Dalton79471932017-10-27 01:50:57 -060040 * If hasScissor() is true, the clip mask is not valid outside this rect and the caller must
41 * enforce this scissor during draw.
csmartdalton77f2fae2016-08-08 09:55:06 -070042 */
Chris Dalton79471932017-10-27 01:50:57 -060043 const SkIRect& scissor() const { SkASSERT(fHasScissor); return fScissor; }
44 int left() const { return this->scissor().left(); }
45 int top() const { return this->scissor().top(); }
46 int width() const { return this->scissor().width(); }
47 int height() const { return this->scissor().height(); }
csmartdaltond211e782016-08-15 11:17:19 -070048
49 /**
Chris Dalton79471932017-10-27 01:50:57 -060050 * Indicates whether scissor() is defined. It will always be defined if the maskElements() are
csmartdaltond211e782016-08-15 11:17:19 -070051 * nonempty.
52 */
Chris Dalton79471932017-10-27 01:50:57 -060053 bool hasScissor() const { return fHasScissor; }
csmartdalton77f2fae2016-08-08 09:55:06 -070054
csmartdaltonbf4a8f92016-09-06 10:01:06 -070055 /**
Chris Dalton79471932017-10-27 01:50:57 -060056 * If nonempty, the clip mask is not valid inside these windows and the caller must clip them
57 * out using the window rectangles GPU extension.
csmartdaltonbf4a8f92016-09-06 10:01:06 -070058 */
59 const GrWindowRectangles& windowRectangles() const { return fWindowRects; }
60
Chris Dalton79471932017-10-27 01:50:57 -060061 /**
62 * An ordered list of clip elements that could not be skipped or implemented by other means. If
63 * nonempty, the caller must create an alpha and/or stencil mask for these elements and apply it
64 * during draw.
65 */
66 const ElementList& maskElements() const { return fMaskElements; }
bsalomon@google.com170bd792012-12-05 22:26:11 +000067
csmartdalton77f2fae2016-08-08 09:55:06 -070068 /**
Brian Salomonc3833b42018-07-09 18:23:58 +000069 * If maskElements() are nonempty, uniquely identifies the region of the clip mask that falls
70 * inside of scissor().
71 *
72 * NOTE: since clip elements might fall outside the query bounds, different regions of the same
73 * clip stack might have more or less restrictive IDs.
74 *
75 * FIXME: this prevents us from reusing a sub-rect of a perfectly good mask when that rect has
76 * been assigned a less restrictive ID.
csmartdalton77f2fae2016-08-08 09:55:06 -070077 */
Brian Salomonc3833b42018-07-09 18:23:58 +000078 uint32_t maskGenID() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskGenID; }
csmartdalton77f2fae2016-08-08 09:55:06 -070079
80 /**
Chris Dalton79471932017-10-27 01:50:57 -060081 * Indicates whether antialiasing is required to process any of the mask elements.
csmartdalton8d3f92a2016-08-17 09:39:38 -070082 */
Chris Dalton79471932017-10-27 01:50:57 -060083 bool maskRequiresAA() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskRequiresAA; }
csmartdalton77f2fae2016-08-08 09:55:06 -070084
Chris Daltonc5348082018-03-30 15:59:38 +000085 bool drawAlphaClipMask(GrRenderTargetContext*) const;
Brian Salomon9a767722017-03-13 17:57:28 -040086 bool drawStencilClipMask(GrContext*, GrRenderTargetContext*) const;
csmartdaltonbde96c62016-08-31 12:54:46 -070087
Chris Daltona32a3c32017-12-05 10:05:21 -070088 int numAnalyticFPs() const { return fAnalyticFPs.count() + fCCPRClipPaths.count(); }
89
90 /**
91 * Called once the client knows the ID of the opList that the clip FPs will operate in. This
92 * method finishes any outstanding work that was waiting for the opList ID, then detaches and
93 * returns this class's list of FPs that complete the clip.
94 *
95 * NOTE: this must be called AFTER producing the clip mask (if any) because draw calls on
96 * the render target context, surface allocations, and even switching render targets (pre MDB)
97 * may cause flushes or otherwise change which opList the actual draw is going into.
98 */
Chris Dalton1dec19a2018-04-27 13:05:19 -060099 std::unique_ptr<GrFragmentProcessor> finishAndDetachAnalyticFPs(GrCoverageCountingPathRenderer*,
Chris Dalton4c458b12018-06-16 17:22:59 -0600100 uint32_t opListID, int rtWidth,
101 int rtHeight);
Chris Daltona32a3c32017-12-05 10:05:21 -0700102
csmartdalton77f2fae2016-08-08 09:55:06 -0700103private:
Chris Dalton584a79a2017-11-15 13:14:01 -0700104 void walkStack(const SkClipStack&, const SkRect& queryBounds);
csmartdalton5ecbbbe2016-08-23 13:26:40 -0700105
Chris Dalton79471932017-10-27 01:50:57 -0600106 enum class ClipResult {
107 kNotClipped,
108 kClipped,
109 kMadeEmpty
110 };
111
Chris Daltona32a3c32017-12-05 10:05:21 -0700112 // Intersects the clip with the element's interior, regardless of inverse fill type.
Chris Dalton79471932017-10-27 01:50:57 -0600113 // NOTE: do not call for elements followed by ops that can grow the clip.
Brian Salomonc3833b42018-07-09 18:23:58 +0000114 ClipResult clipInsideElement(const Element*);
Chris Dalton79471932017-10-27 01:50:57 -0600115
Chris Daltona32a3c32017-12-05 10:05:21 -0700116 // Intersects the clip with the element's exterior, regardless of inverse fill type.
Chris Dalton79471932017-10-27 01:50:57 -0600117 // NOTE: do not call for elements followed by ops that can grow the clip.
Brian Salomonc3833b42018-07-09 18:23:58 +0000118 ClipResult clipOutsideElement(const Element*);
Chris Dalton79471932017-10-27 01:50:57 -0600119
120 void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
Chris Dalton584a79a2017-11-15 13:14:01 -0700121
122 enum class Invert : bool {
Chris Dalton3b51df12017-11-27 14:33:06 -0700123 kNo = false,
124 kYes = true
Chris Dalton584a79a2017-11-15 13:14:01 -0700125 };
126
Chris Daltona32a3c32017-12-05 10:05:21 -0700127 static GrClipEdgeType GetClipEdgeType(Invert, GrAA);
128 ClipResult addAnalyticFP(const SkRect& deviceSpaceRect, Invert, GrAA);
129 ClipResult addAnalyticFP(const SkRRect& deviceSpaceRRect, Invert, GrAA);
130 ClipResult addAnalyticFP(const SkPath& deviceSpacePath, Invert, GrAA);
Chris Dalton584a79a2017-11-15 13:14:01 -0700131
Chris Dalton79471932017-10-27 01:50:57 -0600132 void makeEmpty();
133
Chris Dalton4c458b12018-06-16 17:22:59 -0600134 const GrCaps* fCaps;
Chris Dalton584a79a2017-11-15 13:14:01 -0700135 const int fMaxWindowRectangles;
136 const int fMaxAnalyticFPs;
Chris Dalton1dec19a2018-04-27 13:05:19 -0600137 const int fMaxCCPRClipPaths;
Chris Daltona32a3c32017-12-05 10:05:21 -0700138
139 InitialState fInitialState;
Chris Dalton584a79a2017-11-15 13:14:01 -0700140 SkIRect fScissor;
141 bool fHasScissor;
142 SkRect fAAClipRect;
Brian Salomonc3833b42018-07-09 18:23:58 +0000143 uint32_t fAAClipRectGenID; // GenID the mask will have if includes the AA clip rect.
Chris Dalton584a79a2017-11-15 13:14:01 -0700144 GrWindowRectangles fWindowRects;
Chris Dalton584a79a2017-11-15 13:14:01 -0700145 ElementList fMaskElements;
Brian Salomonc3833b42018-07-09 18:23:58 +0000146 uint32_t fMaskGenID;
Chris Dalton584a79a2017-11-15 13:14:01 -0700147 bool fMaskRequiresAA;
Chris Daltona32a3c32017-12-05 10:05:21 -0700148 SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fAnalyticFPs;
149 SkSTArray<4, SkPath> fCCPRClipPaths; // Will convert to FPs once we have an opList ID for CCPR.
bsalomon@google.com170bd792012-12-05 22:26:11 +0000150};
151
george9eb182a2014-06-20 12:01:06 -0700152#endif