• 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 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, int plotOldThreshold);
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
resolveMaskFormat(GrMaskFormat format)35     GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
36         if (kA565_GrMaskFormat == format &&
37             !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
38                                                              GrRenderable::kNo).isValid()) {
39             format = kARGB_GrMaskFormat;
40         }
41         return format;
42     }
43 
44     // if getProxies returns nullptr, the client must not try to use other functions on the
45     // GrStrikeCache which use the atlas.  This function *must* be called first, before other
46     // functions which use the atlas. Note that we can have proxies available but none active
47     // (i.e., none instantiated).
getProxies(GrMaskFormat format,unsigned int * numActiveProxies)48     const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numActiveProxies) {
49         format = this->resolveMaskFormat(format);
50         if (this->initAtlas(format)) {
51             *numActiveProxies = this->getAtlas(format)->numActivePages();
52             return this->getAtlas(format)->getProxies();
53         }
54         *numActiveProxies = 0;
55         return nullptr;
56     }
57 
58     void freeAll();
59 
60     bool hasGlyph(GrGlyph* glyph);
61 
incAtlasHitCount()62     void incAtlasHitCount() { fAtlasHitCount++; }
incAtlasMissCount()63     void incAtlasMissCount() { fAtlasMissCount++; }
atlasHitRate()64     float atlasHitRate() {
65         if (fAtlasHitCount + fAtlasMissCount == 0) {
66             return 0;
67         }
68         return (float)fAtlasHitCount / (fAtlasHitCount + fAtlasMissCount);
69     }
resetHitCount()70     void resetHitCount() {
71         fAtlasHitCount = 0;
72         fAtlasMissCount = 0;
73     }
74 
75     // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
76     // the client must pass in the current op token along with the GrGlyph.
77     // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
78     // For convenience, this function will also set the use token for the current glyph if required
79     // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
80     void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrGlyph*,
81                                       GrDeferredUploadToken);
82 
setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater & updater,GrDeferredUploadToken token,GrMaskFormat format)83     void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
84                          GrDeferredUploadToken token,
85                          GrMaskFormat format) {
86         this->getAtlas(format)->setLastUseTokenBulk(updater, token);
87     }
88 
89     // add to texture atlas that matches this format
90     GrDrawOpAtlas::ErrorCode addToAtlas(
91                     GrResourceProvider*, GrStrikeCache*, GrTextStrike*,
92                     GrDrawOpAtlas::AtlasID*, GrDeferredUploadTarget*, GrMaskFormat,
93                     int width, int height, const void* image, SkIPoint16* loc);
94 
95     // Some clients may wish to verify the integrity of the texture backing store of the
96     // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
97     // changes every time something is removed from the texture backing store.
atlasGeneration(GrMaskFormat format)98     uint64_t atlasGeneration(GrMaskFormat format) const {
99         return this->getAtlas(format)->atlasGeneration();
100     }
101 
102     // GrOnFlushCallbackObject overrides
103 
preFlush(GrOnFlushResourceProvider * onFlushResourceProvider,const uint32_t *,int,SkTArray<sk_sp<GrRenderTargetContext>> *)104     void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int,
105                   SkTArray<sk_sp<GrRenderTargetContext>>*) override {
106         for (int i = 0; i < kMaskFormatCount; ++i) {
107             if (fAtlases[i]) {
108                 fAtlases[i]->instantiate(onFlushResourceProvider);
109             }
110         }
111     }
112 
113     void postFlush(GrDeferredUploadToken startTokenForNextFlush,
114                     const uint32_t* opListIDs, int numOpListIDs) override;
115 
116     // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active
117     // OnFlushCallbackObject list
retainOnFreeGpuResources()118     bool retainOnFreeGpuResources() override { return true; }
119 
120     ///////////////////////////////////////////////////////////////////////////
121     // Functions intended debug only
122 #ifdef SK_DUMP_ATLAS_IMAGE
123     void dump(GrContext* context) const;
124 #endif
125 
126     void setAtlasSizesToMinimum_ForTesting();
127     void setMaxPages_TestingOnly(uint32_t maxPages);
128 
129 private:
130     bool initAtlas(GrMaskFormat);
131 
132     // There is a 1:1 mapping between GrMaskFormats and atlas indices
MaskFormatToAtlasIndex(GrMaskFormat format)133     static int MaskFormatToAtlasIndex(GrMaskFormat format) { return static_cast<int>(format); }
AtlasIndexToMaskFormat(int idx)134     static GrMaskFormat AtlasIndexToMaskFormat(int idx) { return static_cast<GrMaskFormat>(idx); }
135 
getAtlas(GrMaskFormat format)136     GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
137         format = this->resolveMaskFormat(format);
138         int atlasIndex = MaskFormatToAtlasIndex(format);
139         SkASSERT(fAtlases[atlasIndex]);
140         return fAtlases[atlasIndex].get();
141     }
142 
143     GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
144     std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
145     GrProxyProvider* fProxyProvider;
146     sk_sp<const GrCaps> fCaps;
147     GrStrikeCache* fGlyphCache;
148     GrDrawOpAtlasConfig fAtlasConfig;
149     int fPlotOldThreshold;
150     int fAtlasHitCount;
151     int fAtlasMissCount;
152 
153     typedef GrOnFlushCallbackObject INHERITED;
154 };
155 
156 #endif // GrAtlasManager_DEFINED
157