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