blob: 30cd601dcf2fa98cf1c03bc7b5cac550b0ae8335 [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
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "src/core/SkClipStack.h"
12#include "src/core/SkTLList.h"
13#include "src/gpu/GrFragmentProcessor.h"
14#include "src/gpu/GrWindowRectangles.h"
bsalomon@google.com170bd792012-12-05 22:26:11 +000015
Brian Osmanfe83ab62021-06-19 15:13:02 +000016class GrCoverageCountingPathRenderer;
Robert Phillips6f0e02f2019-02-13 11:02:28 -050017class GrRecordingContext;
Brian Salomoneebe7352020-12-09 16:37:04 -050018class GrSurfaceDrawContext;
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 */
Brian Salomon57f211b2019-08-21 15:21:09 -040024class GrReducedClip {
tfarinabf54e492014-10-23 17:47:18 -070025public:
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
Ethan Nicholaseace9352018-10-15 20:09:54 +000029 GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrCaps* caps,
Brian Osmanfe83ab62021-06-19 15:13:02 +000030 int maxWindowRectangles = 0, int maxAnalyticElements = 0,
31 int maxCCPRClipPaths = 0);
Chris Daltona32a3c32017-12-05 10:05:21 -070032
33 enum class InitialState : bool {
34 kAllIn,
35 kAllOut
36 };
37
38 InitialState initialState() const { return fInitialState; }
csmartdalton77f2fae2016-08-08 09:55:06 -070039
40 /**
Chris Dalton79471932017-10-27 01:50:57 -060041 * If hasScissor() is true, the clip mask is not valid outside this rect and the caller must
42 * enforce this scissor during draw.
csmartdalton77f2fae2016-08-08 09:55:06 -070043 */
Chris Dalton79471932017-10-27 01:50:57 -060044 const SkIRect& scissor() const { SkASSERT(fHasScissor); return fScissor; }
45 int left() const { return this->scissor().left(); }
46 int top() const { return this->scissor().top(); }
47 int width() const { return this->scissor().width(); }
48 int height() const { return this->scissor().height(); }
csmartdaltond211e782016-08-15 11:17:19 -070049
50 /**
Chris Dalton79471932017-10-27 01:50:57 -060051 * Indicates whether scissor() is defined. It will always be defined if the maskElements() are
csmartdaltond211e782016-08-15 11:17:19 -070052 * nonempty.
53 */
Chris Dalton79471932017-10-27 01:50:57 -060054 bool hasScissor() const { return fHasScissor; }
csmartdalton77f2fae2016-08-08 09:55:06 -070055
csmartdaltonbf4a8f92016-09-06 10:01:06 -070056 /**
Michael Ludwig4e221bd2020-06-05 11:29:36 -040057 * Indicates if there is a clip shader, representing the merge of all shader elements of the
58 * original stack.
59 */
60 bool hasShader() const { return SkToBool(fShader); }
61 sk_sp<SkShader> shader() const { SkASSERT(fShader); return fShader; }
62
63 /**
Chris Dalton79471932017-10-27 01:50:57 -060064 * If nonempty, the clip mask is not valid inside these windows and the caller must clip them
65 * out using the window rectangles GPU extension.
csmartdaltonbf4a8f92016-09-06 10:01:06 -070066 */
67 const GrWindowRectangles& windowRectangles() const { return fWindowRects; }
68
Chris Dalton79471932017-10-27 01:50:57 -060069 /**
70 * An ordered list of clip elements that could not be skipped or implemented by other means. If
71 * nonempty, the caller must create an alpha and/or stencil mask for these elements and apply it
72 * during draw.
73 */
74 const ElementList& maskElements() const { return fMaskElements; }
bsalomon@google.com170bd792012-12-05 22:26:11 +000075
csmartdalton77f2fae2016-08-08 09:55:06 -070076 /**
Brian Salomonc3833b42018-07-09 18:23:58 +000077 * If maskElements() are nonempty, uniquely identifies the region of the clip mask that falls
78 * inside of scissor().
79 *
80 * NOTE: since clip elements might fall outside the query bounds, different regions of the same
81 * clip stack might have more or less restrictive IDs.
82 *
83 * FIXME: this prevents us from reusing a sub-rect of a perfectly good mask when that rect has
84 * been assigned a less restrictive ID.
csmartdalton77f2fae2016-08-08 09:55:06 -070085 */
Brian Salomonc3833b42018-07-09 18:23:58 +000086 uint32_t maskGenID() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskGenID; }
csmartdalton77f2fae2016-08-08 09:55:06 -070087
88 /**
Chris Dalton79471932017-10-27 01:50:57 -060089 * Indicates whether antialiasing is required to process any of the mask elements.
csmartdalton8d3f92a2016-08-17 09:39:38 -070090 */
Chris Dalton79471932017-10-27 01:50:57 -060091 bool maskRequiresAA() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskRequiresAA; }
csmartdalton77f2fae2016-08-08 09:55:06 -070092
Brian Salomoneebe7352020-12-09 16:37:04 -050093 bool drawAlphaClipMask(GrSurfaceDrawContext*) const;
94 bool drawStencilClipMask(GrRecordingContext*, GrSurfaceDrawContext*) const;
csmartdaltonbde96c62016-08-31 12:54:46 -070095
John Stiles9e8f4842020-07-09 11:30:05 -040096 int numAnalyticElements() const;
Chris Daltona32a3c32017-12-05 10:05:21 -070097
98 /**
Greg Danielf41b2bd2019-08-22 16:19:24 -040099 * Called once the client knows the ID of the opsTask that the clip FPs will operate in. This
100 * method finishes any outstanding work that was waiting for the opsTask ID, then detaches and
Chris Daltona32a3c32017-12-05 10:05:21 -0700101 * returns this class's list of FPs that complete the clip.
102 *
103 * NOTE: this must be called AFTER producing the clip mask (if any) because draw calls on
104 * the render target context, surface allocations, and even switching render targets (pre MDB)
Greg Danielf41b2bd2019-08-22 16:19:24 -0400105 * may cause flushes or otherwise change which opsTask the actual draw is going into.
Chris Daltona32a3c32017-12-05 10:05:21 -0700106 */
Derek Sollenberger396cd1d2021-04-02 15:44:36 +0000107 GrFPResult finishAndDetachAnalyticElements(GrRecordingContext*, const SkMatrixProvider&
Brian Osmanfe83ab62021-06-19 15:13:02 +0000108 matrixProvider, GrCoverageCountingPathRenderer*,
109 uint32_t opsTaskID);
Chris Daltona32a3c32017-12-05 10:05:21 -0700110
csmartdalton77f2fae2016-08-08 09:55:06 -0700111private:
Chris Dalton584a79a2017-11-15 13:14:01 -0700112 void walkStack(const SkClipStack&, const SkRect& queryBounds);
csmartdalton5ecbbbe2016-08-23 13:26:40 -0700113
Chris Dalton79471932017-10-27 01:50:57 -0600114 enum class ClipResult {
115 kNotClipped,
116 kClipped,
117 kMadeEmpty
118 };
119
Chris Daltona32a3c32017-12-05 10:05:21 -0700120 // Intersects the clip with the element's interior, regardless of inverse fill type.
Chris Dalton79471932017-10-27 01:50:57 -0600121 // NOTE: do not call for elements followed by ops that can grow the clip.
Brian Salomonc3833b42018-07-09 18:23:58 +0000122 ClipResult clipInsideElement(const Element*);
Chris Dalton79471932017-10-27 01:50:57 -0600123
Chris Daltona32a3c32017-12-05 10:05:21 -0700124 // Intersects the clip with the element's exterior, regardless of inverse fill type.
Chris Dalton79471932017-10-27 01:50:57 -0600125 // NOTE: do not call for elements followed by ops that can grow the clip.
Brian Salomonc3833b42018-07-09 18:23:58 +0000126 ClipResult clipOutsideElement(const Element*);
Chris Dalton79471932017-10-27 01:50:57 -0600127
128 void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
Chris Dalton584a79a2017-11-15 13:14:01 -0700129
130 enum class Invert : bool {
Chris Dalton3b51df12017-11-27 14:33:06 -0700131 kNo = false,
132 kYes = true
Chris Dalton584a79a2017-11-15 13:14:01 -0700133 };
134
Chris Daltona32a3c32017-12-05 10:05:21 -0700135 static GrClipEdgeType GetClipEdgeType(Invert, GrAA);
John Stiles9e8f4842020-07-09 11:30:05 -0400136 ClipResult addAnalyticRect(const SkRect& deviceSpaceRect, Invert, GrAA);
137 ClipResult addAnalyticRRect(const SkRRect& deviceSpaceRRect, Invert, GrAA);
138 ClipResult addAnalyticPath(const SkPath& deviceSpacePath, Invert, GrAA);
Chris Dalton584a79a2017-11-15 13:14:01 -0700139
Chris Dalton79471932017-10-27 01:50:57 -0600140 void makeEmpty();
141
Ethan Nicholaseace9352018-10-15 20:09:54 +0000142 const GrCaps* fCaps;
Chris Dalton584a79a2017-11-15 13:14:01 -0700143 const int fMaxWindowRectangles;
John Stiles9e8f4842020-07-09 11:30:05 -0400144 const int fMaxAnalyticElements;
Brian Osmanfe83ab62021-06-19 15:13:02 +0000145 const int fMaxCCPRClipPaths;
Chris Daltona32a3c32017-12-05 10:05:21 -0700146
147 InitialState fInitialState;
Chris Dalton584a79a2017-11-15 13:14:01 -0700148 SkIRect fScissor;
John Stilesc34c6bc2020-07-09 10:16:31 -0400149 bool fHasScissor = false;
Chris Dalton584a79a2017-11-15 13:14:01 -0700150 SkRect fAAClipRect;
John Stilesc34c6bc2020-07-09 10:16:31 -0400151 uint32_t fAAClipRectGenID = SK_InvalidGenID; // the GenID that the mask will have if the AA
152 // clip-rect is included
Chris Dalton584a79a2017-11-15 13:14:01 -0700153 GrWindowRectangles fWindowRects;
Chris Dalton584a79a2017-11-15 13:14:01 -0700154 ElementList fMaskElements;
John Stilesc34c6bc2020-07-09 10:16:31 -0400155 uint32_t fMaskGenID = SK_InvalidGenID;
156 bool fMaskRequiresAA = false;
John Stiles777556a2020-06-19 10:22:31 -0400157 std::unique_ptr<GrFragmentProcessor> fAnalyticFP;
John Stiles9e8f4842020-07-09 11:30:05 -0400158 int fNumAnalyticElements = 0;
Brian Osmanfe83ab62021-06-19 15:13:02 +0000159 SkSTArray<4, SkPath> fCCPRClipPaths; // Converted to FPs once we have an opsTask ID for CCPR.
Michael Ludwig4e221bd2020-06-05 11:29:36 -0400160 // Will be the combination of all kShader elements or null if there's no clip shader.
161 // Does not count against the analytic FP limit.
162 sk_sp<SkShader> fShader;
bsalomon@google.com170bd792012-12-05 22:26:11 +0000163};
164
george9eb182a2014-06-20 12:01:06 -0700165#endif