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