Move GrAtlasRenderTask to gpu/ops and skgpu::v1 namespace
Bug: skia:11837
Change-Id: I29352c0e2c9e987b28be983c3d519a88b589baf1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/442022
Reviewed-by: Chris Dalton <csmartdalton@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ops/AtlasRenderTask.h b/src/gpu/ops/AtlasRenderTask.h
new file mode 100644
index 0000000..7846966
--- /dev/null
+++ b/src/gpu/ops/AtlasRenderTask.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2021 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef AtlasRenderTask_DEFINED
+#define AtlasRenderTask_DEFINED
+
+#include "include/core/SkPath.h"
+#include "src/core/SkTBlockList.h"
+#include "src/gpu/GrDynamicAtlas.h"
+#include "src/gpu/ops/OpsTask.h"
+#include "src/gpu/tessellate/GrPathTessellator.h"
+
+struct SkIPoint16;
+
+namespace skgpu::v1 {
+
+// Represents a GrRenderTask that draws paths into an atlas. This task gets added the DAG and left
+// open, lays out its atlas while future tasks call addPath(), and finally adds its internal draw
+// ops during onMakeClosed().
+//
+// The atlas texture does not get instantiated automatically. It is the creator's responsibility to
+// call instantiate() at flush time.
+class AtlasRenderTask : public OpsTask {
+public:
+ AtlasRenderTask(GrRecordingContext*,
+ sk_sp<GrArenas>,
+ std::unique_ptr<GrDynamicAtlas>);
+
+ const GrTextureProxy* atlasProxy() const { return fDynamicAtlas->textureProxy(); }
+ GrSurfaceProxyView readView(const GrCaps& caps) const { return fDynamicAtlas->readView(caps); }
+
+ // Allocates a rectangle for, and stages the given path to be rendered into the atlas. Returns
+ // false if there was not room in the atlas. On success, writes out the location of the path's
+ // upper-left corner to 'locationInAtlas'.
+ bool addPath(const SkMatrix&, const SkPath&, SkIPoint pathDevTopLeft, int widthInAtlas,
+ int heightInAtlas, bool transposedInAtlas, SkIPoint16* locationInAtlas);
+
+ // Must be called at flush time. The texture proxy is instantiated with 'backingTexture', if
+ // provided. See GrDynamicAtlas.
+ void instantiate(GrOnFlushResourceProvider* onFlushRP,
+ sk_sp<GrTexture> backingTexture = nullptr) {
+ SkASSERT(this->isClosed());
+ fDynamicAtlas->instantiate(onFlushRP, std::move(backingTexture));
+ }
+
+private:
+ // Adds internal ops to render the atlas before deferring to OpsTask::onMakeClosed.
+ ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override;
+
+ void stencilAtlasRect(GrRecordingContext*, const SkRect&, const SkPMColor4f&,
+ const GrUserStencilSettings*);
+ void addAtlasDrawOp(GrOp::Owner, const GrCaps&);
+
+ // Executes the OpsTask and resolves msaa if needed.
+ bool onExecute(GrOpFlushState* flushState) override;
+
+ const std::unique_ptr<GrDynamicAtlas> fDynamicAtlas;
+
+ // Allocate enough inline entries for 16 atlas path draws, then spill to the heap.
+ using PathDrawAllocator = SkTBlockList<GrPathTessellator::PathDrawList, 16>;
+ PathDrawAllocator fPathDrawAllocator{64, SkBlockAllocator::GrowthPolicy::kFibonacci};
+
+ class AtlasPathList : SkNoncopyable {
+ public:
+ void add(PathDrawAllocator* alloc, const SkMatrix& pathMatrix, const SkPath& path) {
+ fPathDrawList = &alloc->emplace_back(pathMatrix, path, fPathDrawList);
+ if (path.isInverseFillType()) {
+ // The atlas never has inverse paths. The inversion happens later.
+ fPathDrawList->fPath.toggleInverseFillType();
+ }
+ fTotalCombinedPathVerbCnt += path.countVerbs();
+ ++fPathCount;
+ }
+ const GrPathTessellator::PathDrawList* pathDrawList() const { return fPathDrawList; }
+ int totalCombinedPathVerbCnt() const { return fTotalCombinedPathVerbCnt; }
+ int pathCount() const { return fPathCount; }
+
+ private:
+ GrPathTessellator::PathDrawList* fPathDrawList = nullptr;
+ int fTotalCombinedPathVerbCnt = 0;
+ int fPathCount = 0;
+ };
+
+ AtlasPathList fWindingPathList;
+ AtlasPathList fEvenOddPathList;
+};
+
+} // namespace skgpu::v1
+
+#endif // AtlasRenderTask_DEFINED