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