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