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 "src/core/SkClipStack.h" 12 #include "src/core/SkTLList.h" 13 #include "src/gpu/GrFragmentProcessor.h" 14 #include "src/gpu/GrWindowRectangles.h" 15 16 class GrCoverageCountingPathRenderer; 17 class GrRecordingContext; 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 GrReducedClip { 25 public: 26 using Element = SkClipStack::Element; 27 using ElementList = SkTLList<SkClipStack::Element, 16>; 28 29 GrReducedClip(const SkClipStack&, const SkRect& queryBounds, const GrCaps* caps, 30 int maxWindowRectangles = 0, int maxAnalyticElements = 0, 31 int maxCCPRClipPaths = 0); 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 * Indicates if there is a clip shader, representing the merge of all shader elements of the 58 * original stack. 59 */ hasShader()60 bool hasShader() const { return SkToBool(fShader); } shader()61 sk_sp<SkShader> shader() const { SkASSERT(fShader); return fShader; } 62 63 /** 64 * 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. 66 */ windowRectangles()67 const GrWindowRectangles& windowRectangles() const { return fWindowRects; } 68 69 /** 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 */ maskElements()74 const ElementList& maskElements() const { return fMaskElements; } 75 76 /** 77 * 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. 85 */ maskGenID()86 uint32_t maskGenID() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskGenID; } 87 88 /** 89 * Indicates whether antialiasing is required to process any of the mask elements. 90 */ maskRequiresAA()91 bool maskRequiresAA() const { SkASSERT(!fMaskElements.isEmpty()); return fMaskRequiresAA; } 92 93 bool drawAlphaClipMask(GrRenderTargetContext*) const; 94 bool drawStencilClipMask(GrRecordingContext*, GrRenderTargetContext*) const; 95 96 int numAnalyticElements() const; 97 98 /** 99 * 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 101 * 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) 105 * may cause flushes or otherwise change which opsTask the actual draw is going into. 106 */ 107 std::unique_ptr<GrFragmentProcessor> finishAndDetachAnalyticElements( 108 GrRecordingContext*, const SkMatrixProvider& matrixProvider, 109 GrCoverageCountingPathRenderer*, uint32_t opsTaskID); 110 111 private: 112 void walkStack(const SkClipStack&, const SkRect& queryBounds); 113 114 enum class ClipResult { 115 kNotClipped, 116 kClipped, 117 kMadeEmpty 118 }; 119 120 // Intersects the clip with the element's interior, regardless of inverse fill type. 121 // NOTE: do not call for elements followed by ops that can grow the clip. 122 ClipResult clipInsideElement(const Element*); 123 124 // Intersects the clip with the element's exterior, regardless of inverse fill type. 125 // NOTE: do not call for elements followed by ops that can grow the clip. 126 ClipResult clipOutsideElement(const Element*); 127 128 void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA); 129 130 enum class Invert : bool { 131 kNo = false, 132 kYes = true 133 }; 134 135 static GrClipEdgeType GetClipEdgeType(Invert, GrAA); 136 ClipResult addAnalyticRect(const SkRect& deviceSpaceRect, Invert, GrAA); 137 ClipResult addAnalyticRRect(const SkRRect& deviceSpaceRRect, Invert, GrAA); 138 ClipResult addAnalyticPath(const SkPath& deviceSpacePath, Invert, GrAA); 139 140 void makeEmpty(); 141 142 const GrCaps* fCaps; 143 const int fMaxWindowRectangles; 144 const int fMaxAnalyticElements; 145 const int fMaxCCPRClipPaths; 146 147 InitialState fInitialState; 148 SkIRect fScissor; 149 bool fHasScissor = false; 150 SkRect fAAClipRect; 151 uint32_t fAAClipRectGenID = SK_InvalidGenID; // the GenID that the mask will have if the AA 152 // clip-rect is included 153 GrWindowRectangles fWindowRects; 154 ElementList fMaskElements; 155 uint32_t fMaskGenID = SK_InvalidGenID; 156 bool fMaskRequiresAA = false; 157 std::unique_ptr<GrFragmentProcessor> fAnalyticFP; 158 int fNumAnalyticElements = 0; 159 SkSTArray<4, SkPath> fCCPRClipPaths; // Converted to FPs once we have an opsTask ID for CCPR. 160 // 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; 163 }; 164 165 #endif 166