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 AtlasPathRenderer_DEFINED 9 #define AtlasPathRenderer_DEFINED 10 11 #include "include/gpu/GrTypes.h" 12 #include "include/private/SkTHash.h" 13 #include "src/core/SkIPoint16.h" 14 #include "src/gpu/GrDynamicAtlas.h" 15 #include "src/gpu/GrFragmentProcessor.h" 16 #include "src/gpu/GrOnFlushResourceProvider.h" 17 #include "src/gpu/v1/PathRenderer.h" 18 19 class GrOp; 20 class GrRecordingContext; 21 22 namespace skgpu::v1 { 23 24 class AtlasRenderTask; 25 26 // Draws paths by first rendering their coverage mask into an offscreen atlas. 27 class AtlasPathRenderer final : public PathRenderer, public GrOnFlushCallbackObject { 28 public: 29 static bool IsSupported(GrRecordingContext*); 30 31 // Returns a GrAtlasPathRenderer if it is supported, otherwise null. 32 static sk_sp<AtlasPathRenderer> Make(GrRecordingContext* rContext); 33 name()34 const char* name() const override { return "GrAtlasPathRenderer"; } 35 36 // Returns a fragment processor that modulates inputFP by the given deviceSpacePath's coverage, 37 // implemented using an internal atlas. 38 // 39 // Returns 'inputFP' wrapped in GrFPFailure() if the path was too large, or if the current atlas 40 // is full and already used by either opBeingClipped or inputFP. (Currently, "too large" means 41 // larger than fMaxAtlasSize in either dimension, more than 256^2 total pixels, or more than 42 // 128^2 total pixels if the surfaceDrawContext supports MSAA or DMSAA.) 43 // 44 // Also returns GrFPFailure() if the view matrix has perspective. 45 GrFPResult makeAtlasClipEffect(const skgpu::v1::SurfaceDrawContext*, 46 const GrOp* opBeingClipped, 47 std::unique_ptr<GrFragmentProcessor> inputFP, 48 const SkIRect& drawBounds, 49 const SkMatrix&, 50 const SkPath&); 51 52 private: 53 // The atlas is not compatible with DDL. We can only use it on direct contexts. 54 AtlasPathRenderer(GrDirectContext*); 55 onGetStencilSupport(const GrStyledShape &)56 StencilSupport onGetStencilSupport(const GrStyledShape&) const override { 57 return kNoSupport_StencilSupport; 58 } 59 60 CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override; 61 62 bool onDrawPath(const DrawPathArgs&) override; 63 64 // Returns true if the given device-space path bounds are small enough to fit in an atlas and to 65 // benefit from atlasing. (Currently, "small enough" means no larger than fMaxAtlasSize in 66 // either dimension, no more than 256^2 total pixels, or no more than 128^2 total pixels if the 67 // fallbackAAType is kMSAA.) 68 bool pathFitsInAtlas(const SkRect& pathDevBounds, GrAAType fallbackAAType) const; 69 70 // Returns true if the draw being set up already uses the given atlasProxy. 71 using DrawRefsAtlasCallback = std::function<bool(const GrSurfaceProxy* atlasProxy)>; 72 73 // Adds the filled path to an atlas. 74 // 75 // pathFitsInAtlas() and is_visible() both must have returned true before making this call. 76 // 77 // Fails and returns false if the current atlas is full and already in use according to 78 // DrawRefsAtlasCallback. 79 bool addPathToAtlas(GrRecordingContext*, 80 const SkMatrix&, 81 const SkPath&, 82 const SkRect& pathDevBounds, 83 SkIRect* devIBounds, 84 SkIPoint16* locationInAtlas, 85 bool* transposedInAtlas, 86 const DrawRefsAtlasCallback&); 87 88 // Instantiates texture(s) for all atlases we've created since the last flush. Atlases that are 89 // the same size will be instantiated with the same backing texture. 90 void preFlush(GrOnFlushResourceProvider*, SkSpan<const uint32_t> taskIDs) override; 91 92 float fAtlasMaxSize = 0; 93 float fAtlasMaxPathWidth = 0; 94 int fAtlasInitialSize = 0; 95 96 // A collection of all atlases we've created and used since the last flush. We instantiate these 97 // at flush time during preFlush(). 98 SkSTArray<4, sk_sp<AtlasRenderTask>> fAtlasRenderTasks; 99 100 // This simple cache remembers the locations of cacheable path masks in the most recent atlas. 101 // Its main motivation is for clip paths. 102 struct AtlasPathKey { 103 void set(const SkMatrix&, const SkPath&); 104 bool operator==(const AtlasPathKey& k) const { 105 static_assert(sizeof(*this) == sizeof(uint32_t) * 8); 106 return !memcmp(this, &k, sizeof(*this)); 107 } 108 uint32_t fPathGenID; 109 float fAffineMatrix[6]; 110 uint32_t fFillRule; 111 }; 112 SkTHashMap<AtlasPathKey, SkIPoint16> fAtlasPathCache; 113 }; 114 115 } // namespace skgpu::v1 116 117 #endif // GrAtlasPathRenderer_DEFINED 118