xref: /aosp_15_r20/external/skia/src/gpu/ganesh/ops/AtlasRenderTask.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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