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