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