• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 GrPathRenderer_DEFINED
9 #define GrPathRenderer_DEFINED
10 
11 #include "GrCaps.h"
12 #include "GrRenderTargetContext.h"
13 #include "GrPaint.h"
14 #include "GrShape.h"
15 #include "GrUserStencilSettings.h"
16 
17 #include "SkDrawProcs.h"
18 #include "SkTArray.h"
19 
20 class SkPath;
21 class GrFixedClip;
22 struct GrPoint;
23 
24 /**
25  *  Base class for drawing paths into a GrOpList.
26  */
27 class SK_API GrPathRenderer : public SkRefCnt {
28 public:
29     GrPathRenderer();
30 
31     /**
32      * A caller may wish to use a path renderer to draw a path into the stencil buffer. However,
33      * the path renderer itself may require use of the stencil buffer. Also a path renderer may
34      * use a GrProcessor coverage stage that sets coverage to zero to eliminate pixels that are
35      * covered by bounding geometry but outside the path. These exterior pixels would still be
36      * rendered into the stencil.
37      *
38      * A GrPathRenderer can provide three levels of support for stenciling paths:
39      * 1) kNoRestriction: This is the most general. The caller passes a GrPaint and calls drawPath().
40      *                    The path is rendered exactly as the draw state indicates including support
41      *                    for simultaneous color and stenciling with arbitrary stenciling rules.
42      *                    Pixels partially covered by AA paths are affected by the stencil settings.
43      * 2) kStencilOnly: The path renderer cannot apply arbitrary stencil rules nor shade and stencil
44      *                  simultaneously. The path renderer does support the stencilPath() function
45      *                  which performs no color writes and writes a non-zero stencil value to pixels
46      *                  covered by the path.
47      * 3) kNoSupport: This path renderer cannot be used to stencil the path.
48      */
49     enum StencilSupport {
50         kNoSupport_StencilSupport,
51         kStencilOnly_StencilSupport,
52         kNoRestriction_StencilSupport,
53     };
54 
55     /**
56      * This function is to get the stencil support for a particular path. The path's fill must
57      * not be an inverse type. The path will always be filled and not stroked.
58      *
59      * @param shape   the shape that will be drawn. Must be simple fill styled and non-inverse
60      *                filled.
61      */
getStencilSupport(const GrShape & shape)62     StencilSupport getStencilSupport(const GrShape& shape) const {
63         SkDEBUGCODE(SkPath path;)
64         SkDEBUGCODE(shape.asPath(&path);)
65         SkASSERT(shape.style().isSimpleFill());
66         SkASSERT(!path.isInverseFillType());
67         return this->onGetStencilSupport(shape);
68     }
69 
70     /** Args to canDrawPath()
71      *
72      * fCaps             The context caps
73      * fPipelineBuilder  The pipelineBuilder
74      * fViewMatrix       The viewMatrix
75      * fShape            The shape to draw
76      * fAntiAlias        The type of anti aliasing required.
77      */
78     struct CanDrawPathArgs {
79         const GrCaps*               fCaps;
80         const SkMatrix*             fViewMatrix;
81         const GrShape*              fShape;
82         GrAAType                    fAAType;
83 
84         // These next two are only used by GrStencilAndCoverPathRenderer
85         bool                        fHasUserStencilSettings;
86 
87 #ifdef SK_DEBUG
validateCanDrawPathArgs88         void validate() const {
89             SkASSERT(fCaps);
90             SkASSERT(fViewMatrix);
91             SkASSERT(fShape);
92         }
93 #endif
94     };
95 
96     /**
97      * Returns true if this path renderer is able to render the path. Returning false allows the
98      * caller to fallback to another path renderer This function is called when searching for a path
99      * renderer capable of rendering a path.
100      *
101      * @return  true if the path can be drawn by this object, false otherwise.
102      */
canDrawPath(const CanDrawPathArgs & args)103     bool canDrawPath(const CanDrawPathArgs& args) const {
104         SkDEBUGCODE(args.validate();)
105         return this->onCanDrawPath(args);
106     }
107 
108     /**
109      * Args to drawPath()
110      *
111      * fTarget                The target that the path will be rendered to
112      * fResourceProvider      The resource provider for creating gpu resources to render the path
113      * fPipelineBuilder       The pipelineBuilder
114      * fClip                  The clip
115      * fColor                 Color to render with
116      * fViewMatrix            The viewMatrix
117      * fShape                 The shape to draw
118      * fAAtype                true if anti-aliasing is required.
119      * fGammaCorrect          true if gamma-correct rendering is to be used.
120      */
121     struct DrawPathArgs {
122         GrContext*                   fContext;
123         GrPaint&&                    fPaint;
124         const GrUserStencilSettings* fUserStencilSettings;
125         GrRenderTargetContext*       fRenderTargetContext;
126         const GrClip*                fClip;
127         const SkMatrix*              fViewMatrix;
128         const GrShape*               fShape;
129         GrAAType                     fAAType;
130         bool                         fGammaCorrect;
131 #ifdef SK_DEBUG
validateDrawPathArgs132         void validate() const {
133             SkASSERT(fContext);
134             SkASSERT(fUserStencilSettings);
135             SkASSERT(fRenderTargetContext);
136             SkASSERT(fClip);
137             SkASSERT(fViewMatrix);
138             SkASSERT(fShape);
139         }
140 #endif
141     };
142 
143     /**
144      * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then
145      * the subclass must respect the stencil settings.
146      */
drawPath(const DrawPathArgs & args)147     bool drawPath(const DrawPathArgs& args) {
148         SkDEBUGCODE(args.validate();)
149 #ifdef SK_DEBUG
150         CanDrawPathArgs canArgs;
151         canArgs.fCaps = args.fContext->caps();
152         canArgs.fViewMatrix = args.fViewMatrix;
153         canArgs.fShape = args.fShape;
154         canArgs.fAAType = args.fAAType;
155 
156         canArgs.fHasUserStencilSettings = !args.fUserStencilSettings->isUnused();
157         SkASSERT(!(canArgs.fAAType == GrAAType::kMSAA &&
158                    GrFSAAType::kUnifiedMSAA != args.fRenderTargetContext->fsaaType()));
159         SkASSERT(!(canArgs.fAAType == GrAAType::kMixedSamples &&
160                    GrFSAAType::kMixedSamples != args.fRenderTargetContext->fsaaType()));
161         SkASSERT(this->canDrawPath(canArgs));
162         if (!args.fUserStencilSettings->isUnused()) {
163             SkPath path;
164             args.fShape->asPath(&path);
165             SkASSERT(args.fShape->style().isSimpleFill());
166             SkASSERT(kNoRestriction_StencilSupport == this->getStencilSupport(*args.fShape));
167         }
168 #endif
169         return this->onDrawPath(args);
170     }
171 
172     /* Args to stencilPath().
173      *
174      * fResourceProvider      The resource provider for creating gpu resources to render the path
175      * fRenderTargetContext   The target of the draws
176      * fViewMatrix            Matrix applied to the path.
177      * fPath                  The path to draw.
178      * fAAType                The type of AA, cannot be kCoverage.
179      */
180     struct StencilPathArgs {
181         GrContext*             fContext;
182         GrRenderTargetContext* fRenderTargetContext;
183         const GrClip*          fClip;
184         const SkMatrix*        fViewMatrix;
185         GrAAType               fAAType;
186         const GrShape*         fShape;
187 
188 #ifdef SK_DEBUG
validateStencilPathArgs189         void validate() const {
190             SkASSERT(fContext);
191             SkASSERT(fRenderTargetContext);
192             SkASSERT(fViewMatrix);
193             SkASSERT(fShape);
194             SkASSERT(fShape->style().isSimpleFill());
195             SkASSERT(GrAAType::kCoverage != fAAType);
196             SkPath path;
197             fShape->asPath(&path);
198             SkASSERT(!path.isInverseFillType());
199         }
200 #endif
201     };
202 
203     /**
204      * Draws the path to the stencil buffer. Assume the writable stencil bits are already
205      * initialized to zero. The pixels inside the path will have non-zero stencil values afterwards.
206      */
stencilPath(const StencilPathArgs & args)207     void stencilPath(const StencilPathArgs& args) {
208         SkDEBUGCODE(args.validate();)
209         SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(*args.fShape));
210         this->onStencilPath(args);
211     }
212 
213     // Helper for determining if we can treat a thin stroke as a hairline w/ coverage.
214     // If we can, we draw lots faster (raster device does this same test).
IsStrokeHairlineOrEquivalent(const GrStyle & style,const SkMatrix & matrix,SkScalar * outCoverage)215     static bool IsStrokeHairlineOrEquivalent(const GrStyle& style, const SkMatrix& matrix,
216                                              SkScalar* outCoverage) {
217         if (style.pathEffect()) {
218             return false;
219         }
220         const SkStrokeRec& stroke = style.strokeRec();
221         if (stroke.isHairlineStyle()) {
222             if (outCoverage) {
223                 *outCoverage = SK_Scalar1;
224             }
225             return true;
226         }
227         return stroke.getStyle() == SkStrokeRec::kStroke_Style &&
228             SkDrawTreatAAStrokeAsHairline(stroke.getWidth(), matrix, outCoverage);
229     }
230 
231 protected:
232     // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set
233     // by devSize. Non-inverse path bounds will not necessarily be clipped to devSize.
234     static void GetPathDevBounds(const SkPath& path,
235                                  int devW,
236                                  int devH,
237                                  const SkMatrix& matrix,
238                                  SkRect* bounds);
239 
240 private:
241     /**
242      * Subclass overrides if it has any limitations of stenciling support.
243      */
onGetStencilSupport(const GrShape &)244     virtual StencilSupport onGetStencilSupport(const GrShape&) const {
245         return kNoRestriction_StencilSupport;
246     }
247 
248     /**
249      * Subclass implementation of drawPath()
250      */
251     virtual bool onDrawPath(const DrawPathArgs& args) = 0;
252 
253     /**
254      * Subclass implementation of canDrawPath()
255      */
256     virtual bool onCanDrawPath(const CanDrawPathArgs& args) const = 0;
257 
258     /**
259      * Subclass implementation of stencilPath(). Subclass must override iff it ever returns
260      * kStencilOnly in onGetStencilSupport().
261      */
onStencilPath(const StencilPathArgs & args)262     virtual void onStencilPath(const StencilPathArgs& args) {
263         static constexpr GrUserStencilSettings kIncrementStencil(
264             GrUserStencilSettings::StaticInit<
265                  0xffff,
266                  GrUserStencilTest::kAlways,
267                  0xffff,
268                  GrUserStencilOp::kReplace,
269                  GrUserStencilOp::kReplace,
270                  0xffff>()
271         );
272 
273         GrPaint paint;
274 
275         DrawPathArgs drawArgs{args.fContext,
276                               std::move(paint),
277                               &kIncrementStencil,
278                               args.fRenderTargetContext,
279                               nullptr,  // clip
280                               args.fViewMatrix,
281                               args.fShape,
282                               args.fAAType,
283                               false};
284         this->drawPath(drawArgs);
285     }
286 
287     typedef SkRefCnt INHERITED;
288 };
289 
290 #endif
291