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