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