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 "GrCaps.h"
12 #include "GrDrawOpAtlas.h"
13 #include "GrOnFlushResourceProvider.h"
14 #include "GrProxyProvider.h"
15 
16 struct GrGlyph;
17 class GrTextStrike;
18 
19 //////////////////////////////////////////////////////////////////////////////////////////////////
20 /** The GrAtlasManager manages the lifetime of and access to GrDrawOpAtlases.
21  *  It is only available at flush and only via the GrOpFlushState.
22  *
23  *  This implies that all of the advanced atlasManager functionality (i.e.,
24  *  adding glyphs to the atlas) are only available at flush time.
25  */
26 class GrAtlasManager : public GrOnFlushCallbackObject {
27 public:
28     GrAtlasManager(GrProxyProvider*, GrStrikeCache*,
29                    size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
30     ~GrAtlasManager() override;
31 
32     // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
33     // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in
34     // GrStrikeCache.cpp
35     GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
36         if (kA565_GrMaskFormat == format &&
37             !fProxyProvider->caps()->isConfigTexturable(kRGB_565_GrPixelConfig)) {
38             format = kARGB_GrMaskFormat;
39         }
40         return format;
41     }
42 
43     // if getProxies returns nullptr, the client must not try to use other functions on the
44     // GrStrikeCache which use the atlas.  This function *must* be called first, before other
45     // functions which use the atlas. Note that we can have proxies available but none active
46     // (i.e., none instantiated).
47     const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numActiveProxies) {
48         format = this->resolveMaskFormat(format);
49         if (this->initAtlas(format)) {
50             *numActiveProxies = this->getAtlas(format)->numActivePages();
51             return this->getAtlas(format)->getProxies();
52         }
53         *numActiveProxies = 0;
54         return nullptr;
55     }
56 
57     void freeAll();
58 
59     bool hasGlyph(GrGlyph* glyph);
60 
61     // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
62     // the client must pass in the current op token along with the GrGlyph.
63     // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
64     // For convenience, this function will also set the use token for the current glyph if required
65     // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
66     void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrGlyph*,
67                                       GrDeferredUploadToken);
68 
69     void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
70                          GrDeferredUploadToken token,
71                          GrMaskFormat format) {
72         this->getAtlas(format)->setLastUseTokenBulk(updater, token);
73     }
74 
75     // add to texture atlas that matches this format
76     GrDrawOpAtlas::ErrorCode addToAtlas(
77                     GrResourceProvider*, GrStrikeCache*, GrTextStrike*,
78                     GrDrawOpAtlas::AtlasID*, GrDeferredUploadTarget*, GrMaskFormat,
79                     int width, int height, const void* image, SkIPoint16* loc);
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.
84     uint64_t atlasGeneration(GrMaskFormat format) const {
85         return this->getAtlas(format)->atlasGeneration();
86     }
87 
88     // GrOnFlushCallbackObject overrides
89 
90     void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int,
91                   SkTArray<sk_sp<GrRenderTargetContext>>*) override {
92         for (int i = 0; i < kMaskFormatCount; ++i) {
93             if (fAtlases[i]) {
94                 fAtlases[i]->instantiate(onFlushResourceProvider);
95             }
96         }
97     }
98 
99     void postFlush(GrDeferredUploadToken startTokenForNextFlush,
100                    const uint32_t* opListIDs, int numOpListIDs) override {
101         for (int i = 0; i < kMaskFormatCount; ++i) {
102             if (fAtlases[i]) {
103                 fAtlases[i]->compact(startTokenForNextFlush);
104             }
105         }
106     }
107 
108     // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active
109     // OnFlushCallbackObject list
110     bool retainOnFreeGpuResources() override { return true; }
111 
112     ///////////////////////////////////////////////////////////////////////////
113     // Functions intended debug only
114 #ifdef SK_DEBUG
115     void dump(GrContext* context) const;
116 #endif
117 
118     void setAtlasSizesToMinimum_ForTesting();
119     void setMaxPages_TestingOnly(uint32_t maxPages);
120 
121 private:
122     bool initAtlas(GrMaskFormat);
123 
124     // There is a 1:1 mapping between GrMaskFormats and atlas indices
125     static int MaskFormatToAtlasIndex(GrMaskFormat format) {
126         static const int sAtlasIndices[] = {
127             kA8_GrMaskFormat,
128             kA565_GrMaskFormat,
129             kARGB_GrMaskFormat,
130         };
131         static_assert(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, "array_size_mismatch");
132 
133         SkASSERT(sAtlasIndices[format] < kMaskFormatCount);
134         return sAtlasIndices[format];
135     }
136 
137     GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
138         format = this->resolveMaskFormat(format);
139         int atlasIndex = MaskFormatToAtlasIndex(format);
140         SkASSERT(fAtlases[atlasIndex]);
141         return fAtlases[atlasIndex].get();
142     }
143 
144     GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
145     std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
146     GrProxyProvider* fProxyProvider;
147     sk_sp<const GrCaps> fCaps;
148     GrStrikeCache* fGlyphCache;
149     GrDrawOpAtlasConfig fAtlasConfig;
150 
151     typedef GrOnFlushCallbackObject INHERITED;
152 };
153 
154 #endif // GrAtlasManager_DEFINED
155