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