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