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 "src/gpu/GrCaps.h"
12#include "src/gpu/GrDrawOpAtlas.h"
13#include "src/gpu/GrOnFlushResourceProvider.h"
14#include "src/gpu/GrProxyProvider.h"
15
16class GrGlyph;
17class GrTextStrike;
18
19//////////////////////////////////////////////////////////////////////////////////////////////////
20/** The GrAtlasManager manages the lifetime of and access to GrDrawOpAtlases.
21 * It is only available at flush and only via the GrOpFlushState.
22 *
23 * This implies that all of the advanced atlasManager functionality (i.e.,
24 * adding glyphs to the atlas) are only available at flush time.
25 */
26class GrAtlasManager : public GrOnFlushCallbackObject, public GrDrawOpAtlas::GenerationCounter {
27public:
28 GrAtlasManager(GrProxyProvider*, size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
29 ~GrAtlasManager() override;
30
31 // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
32 // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in
33 // GrStrikeCache.cpp
34 GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
35 if (kA565_GrMaskFormat == format &&
36 !fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
37 GrRenderable::kNo).isValid()) {
38 format = kARGB_GrMaskFormat;
39 }
40 return format;
41 }
42
43 // if getViews returns nullptr, the client must not try to use other functions on the
44 // GrStrikeCache which use the atlas. This function *must* be called first, before other
45 // functions which use the atlas. Note that we can have proxies available but none active
46 // (i.e., none instantiated).
47 const GrSurfaceProxyView* getViews(GrMaskFormat format, unsigned int* numActiveProxies) {
48 format = this->resolveMaskFormat(format);
49 if (this->initAtlas(format)) {
50 *numActiveProxies = this->getAtlas(format)->numActivePages();
51 return this->getAtlas(format)->getViews();
52 }
53 *numActiveProxies = 0;
54 return nullptr;
55 }
56
57 void freeAll();
58
59 bool hasGlyph(GrMaskFormat, GrGlyph*);
60
61 // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
62 // the client must pass in the current op token along with the GrGlyph.
63 // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
64 // For convenience, this function will also set the use token for the current glyph if required
65 // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
66 void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrMaskFormat, GrGlyph*,
67 GrDeferredUploadToken);
68
69 void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
70 GrDeferredUploadToken token,
71 GrMaskFormat format) {
72 this->getAtlas(format)->setLastUseTokenBulk(updater, token);
73 }
74
75 // add to texture atlas that matches this format
76 GrDrawOpAtlas::ErrorCode addToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrMaskFormat,
77 int width, int height, const void* image,
78 GrDrawOpAtlas::AtlasLocator*);
79
80 // Some clients may wish to verify the integrity of the texture backing store of the
81 // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
82 // changes every time something is removed from the texture backing store.
83 uint64_t atlasGeneration(GrMaskFormat format) const {
84 return this->getAtlas(format)->atlasGeneration();
85 }
86
87 // GrOnFlushCallbackObject overrides
88
89 void preFlush(GrOnFlushResourceProvider* onFlushRP, const uint32_t*, int) override {
90 for (int i = 0; i < kMaskFormatCount; ++i) {
91 if (fAtlases[i]) {
92 fAtlases[i]->instantiate(onFlushRP);
93 }
94 }
95 }
96
97 void postFlush(GrDeferredUploadToken startTokenForNextFlush,
98 const uint32_t* opsTaskIDs, int numOpsTaskIDs) override {
99 for (int i = 0; i < kMaskFormatCount; ++i) {
100 if (fAtlases[i]) {
101 fAtlases[i]->compact(startTokenForNextFlush);
102 }
103 }
104 }
105
106 // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active
107 // OnFlushCallbackObject list
108 bool retainOnFreeGpuResources() override { return true; }
109
110 ///////////////////////////////////////////////////////////////////////////
111 // Functions intended debug only
112#ifdef SK_DEBUG
113 void dump(GrContext* context) const;
114#endif
115
116 void setAtlasDimensionsToMinimum_ForTesting();
117 void setMaxPages_TestingOnly(uint32_t maxPages);
118
119private:
120 bool initAtlas(GrMaskFormat);
121
122 // There is a 1:1 mapping between GrMaskFormats and atlas indices
123 static int MaskFormatToAtlasIndex(GrMaskFormat format) { return static_cast<int>(format); }
124 static GrMaskFormat AtlasIndexToMaskFormat(int idx) { return static_cast<GrMaskFormat>(idx); }
125
126 GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
127 format = this->resolveMaskFormat(format);
128 int atlasIndex = MaskFormatToAtlasIndex(format);
129 SkASSERT(fAtlases[atlasIndex]);
130 return fAtlases[atlasIndex].get();
131 }
132
133 GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
134 std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
135 static_assert(kMaskFormatCount == 3);
136 GrProxyProvider* fProxyProvider;
137 sk_sp<const GrCaps> fCaps;
138 GrDrawOpAtlasConfig fAtlasConfig;
139
140 typedef GrOnFlushCallbackObject INHERITED;
141};
142
143#endif // GrAtlasManager_DEFINED
144