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