• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC.
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 
8 #ifndef AtlasPathRenderer_DEFINED
9 #define AtlasPathRenderer_DEFINED
10 
11 #include "include/gpu/GrTypes.h"
12 #include "include/private/SkTHash.h"
13 #include "src/core/SkIPoint16.h"
14 #include "src/gpu/GrDynamicAtlas.h"
15 #include "src/gpu/GrFragmentProcessor.h"
16 #include "src/gpu/GrOnFlushResourceProvider.h"
17 #include "src/gpu/v1/PathRenderer.h"
18 
19 class GrOp;
20 class GrRecordingContext;
21 
22 namespace skgpu::v1 {
23 
24 class AtlasRenderTask;
25 
26 // Draws paths by first rendering their coverage mask into an offscreen atlas.
27 class AtlasPathRenderer final : public PathRenderer, public GrOnFlushCallbackObject {
28 public:
29     static bool IsSupported(GrRecordingContext*);
30 
31     // Returns a GrAtlasPathRenderer if it is supported, otherwise null.
32     static sk_sp<AtlasPathRenderer> Make(GrRecordingContext* rContext);
33 
name()34     const char* name() const override { return "GrAtlasPathRenderer"; }
35 
36     // Returns a fragment processor that modulates inputFP by the given deviceSpacePath's coverage,
37     // implemented using an internal atlas.
38     //
39     // Returns 'inputFP' wrapped in GrFPFailure() if the path was too large, or if the current atlas
40     // is full and already used by either opBeingClipped or inputFP. (Currently, "too large" means
41     // larger than fMaxAtlasSize in either dimension, more than 256^2 total pixels, or more than
42     // 128^2 total pixels if the surfaceDrawContext supports MSAA or DMSAA.)
43     //
44     // Also returns GrFPFailure() if the view matrix has perspective.
45     GrFPResult makeAtlasClipEffect(const skgpu::v1::SurfaceDrawContext*,
46                                    const GrOp* opBeingClipped,
47                                    std::unique_ptr<GrFragmentProcessor> inputFP,
48                                    const SkIRect& drawBounds,
49                                    const SkMatrix&,
50                                    const SkPath&);
51 
52 private:
53     // The atlas is not compatible with DDL. We can only use it on direct contexts.
54     AtlasPathRenderer(GrDirectContext*);
55 
onGetStencilSupport(const GrStyledShape &)56     StencilSupport onGetStencilSupport(const GrStyledShape&) const override {
57         return kNoSupport_StencilSupport;
58     }
59 
60     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
61 
62     bool onDrawPath(const DrawPathArgs&) override;
63 
64     // Returns true if the given device-space path bounds are small enough to fit in an atlas and to
65     // benefit from atlasing. (Currently, "small enough" means no larger than fMaxAtlasSize in
66     // either dimension, no more than 256^2 total pixels, or no more than 128^2 total pixels if the
67     // fallbackAAType is kMSAA.)
68     bool pathFitsInAtlas(const SkRect& pathDevBounds, GrAAType fallbackAAType) const;
69 
70     // Returns true if the draw being set up already uses the given atlasProxy.
71     using DrawRefsAtlasCallback = std::function<bool(const GrSurfaceProxy* atlasProxy)>;
72 
73     // Adds the filled path to an atlas.
74     //
75     // pathFitsInAtlas() and is_visible() both must have returned true before making this call.
76     //
77     // Fails and returns false if the current atlas is full and already in use according to
78     // DrawRefsAtlasCallback.
79     bool addPathToAtlas(GrRecordingContext*,
80                         const SkMatrix&,
81                         const SkPath&,
82                         const SkRect& pathDevBounds,
83                         SkIRect* devIBounds,
84                         SkIPoint16* locationInAtlas,
85                         bool* transposedInAtlas,
86                         const DrawRefsAtlasCallback&);
87 
88     // Instantiates texture(s) for all atlases we've created since the last flush. Atlases that are
89     // the same size will be instantiated with the same backing texture.
90     void preFlush(GrOnFlushResourceProvider*, SkSpan<const uint32_t> taskIDs) override;
91 
92     float fAtlasMaxSize = 0;
93     float fAtlasMaxPathWidth = 0;
94     int fAtlasInitialSize = 0;
95 
96     // A collection of all atlases we've created and used since the last flush. We instantiate these
97     // at flush time during preFlush().
98     SkSTArray<4, sk_sp<AtlasRenderTask>> fAtlasRenderTasks;
99 
100     // This simple cache remembers the locations of cacheable path masks in the most recent atlas.
101     // Its main motivation is for clip paths.
102     struct AtlasPathKey {
103         void set(const SkMatrix&, const SkPath&);
104         bool operator==(const AtlasPathKey& k) const {
105             static_assert(sizeof(*this) == sizeof(uint32_t) * 8);
106             return !memcmp(this, &k, sizeof(*this));
107         }
108         uint32_t fPathGenID;
109         float fAffineMatrix[6];
110         uint32_t fFillRule;
111     };
112     SkTHashMap<AtlasPathKey, SkIPoint16> fAtlasPathCache;
113 };
114 
115 } // namespace skgpu::v1
116 
117 #endif // GrAtlasPathRenderer_DEFINED
118