blob: 78469667bf175f3c19e98c07f54af5661c47b170 [file] [log] [blame]
Chris Dalton83420eb2021-06-23 18:47:09 -06001/*
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
Robert Phillipsfdafc0c2021-08-25 16:39:14 -04008#ifndef AtlasRenderTask_DEFINED
9#define AtlasRenderTask_DEFINED
Chris Dalton83420eb2021-06-23 18:47:09 -060010
11#include "include/core/SkPath.h"
Michael Ludwigc1ed11d2021-08-24 11:49:55 -040012#include "src/core/SkTBlockList.h"
Chris Dalton83420eb2021-06-23 18:47:09 -060013#include "src/gpu/GrDynamicAtlas.h"
Robert Phillips3e87a8e2021-08-25 13:22:24 -040014#include "src/gpu/ops/OpsTask.h"
Chris Dalton8a1bbaa2021-07-28 14:43:07 -060015#include "src/gpu/tessellate/GrPathTessellator.h"
Chris Dalton83420eb2021-06-23 18:47:09 -060016
17struct SkIPoint16;
18
Robert Phillipsfdafc0c2021-08-25 16:39:14 -040019namespace skgpu::v1 {
20
Chris Dalton83420eb2021-06-23 18:47:09 -060021// 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.
Robert Phillipsfdafc0c2021-08-25 16:39:14 -040027class AtlasRenderTask : public OpsTask {
Chris Dalton83420eb2021-06-23 18:47:09 -060028public:
Robert Phillipsfdafc0c2021-08-25 16:39:14 -040029 AtlasRenderTask(GrRecordingContext*,
30 sk_sp<GrArenas>,
31 std::unique_ptr<GrDynamicAtlas>);
Chris Dalton83420eb2021-06-23 18:47:09 -060032
33 const GrTextureProxy* atlasProxy() const { return fDynamicAtlas->textureProxy(); }
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'.
Chris Dalton5e332c82021-07-21 16:04:47 -060039 bool addPath(const SkMatrix&, const SkPath&, SkIPoint pathDevTopLeft, int widthInAtlas,
40 int heightInAtlas, bool transposedInAtlas, SkIPoint16* locationInAtlas);
Chris Dalton83420eb2021-06-23 18:47:09 -060041
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
50private:
Robert Phillips3e87a8e2021-08-25 13:22:24 -040051 // Adds internal ops to render the atlas before deferring to OpsTask::onMakeClosed.
Chris Dalton83420eb2021-06-23 18:47:09 -060052 ExpectedOutcome onMakeClosed(GrRecordingContext*, SkIRect* targetUpdateBounds) override;
53
54 void stencilAtlasRect(GrRecordingContext*, const SkRect&, const SkPMColor4f&,
55 const GrUserStencilSettings*);
Chris Dalton5e332c82021-07-21 16:04:47 -060056 void addAtlasDrawOp(GrOp::Owner, const GrCaps&);
Chris Dalton83420eb2021-06-23 18:47:09 -060057
Robert Phillips3e87a8e2021-08-25 13:22:24 -040058 // Executes the OpsTask and resolves msaa if needed.
Chris Dalton83420eb2021-06-23 18:47:09 -060059 bool onExecute(GrOpFlushState* flushState) override;
60
Chris Dalton83420eb2021-06-23 18:47:09 -060061 const std::unique_ptr<GrDynamicAtlas> fDynamicAtlas;
Chris Dalton8a1bbaa2021-07-28 14:43:07 -060062
63 // Allocate enough inline entries for 16 atlas path draws, then spill to the heap.
Michael Ludwigc1ed11d2021-08-24 11:49:55 -040064 using PathDrawAllocator = SkTBlockList<GrPathTessellator::PathDrawList, 16>;
65 PathDrawAllocator fPathDrawAllocator{64, SkBlockAllocator::GrowthPolicy::kFibonacci};
Chris Dalton8a1bbaa2021-07-28 14:43:07 -060066
67 class AtlasPathList : SkNoncopyable {
68 public:
69 void add(PathDrawAllocator* alloc, const SkMatrix& pathMatrix, const SkPath& path) {
70 fPathDrawList = &alloc->emplace_back(pathMatrix, path, fPathDrawList);
71 if (path.isInverseFillType()) {
72 // The atlas never has inverse paths. The inversion happens later.
73 fPathDrawList->fPath.toggleInverseFillType();
74 }
75 fTotalCombinedPathVerbCnt += path.countVerbs();
76 ++fPathCount;
77 }
78 const GrPathTessellator::PathDrawList* pathDrawList() const { return fPathDrawList; }
79 int totalCombinedPathVerbCnt() const { return fTotalCombinedPathVerbCnt; }
80 int pathCount() const { return fPathCount; }
81
82 private:
83 GrPathTessellator::PathDrawList* fPathDrawList = nullptr;
84 int fTotalCombinedPathVerbCnt = 0;
85 int fPathCount = 0;
86 };
87
88 AtlasPathList fWindingPathList;
89 AtlasPathList fEvenOddPathList;
Chris Dalton83420eb2021-06-23 18:47:09 -060090};
91
Robert Phillipsfdafc0c2021-08-25 16:39:14 -040092} // namespace skgpu::v1
93
94#endif // AtlasRenderTask_DEFINED