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