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