• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 
8 #ifndef GrAtlasManager_DEFINED
9 #define GrAtlasManager_DEFINED
10 
11 #include "src/gpu/ganesh/GrCaps.h"
12 #include "src/gpu/ganesh/GrDrawOpAtlas.h"
13 #include "src/gpu/ganesh/GrOnFlushResourceProvider.h"
14 #include "src/gpu/ganesh/GrProxyProvider.h"
15 
16 namespace sktext::gpu {
17 class Glyph;
18 }
19 class GrResourceProvider;
20 class SkGlyph;
21 class GrTextStrike;
22 
23 //////////////////////////////////////////////////////////////////////////////////////////////////
24 /** The GrAtlasManager manages the lifetime of and access to GrDrawOpAtlases.
25  *  It is only available at flush and only via the GrOpFlushState.
26  *
27  *  This implies that all of the advanced atlasManager functionality (i.e.,
28  *  adding glyphs to the atlas) are only available at flush time.
29  */
30 class GrAtlasManager : public GrOnFlushCallbackObject, public skgpu::AtlasGenerationCounter {
31 public:
32     GrAtlasManager(GrProxyProvider*,
33                    size_t maxTextureBytes,
34                    GrDrawOpAtlas::AllowMultitexturing,
35                    bool supportBilerpAtlas);
36     ~GrAtlasManager() override;
37 
38     // if getViews returns nullptr, the client must not try to use other functions on the
39     // StrikeCache which use the atlas.  This function *must* be called first, before other
40     // functions which use the atlas. Note that we can have proxies available but none active
41     // (i.e., none instantiated).
getViews(skgpu::MaskFormat format,unsigned int * numActiveProxies)42     const GrSurfaceProxyView* getViews(skgpu::MaskFormat format, unsigned int* numActiveProxies) {
43         format = this->resolveMaskFormat(format);
44         if (this->initAtlas(format)) {
45             *numActiveProxies = this->getAtlas(format)->numActivePages();
46             return this->getAtlas(format)->getViews();
47         }
48         *numActiveProxies = 0;
49         return nullptr;
50     }
51 
52     void freeAll();
53 
54     bool hasGlyph(skgpu::MaskFormat, sktext::gpu::Glyph*);
55 
56     GrDrawOpAtlas::ErrorCode addGlyphToAtlas(const SkGlyph&,
57                                              sktext::gpu::Glyph*,
58                                              int srcPadding,
59                                              GrResourceProvider*,
60                                              GrDeferredUploadTarget*);
61 
62     // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
63     // the client must pass in the current op token along with the sktext::gpu::Glyph.
64     // A BulkUsePlotUpdater is used to manage bulk last use token updating in the Atlas.
65     // For convenience, this function will also set the use token for the current glyph if required
66     // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
67     void addGlyphToBulkAndSetUseToken(skgpu::BulkUsePlotUpdater*, skgpu::MaskFormat,
68                                       sktext::gpu::Glyph*, skgpu::AtlasToken);
69 
setUseTokenBulk(const skgpu::BulkUsePlotUpdater & updater,skgpu::AtlasToken token,skgpu::MaskFormat format)70     void setUseTokenBulk(const skgpu::BulkUsePlotUpdater& updater,
71                          skgpu::AtlasToken token,
72                          skgpu::MaskFormat format) {
73         this->getAtlas(format)->setLastUseTokenBulk(updater, token);
74     }
75 
76     // add to texture atlas that matches this format
77     GrDrawOpAtlas::ErrorCode addToAtlas(GrResourceProvider*, GrDeferredUploadTarget*,
78                                         skgpu::MaskFormat, int width, int height, const void* image,
79                                         skgpu::AtlasLocator*);
80 
81     // Some clients may wish to verify the integrity of the texture backing store of the
82     // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
83     // changes every time something is removed from the texture backing store.
atlasGeneration(skgpu::MaskFormat format)84     uint64_t atlasGeneration(skgpu::MaskFormat format) const {
85         return this->getAtlas(format)->atlasGeneration();
86     }
87 
88     // GrOnFlushCallbackObject overrides
89 
preFlush(GrOnFlushResourceProvider * onFlushRP)90     bool preFlush(GrOnFlushResourceProvider* onFlushRP) override {
91 #if GR_TEST_UTILS
92         if (onFlushRP->failFlushTimeCallbacks()) {
93             return false;
94         }
95 #endif
96 
97         for (int i = 0; i < skgpu::kMaskFormatCount; ++i) {
98             if (fAtlases[i]) {
99                 fAtlases[i]->instantiate(onFlushRP);
100             }
101         }
102         return true;
103     }
104 
postFlush(skgpu::AtlasToken startTokenForNextFlush)105     void postFlush(skgpu::AtlasToken startTokenForNextFlush) override {
106         for (int i = 0; i < skgpu::kMaskFormatCount; ++i) {
107             if (fAtlases[i]) {
108                 fAtlases[i]->compact(startTokenForNextFlush);
109             }
110         }
111     }
112 
113     // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active
114     // OnFlushCallbackObject list
retainOnFreeGpuResources()115     bool retainOnFreeGpuResources() override { return true; }
116 
117     ///////////////////////////////////////////////////////////////////////////
118     // Functions intended debug only
119 #ifdef SK_DEBUG
120     void dump(GrDirectContext*) const;
121 #endif
122 
123     void setAtlasDimensionsToMinimum_ForTesting();
124     void setMaxPages_TestingOnly(uint32_t maxPages);
125 
126 private:
127     bool initAtlas(skgpu::MaskFormat);
128     // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
129     // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in
130     // StrikeCache.cpp
resolveMaskFormat(skgpu::MaskFormat format)131     skgpu::MaskFormat resolveMaskFormat(skgpu::MaskFormat format) const {
132         if (skgpu::MaskFormat::kA565 == format &&
133             !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
134                                                              GrRenderable::kNo).isValid()) {
135             format = skgpu::MaskFormat::kARGB;
136         }
137         return format;
138     }
139 
140     // There is a 1:1 mapping between skgpu::MaskFormats and atlas indices
MaskFormatToAtlasIndex(skgpu::MaskFormat format)141     static int MaskFormatToAtlasIndex(skgpu::MaskFormat format) {
142         return static_cast<int>(format);
143     }
AtlasIndexToMaskFormat(int idx)144     static skgpu::MaskFormat AtlasIndexToMaskFormat(int idx) {
145         return static_cast<skgpu::MaskFormat>(idx);
146     }
147 
getAtlas(skgpu::MaskFormat format)148     GrDrawOpAtlas* getAtlas(skgpu::MaskFormat format) const {
149         format = this->resolveMaskFormat(format);
150         int atlasIndex = MaskFormatToAtlasIndex(format);
151         SkASSERT(fAtlases[atlasIndex]);
152         return fAtlases[atlasIndex].get();
153     }
154 
155     GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
156     std::unique_ptr<GrDrawOpAtlas> fAtlases[skgpu::kMaskFormatCount];
157     static_assert(skgpu::kMaskFormatCount == 3);
158     bool fSupportBilerpAtlas;
159     GrProxyProvider* fProxyProvider;
160     sk_sp<const GrCaps> fCaps;
161     GrDrawOpAtlasConfig fAtlasConfig;
162 
163     using INHERITED = GrOnFlushCallbackObject;
164 };
165 
166 #endif // GrAtlasManager_DEFINED
167