xref: /aosp_15_r20/external/skia/src/gpu/graphite/text/TextAtlasManager.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2022 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 skgpu_graphite_TextAtlasManager_DEFINED
9 #define skgpu_graphite_TextAtlasManager_DEFINED
10 
11 #include "include/gpu/graphite/TextureInfo.h"
12 #include "src/gpu/AtlasTypes.h"
13 #include "src/gpu/graphite/Caps.h"
14 #include "src/gpu/graphite/DrawAtlas.h"
15 
16 namespace sktext::gpu {
17 class Glyph;
18 }
19 class SkGlyph;
20 
21 namespace skgpu::graphite {
22 
23 class Recorder;
24 class UploadList;
25 
26 //////////////////////////////////////////////////////////////////////////////////////////////////
27 /** The TextAtlasManager manages the lifetime of and access to DrawAtlases used in glyph rendering.
28  */
29 class TextAtlasManager : public AtlasGenerationCounter {
30 public:
31     TextAtlasManager(Recorder*);
32     ~TextAtlasManager();
33 
34     // If getProxies returns nullptr, the client must not try to use other functions on the
35     // StrikeCache which use the atlas.  This function *must* be called first, before other
36     // functions which use the atlas.
getProxies(MaskFormat format,unsigned int * numActiveProxies)37     const sk_sp<TextureProxy>* getProxies(MaskFormat format,
38                                           unsigned int* numActiveProxies) {
39         format = this->resolveMaskFormat(format);
40         if (this->initAtlas(format)) {
41             *numActiveProxies = this->getAtlas(format)->numActivePages();
42             return this->getAtlas(format)->getProxies();
43         }
44         *numActiveProxies = 0;
45         return nullptr;
46     }
47 
48     void freeAll();
49 
50     bool hasGlyph(MaskFormat, sktext::gpu::Glyph*);
51 
52     DrawAtlas::ErrorCode addGlyphToAtlas(const SkGlyph&,
53                                          sktext::gpu::Glyph*,
54                                          int srcPadding);
55 
56     // To ensure the DrawAtlas does not evict the Glyph Mask from its texture backing store,
57     // the client must pass in the current draw token along with the sktext::gpu::Glyph.
58     // A BulkUsePlotUpdater is used to manage bulk last use token updating in the Atlas.
59     // For convenience, this function will also set the use token for the current glyph if required
60     // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
61     void addGlyphToBulkAndSetUseToken(BulkUsePlotUpdater*, MaskFormat,
62                                       sktext::gpu::Glyph*, AtlasToken);
63 
setUseTokenBulk(const BulkUsePlotUpdater & updater,AtlasToken token,MaskFormat format)64     void setUseTokenBulk(const BulkUsePlotUpdater& updater,
65                          AtlasToken token,
66                          MaskFormat format) {
67         this->getAtlas(format)->setLastUseTokenBulk(updater, token);
68     }
69 
70     bool recordUploads(DrawContext* dc);
71 
evictAtlases()72     void evictAtlases() {
73         for (int i = 0; i < kMaskFormatCount; ++i) {
74             if (fAtlases[i]) {
75                 fAtlases[i]->evictAllPlots();
76             }
77         }
78     }
79 
80     void compact(bool forceCompact);
81 
82     // Some clients may wish to verify the integrity of the texture backing store of the
83     // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
84     // changes every time something is removed from the texture backing store.
atlasGeneration(skgpu::MaskFormat format)85     uint64_t atlasGeneration(skgpu::MaskFormat format) const {
86         return this->getAtlas(format)->atlasGeneration();
87     }
88 
89     ///////////////////////////////////////////////////////////////////////////
90     // Functions intended debug only
91 
92     void setAtlasDimensionsToMinimum_ForTesting();
93     void setMaxPages_TestingOnly(uint32_t maxPages);
94 
95 private:
96     bool initAtlas(MaskFormat);
97     // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
98     // Metal on Intel MacOS). The actual conversion of the data is handled in
99     // get_packed_glyph_image() in StrikeCache.cpp
100     MaskFormat resolveMaskFormat(MaskFormat format) const;
101 
102     // There is a 1:1 mapping between skgpu::MaskFormats and atlas indices
MaskFormatToAtlasIndex(skgpu::MaskFormat format)103     static int MaskFormatToAtlasIndex(skgpu::MaskFormat format) {
104         return static_cast<int>(format);
105     }
AtlasIndexToMaskFormat(int idx)106     static skgpu::MaskFormat AtlasIndexToMaskFormat(int idx) {
107         return static_cast<skgpu::MaskFormat>(idx);
108     }
109 
getAtlas(skgpu::MaskFormat format)110     DrawAtlas* getAtlas(skgpu::MaskFormat format) const {
111         format = this->resolveMaskFormat(format);
112         int atlasIndex = MaskFormatToAtlasIndex(format);
113         SkASSERT(fAtlases[atlasIndex]);
114         return fAtlases[atlasIndex].get();
115     }
116 
117     Recorder* fRecorder;
118     DrawAtlas::AllowMultitexturing fAllowMultitexturing;
119     std::unique_ptr<DrawAtlas> fAtlases[kMaskFormatCount];
120     static_assert(kMaskFormatCount == 3);
121     bool fSupportBilerpAtlas;
122     DrawAtlasConfig fAtlasConfig;
123 };
124 
125 }  // namespace skgpu::graphite
126 
127 #endif  // skgpu_graphite_TextAtlasManager_DEFINED
128