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