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