1/* 2 * Copyright 2020 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#include "src/gpu/ops/SmallPathAtlasMgr.h" 9 10#include "src/gpu/geometry/GrStyledShape.h" 11#include "src/gpu/ops/SmallPathShapeData.h" 12 13#ifdef DF_PATH_TRACKING 14static int g_NumCachedShapes = 0; 15static int g_NumFreedShapes = 0; 16#endif 17 18namespace skgpu::v1 { 19 20SmallPathAtlasMgr::SmallPathAtlasMgr() {} 21 22SmallPathAtlasMgr::~SmallPathAtlasMgr() { 23 this->reset(); 24} 25 26void SmallPathAtlasMgr::reset() { 27 ShapeDataList::Iter iter; 28 iter.init(fShapeList, ShapeDataList::Iter::kHead_IterStart); 29 SmallPathShapeData* shapeData; 30 while ((shapeData = iter.get())) { 31 iter.next(); 32 delete shapeData; 33 } 34 35 fShapeList.reset(); 36 fShapeCache.reset(); 37 38#ifdef DF_PATH_TRACKING 39 SkDebugf("Cached shapes: %d, freed shapes: %d\n", g_NumCachedShapes, g_NumFreedShapes); 40#endif 41 42 fAtlas = nullptr; 43} 44 45bool SmallPathAtlasMgr::initAtlas(GrProxyProvider* proxyProvider, const GrCaps* caps) { 46 if (fAtlas) { 47 return true; 48 } 49 50 static constexpr size_t kMaxAtlasTextureBytes = 2048 * 2048; 51 static constexpr size_t kPlotWidth = 512; 52 static constexpr size_t kPlotHeight = 256; 53 54 const GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8, 55 GrRenderable::kNo); 56 57 GrDrawOpAtlasConfig atlasConfig(caps->maxTextureSize(), kMaxAtlasTextureBytes); 58 SkISize size = atlasConfig.atlasDimensions(kA8_GrMaskFormat); 59#ifdef SK_ENABLE_SMALL_PAGE 60 int pageNum = 4; // The maximum number of texture pages in the original skia code is 4 61 if (atlasConfig.getARGBDimensions().width() > 512) { 62 // reset atlasConfig to suit small page. 63 pageNum = atlasConfig.resetAsSmallPage(); 64 } 65#endif 66 fAtlas = GrDrawOpAtlas::Make(proxyProvider, format, 67 GrColorType::kAlpha_8, size.width(), size.height(), 68 kPlotWidth, kPlotHeight, this, 69 GrDrawOpAtlas::AllowMultitexturing::kYes, 70#ifdef SK_ENABLE_SMALL_PAGE 71 pageNum, 72#endif 73 this); 74 75 return SkToBool(fAtlas); 76} 77 78void SmallPathAtlasMgr::deleteCacheEntry(SmallPathShapeData* shapeData) { 79 fShapeCache.remove(shapeData->fKey); 80 fShapeList.remove(shapeData); 81 delete shapeData; 82} 83 84SmallPathShapeData* SmallPathAtlasMgr::findOrCreate(const SmallPathShapeDataKey& key) { 85 auto shapeData = fShapeCache.find(key); 86 if (!shapeData) { 87 // TODO: move the key into the ctor 88 shapeData = new SmallPathShapeData(key); 89 fShapeCache.add(shapeData); 90 fShapeList.addToTail(shapeData); 91#ifdef DF_PATH_TRACKING 92 ++g_NumCachedShapes; 93#endif 94 } else if (!fAtlas->hasID(shapeData->fAtlasLocator.plotLocator())) { 95 shapeData->fAtlasLocator.invalidatePlotLocator(); 96 } 97 98 return shapeData; 99} 100 101SmallPathShapeData* SmallPathAtlasMgr::findOrCreate(const GrStyledShape& shape, 102 int desiredDimension) { 103 SmallPathShapeDataKey key(shape, desiredDimension); 104 105 // TODO: move the key into 'findOrCreate' 106 return this->findOrCreate(key); 107} 108 109SmallPathShapeData* SmallPathAtlasMgr::findOrCreate(const GrStyledShape& shape, 110 const SkMatrix& ctm) { 111 SmallPathShapeDataKey key(shape, ctm); 112 113 // TODO: move the key into 'findOrCreate' 114 return this->findOrCreate(key); 115} 116 117GrDrawOpAtlas::ErrorCode SmallPathAtlasMgr::addToAtlas(GrResourceProvider* resourceProvider, 118 GrDeferredUploadTarget* target, 119 int width, int height, const void* image, 120 GrDrawOpAtlas::AtlasLocator* locator) { 121 return fAtlas->addToAtlas(resourceProvider, target, width, height, image, locator); 122} 123 124void SmallPathAtlasMgr::setUseToken(SmallPathShapeData* shapeData, 125 GrDeferredUploadToken token) { 126 fAtlas->setLastUseToken(shapeData->fAtlasLocator, token); 127} 128 129// Callback to clear out internal path cache when eviction occurs 130void SmallPathAtlasMgr::evict(GrDrawOpAtlas::PlotLocator plotLocator) { 131 // remove any paths that use this plot 132 ShapeDataList::Iter iter; 133 iter.init(fShapeList, ShapeDataList::Iter::kHead_IterStart); 134 SmallPathShapeData* shapeData; 135 while ((shapeData = iter.get())) { 136 iter.next(); 137 if (plotLocator == shapeData->fAtlasLocator.plotLocator()) { 138 fShapeCache.remove(shapeData->fKey); 139 fShapeList.remove(shapeData); 140 delete shapeData; 141#ifdef DF_PATH_TRACKING 142 ++g_NumFreedShapes; 143#endif 144 } 145 } 146} 147 148} // namespace skgpu::v1 149