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