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