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 GrOpList. 32 */ 33 class SK_API 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 int devW, 177 int devH, 178 const SkMatrix& matrix, 179 SkRect* bounds); 180 181 private: 182 /** 183 * Subclass overrides if it has any limitations of stenciling support. 184 */ onGetStencilSupport(const GrShape &)185 virtual StencilSupport onGetStencilSupport(const GrShape&) 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