1 /* 2 * Copyright 2019 Google LLC. 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 GrTessellationPathRenderer_DEFINED 9 #define GrTessellationPathRenderer_DEFINED 10 11 #include "src/gpu/GrDynamicAtlas.h" 12 #include "src/gpu/GrOnFlushResourceProvider.h" 13 #include "src/gpu/GrPathRenderer.h" 14 #include <map> 15 16 // This is the tie-in point for path rendering via GrPathTessellateOp. This path renderer draws 17 // paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by GPU 18 // tessellation shaders. This path renderer doesn't apply analytic AA, so it requires MSAA if AA is 19 // desired. 20 class GrTessellationPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject { 21 public: 22 // Don't allow linearized segments to be off by more than 1/4th of a pixel from the true curve. 23 constexpr static float kLinearizationPrecision = 4; 24 25 // This is the maximum resolve level supported by our internal indirect draw shaders. (Indirect 26 // draws are an alternative to hardware tessellation, and we can use them when hardware support 27 // is lacking.) 28 // 29 // At a given resolveLevel, a curve gets linearized into 2^resolveLevel line segments. So the 30 // finest resolveLevel supported by our indirect draw shaders is 2^10 == 1024 line segments. 31 // 32 // 1024 line segments is enough resolution (with precision == 4) to guarantee we can render a 33 // 123575px x 123575px path. (See GrWangsFormula::worst_case_cubic.) 34 constexpr static int kMaxResolveLevel = 10; 35 36 // We send these flags to the internal tessellation Ops to control how a path gets rendered. 37 enum class OpFlags { 38 kNone = 0, 39 // Used when tessellation is not supported, or when a path will require more resolution than 40 // the max number of segments supported by the hardware. 41 kDisableHWTessellation = (1 << 0), 42 kStencilOnly = (1 << 1), 43 kWireframe = (1 << 2) 44 }; 45 46 static bool IsSupported(const GrCaps&); 47 48 GrTessellationPathRenderer(GrRecordingContext*); name()49 const char* name() const final { return "GrTessellationPathRenderer"; } onGetStencilSupport(const GrStyledShape & shape)50 StencilSupport onGetStencilSupport(const GrStyledShape& shape) const override { 51 // TODO: Single-pass (e.g., convex) paths can have full support. 52 return kStencilOnly_StencilSupport; 53 } 54 CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override; 55 bool onDrawPath(const DrawPathArgs&) override; 56 void onStencilPath(const StencilPathArgs&) override; 57 void preFlush(GrOnFlushResourceProvider*, SkSpan<const uint32_t> taskIDs) override; 58 59 private: 60 void initAtlasFlags(GrRecordingContext*); getAtlasUberPath(SkPathFillType fillType,bool antialias)61 SkPath* getAtlasUberPath(SkPathFillType fillType, bool antialias) { 62 int idx = (int)antialias << 1; 63 idx |= (int)fillType & 1; 64 return &fAtlasUberPaths[idx]; 65 } 66 // Allocates space in fAtlas if the path is small and simple enough, and if there is room. 67 bool tryAddPathToAtlas(const GrCaps&, const SkMatrix&, const GrStyledShape&, 68 const SkRect& devBounds, GrAAType, SkIRect* devIBounds, 69 SkIPoint16* locationInAtlas, bool* transposedInAtlas); 70 void renderAtlas(GrOnFlushResourceProvider*); 71 72 GrDynamicAtlas fAtlas; 73 OpFlags fStencilAtlasFlags; 74 int fMaxAtlasPathWidth; 75 SkPath fAtlasUberPaths[4]; // 2 fillTypes * 2 antialias modes. 76 }; 77 78 GR_MAKE_BITFIELD_CLASS_OPS(GrTessellationPathRenderer::OpFlags); 79 80 #endif 81