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 GrFixedClip;
18class GrHardClip;
19class GrPaint;
20class GrRecordingContext;
21class GrRenderTargetContext;
22class GrRenderTargetProxy;
23class GrShape;
24class GrStyle;
25struct GrUserStencilSettings;
26struct SkIRect;
27class SkMatrix;
28class SkPath;
29
30/**
31 * Base class for drawing paths into a GrOpsTask.
32 */
33class GrPathRenderer : public SkRefCnt {
34public:
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
91 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 */
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
123 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 */
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
172protected:
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
180private:
181 /**
182 * Subclass overrides if it has any limitations of stenciling support.
183 */
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