2 * Copyright 2021 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef AtlasRenderTask_DEFINED
9 #define AtlasRenderTask_DEFINED
11 #include "include/core/SkPath.h"
12 #include "src/core/SkTBlockList.h"
13 #include "src/gpu/ganesh/GrDynamicAtlas.h"
14 #include "src/gpu/ganesh/ops/OpsTask.h"
15 #include "src/gpu/ganesh/tessellate/PathTessellator.h"
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().
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 final : public OpsTask {
29 AtlasRenderTask(GrRecordingContext*,
31 std::unique_ptr<GrDynamicAtlas>);
33 const GrTextureProxy* atlasProxy() const { return fDynamicAtlas->textureProxy(); }
34 GrSurfaceProxyView readView(const GrCaps& caps) const { return fDynamicAtlas->readView(caps); }
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);
42 // Must be called at flush time. The texture proxy is instantiated with 'backingTexture', if
43 // provided. See GrDynamicAtlas.
44 bool SK_WARN_UNUSED_RESULT instantiate(GrOnFlushResourceProvider* onFlushRP,
45 sk_sp<GrTexture> backingTexture = nullptr) {
46 SkASSERT(this->isClosed());
47 return fDynamicAtlas->instantiate(onFlushRP, std::move(backingTexture));
51 // Adds internal ops to render the atlas before deferring to OpsTask::onMakeClosed.
52 ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override;
54 void stencilAtlasRect(GrRecordingContext*, const SkRect&, const SkPMColor4f&,
55 const GrUserStencilSettings*);
56 void addAtlasDrawOp(GrOp::Owner, const GrCaps&);
58 // Executes the OpsTask and resolves msaa if needed.
59 bool onExecute(GrOpFlushState* flushState) override;
61 const std::unique_ptr<GrDynamicAtlas> fDynamicAtlas;
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};
68 class AtlasPathList : SkNoncopyable {
70 void add(PathDrawAllocator* alloc, const SkMatrix& pathMatrix, const SkPath& path) {
71 fPathDrawList = &alloc->emplace_back(pathMatrix, path, SK_PMColor4fTRANSPARENT,
73 if (path.isInverseFillType()) {
74 // The atlas never has inverse paths. The inversion happens later.
75 fPathDrawList->fPath.toggleInverseFillType();
77 fTotalCombinedPathVerbCnt += path.countVerbs();
80 const PathDrawList* pathDrawList() const { return fPathDrawList; }
81 int totalCombinedPathVerbCnt() const { return fTotalCombinedPathVerbCnt; }
82 int pathCount() const { return fPathCount; }
85 PathDrawList* fPathDrawList = nullptr;
86 int fTotalCombinedPathVerbCnt = 0;
90 AtlasPathList fWindingPathList;
91 AtlasPathList fEvenOddPathList;
94 } // namespace skgpu::v1
96 #endif // AtlasRenderTask_DEFINED