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