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