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