1 /* 2 * Copyright 2021 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 AtlasRenderTask_DEFINED 9 #define AtlasRenderTask_DEFINED 10 11 #include "include/core/SkPath.h" 12 #include "src/core/SkTBlockList.h" 13 #include "src/gpu/GrDynamicAtlas.h" 14 #include "src/gpu/ops/OpsTask.h" 15 #include "src/gpu/tessellate/PathTessellator.h" 16 17 struct SkIPoint16; 18 19 namespace skgpu::v1 { 20 21 // Represents a GrRenderTask that draws paths into an atlas. This task gets added the DAG and left 22 // open, lays out its atlas while future tasks call addPath(), and finally adds its internal draw 23 // ops during onMakeClosed(). 24 // 25 // The atlas texture does not get instantiated automatically. It is the creator's responsibility to 26 // call instantiate() at flush time. 27 class AtlasRenderTask : public OpsTask { 28 public: 29 AtlasRenderTask(GrRecordingContext*, 30 sk_sp<GrArenas>, 31 std::unique_ptr<GrDynamicAtlas>); 32 atlasProxy()33 const GrTextureProxy* atlasProxy() const { return fDynamicAtlas->textureProxy(); } readView(const GrCaps & caps)34 GrSurfaceProxyView readView(const GrCaps& caps) const { return fDynamicAtlas->readView(caps); } 35 36 // Allocates a rectangle for, and stages the given path to be rendered into the atlas. Returns 37 // false if there was not room in the atlas. On success, writes out the location of the path's 38 // upper-left corner to 'locationInAtlas'. 39 bool addPath(const SkMatrix&, const SkPath&, SkIPoint pathDevTopLeft, int widthInAtlas, 40 int heightInAtlas, bool transposedInAtlas, SkIPoint16* locationInAtlas); 41 42 // Must be called at flush time. The texture proxy is instantiated with 'backingTexture', if 43 // provided. See GrDynamicAtlas. 44 void instantiate(GrOnFlushResourceProvider* onFlushRP, 45 sk_sp<GrTexture> backingTexture = nullptr) { 46 SkASSERT(this->isClosed()); 47 fDynamicAtlas->instantiate(onFlushRP, std::move(backingTexture)); 48 } 49 50 private: 51 // Adds internal ops to render the atlas before deferring to OpsTask::onMakeClosed. 52 ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override; 53 54 void stencilAtlasRect(GrRecordingContext*, const SkRect&, const SkPMColor4f&, 55 const GrUserStencilSettings*); 56 void addAtlasDrawOp(GrOp::Owner, const GrCaps&); 57 58 // Executes the OpsTask and resolves msaa if needed. 59 bool onExecute(GrOpFlushState* flushState) override; 60 61 const std::unique_ptr<GrDynamicAtlas> fDynamicAtlas; 62 63 // Allocate enough inline entries for 16 atlas path draws, then spill to the heap. 64 using PathDrawList = PathTessellator::PathDrawList; 65 using PathDrawAllocator = SkTBlockList<PathDrawList, 16>; 66 PathDrawAllocator fPathDrawAllocator{64, SkBlockAllocator::GrowthPolicy::kFibonacci}; 67 68 class AtlasPathList : SkNoncopyable { 69 public: add(PathDrawAllocator * alloc,const SkMatrix & pathMatrix,const SkPath & path)70 void add(PathDrawAllocator* alloc, const SkMatrix& pathMatrix, const SkPath& path) { 71 fPathDrawList = &alloc->emplace_back(pathMatrix, path, SK_PMColor4fTRANSPARENT, 72 fPathDrawList); 73 if (path.isInverseFillType()) { 74 // The atlas never has inverse paths. The inversion happens later. 75 fPathDrawList->fPath.toggleInverseFillType(); 76 } 77 fTotalCombinedPathVerbCnt += path.countVerbs(); 78 ++fPathCount; 79 } pathDrawList()80 const PathDrawList* pathDrawList() const { return fPathDrawList; } totalCombinedPathVerbCnt()81 int totalCombinedPathVerbCnt() const { return fTotalCombinedPathVerbCnt; } pathCount()82 int pathCount() const { return fPathCount; } 83 84 private: 85 PathDrawList* fPathDrawList = nullptr; 86 int fTotalCombinedPathVerbCnt = 0; 87 int fPathCount = 0; 88 }; 89 90 AtlasPathList fWindingPathList; 91 AtlasPathList fEvenOddPathList; 92 }; 93 94 } // namespace skgpu::v1 95 96 #endif // AtlasRenderTask_DEFINED 97