• 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 "include/core/SkRefCnt.h"
12 #include "include/private/GrTypesPriv.h"
13 #include "include/private/SkTArray.h"
14 
15 class GrCaps;
16 class GrClip;
17 class GrHardClip;
18 class GrPaint;
19 class GrRecordingContext;
20 class GrSurfaceDrawContext;
21 class GrRenderTargetProxy;
22 class GrStyledShape;
23 class GrStyle;
24 struct GrUserStencilSettings;
25 struct SkIRect;
26 class SkMatrix;
27 class SkPath;
28 class SkSurfaceProps;
29 
30 /**
31  *  Base class for drawing paths into a GrOpsTask.
32  */
33 class GrPathRenderer : public SkRefCnt {
34 public:
35     GrPathRenderer();
36 
37     virtual const char* name() const = 0;
38 
39     /**
40      * A caller may wish to use a path renderer to draw a path into the stencil buffer. However,
41      * the path renderer itself may require use of the stencil buffer. Also a path renderer may
42      * use a GrProcessor coverage stage that sets coverage to zero to eliminate pixels that are
43      * covered by bounding geometry but outside the path. These exterior pixels would still be
44      * rendered into the stencil.
45      *
46      * A GrPathRenderer can provide three levels of support for stenciling paths:
47      * 1) kNoRestriction: This is the most general. The caller passes a GrPaint and calls drawPath().
48      *                    The path is rendered exactly as the draw state indicates including support
49      *                    for simultaneous color and stenciling with arbitrary stenciling rules.
50      *                    Pixels partially covered by AA paths are affected by the stencil settings.
51      * 2) kStencilOnly: The path renderer cannot apply arbitrary stencil rules nor shade and stencil
52      *                  simultaneously. The path renderer does support the stencilPath() function
53      *                  which performs no color writes and writes a non-zero stencil value to pixels
54      *                  covered by the path.
55      * 3) kNoSupport: This path renderer cannot be used to stencil the path.
56      */
57     enum StencilSupport {
58         kNoSupport_StencilSupport,
59         kStencilOnly_StencilSupport,
60         kNoRestriction_StencilSupport,
61     };
62 
63     /**
64      * This function is to get the stencil support for a particular path. The path's fill must
65      * not be an inverse type. The path will always be filled and not stroked.
66      *
67      * @param shape   the shape that will be drawn. Must be simple fill styled and non-inverse
68      *                filled.
69      */
70     StencilSupport getStencilSupport(const GrStyledShape& shape) const;
71 
72     enum class CanDrawPath {
73         kNo,
74         kAsBackup, // i.e. This renderer is better than SW fallback if no others can draw the path.
75         kYes
76     };
77 
78     struct CanDrawPathArgs {
79         SkDEBUGCODE(CanDrawPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation.
80 
81         const GrCaps*               fCaps;
82         const GrRenderTargetProxy*  fProxy;
83         const SkIRect*              fClipConservativeBounds;
84         const SkMatrix*             fViewMatrix;
85         const GrStyledShape*        fShape;
86         const GrPaint*              fPaint;
87         const SkSurfaceProps*       fSurfaceProps;
88         GrAAType                    fAAType;
89 
90         // This is only used by GrTessellationPathRenderer
91         bool                        fHasUserStencilSettings;
92 
93 #ifdef SK_DEBUG
validateCanDrawPathArgs94         void validate() const {
95             SkASSERT(fCaps);
96             SkASSERT(fProxy);
97             SkASSERT(fClipConservativeBounds);
98             SkASSERT(fViewMatrix);
99             SkASSERT(fShape);
100             SkASSERT(fSurfaceProps);
101         }
102 #endif
103     };
104 
105     /**
106      * Returns how well this path renderer is able to render the given path. Returning kNo or
107      * kAsBackup allows the caller to keep searching for a better path renderer. This function is
108      * called when searching for the best path renderer to draw a path.
109      */
canDrawPath(const CanDrawPathArgs & args)110     CanDrawPath canDrawPath(const CanDrawPathArgs& args) const {
111         SkDEBUGCODE(args.validate();)
112         return this->onCanDrawPath(args);
113     }
114 
115     struct DrawPathArgs {
116         GrRecordingContext*          fContext;
117         GrPaint&&                    fPaint;
118         const GrUserStencilSettings* fUserStencilSettings;
119         GrSurfaceDrawContext*        fRenderTargetContext;
120         const GrClip*                fClip;
121         const SkIRect*               fClipConservativeBounds;
122         const SkMatrix*              fViewMatrix;
123         const GrStyledShape*         fShape;
124         GrAAType                     fAAType;
125         bool                         fGammaCorrect;
126 #ifdef SK_DEBUG
validateDrawPathArgs127         void validate() const {
128             SkASSERT(fContext);
129             SkASSERT(fUserStencilSettings);
130             SkASSERT(fRenderTargetContext);
131             SkASSERT(fClipConservativeBounds);
132             SkASSERT(fViewMatrix);
133             SkASSERT(fShape);
134         }
135 #endif
136     };
137 
138     /**
139      * Draws the path into the draw target. If getStencilSupport() would return kNoRestriction then
140      * the subclass must respect the stencil settings.
141      */
142     bool drawPath(const DrawPathArgs& args);
143     /**
144      * Args to stencilPath(). fAAType cannot be kCoverage.
145      */
146     struct StencilPathArgs {
147         SkDEBUGCODE(StencilPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation.
148 
149         GrRecordingContext*    fContext;
150         GrSurfaceDrawContext*  fRenderTargetContext;
151         const GrHardClip*      fClip;
152         const SkIRect*         fClipConservativeBounds;
153         const SkMatrix*        fViewMatrix;
154         const GrStyledShape*   fShape;
155         GrAA                   fDoStencilMSAA;
156 
157         SkDEBUGCODE(void validate() const);
158     };
159 
160     /**
161      * Draws the path to the stencil buffer. Assume the writable stencil bits are already
162      * initialized to zero. The pixels inside the path will have non-zero stencil values afterwards.
163      */
stencilPath(const StencilPathArgs & args)164     void stencilPath(const StencilPathArgs& args) {
165         SkDEBUGCODE(args.validate();)
166         SkASSERT(kNoSupport_StencilSupport != this->getStencilSupport(*args.fShape));
167         this->onStencilPath(args);
168     }
169 
170     // Helper for determining if we can treat a thin stroke as a hairline w/ coverage.
171     // If we can, we draw lots faster (raster device does this same test).
172     static bool IsStrokeHairlineOrEquivalent(const GrStyle&, const SkMatrix&,
173                                              SkScalar* outCoverage);
174 
175 protected:
176     // Helper for getting the device bounds of a path. Inverse filled paths will have bounds set
177     // by devSize. Non-inverse path bounds will not necessarily be clipped to devSize.
178     static void GetPathDevBounds(const SkPath& path,
179                                  SkISize devSize,
180                                  const SkMatrix& matrix,
181                                  SkRect* bounds);
182 
183 private:
184     /**
185      * Subclass overrides if it has any limitations of stenciling support.
186      */
onGetStencilSupport(const GrStyledShape &)187     virtual StencilSupport onGetStencilSupport(const GrStyledShape&) const {
188         return kNoRestriction_StencilSupport;
189     }
190 
191     /**
192      * Subclass implementation of drawPath()
193      */
194     virtual bool onDrawPath(const DrawPathArgs& args) = 0;
195 
196     /**
197      * Subclass implementation of canDrawPath()
198      */
199     virtual CanDrawPath onCanDrawPath(const CanDrawPathArgs& args) const = 0;
200 
201     /**
202      * Subclass implementation of stencilPath(). Subclass must override iff it ever returns
203      * kStencilOnly in onGetStencilSupport().
204      */
205     virtual void onStencilPath(const StencilPathArgs&);
206 
207     using INHERITED = SkRefCnt;
208 };
209 
210 #endif
211