blob: e857ae825d0c7c6e3227dd9227cd3acf45e9894d [file] [log] [blame]
Robert Phillipsc4039ea2018-03-01 11:36:45 -05001/*
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
Timothy Liang91e260f2018-06-15 13:28:35 -040011#include "GrCaps.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050012#include "GrDrawOpAtlas.h"
13#include "GrOnFlushResourceProvider.h"
Timothy Liang91e260f2018-06-15 13:28:35 -040014#include "GrProxyProvider.h"
Robert Phillipsc4039ea2018-03-01 11:36:45 -050015
16class GrAtlasGlypCache;
Robert Phillipscaf1ebb2018-03-01 14:28:44 -050017class GrTextStrike;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050018struct GrGlyph;
19
Robert Phillips5a66efb2018-03-07 15:13:18 -050020//////////////////////////////////////////////////////////////////////////////////////////////////
21/** The GrAtlasManager manages the lifetime of and access to GrDrawOpAtlases.
22 * It is only available at flush and only via the GrOpFlushState.
23 *
24 * This implies that all of the advanced atlasManager functionality (i.e.,
25 * adding glyphs to the atlas) are only available at flush time.
26 */
27class GrAtlasManager : public GrOnFlushCallbackObject {
Robert Phillipsc4039ea2018-03-01 11:36:45 -050028public:
Robert Phillips5a66efb2018-03-07 15:13:18 -050029 GrAtlasManager(GrProxyProvider*, GrGlyphCache*,
Herb Derby3c4d5332018-09-07 15:27:57 -040030 size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
Robert Phillips5a66efb2018-03-07 15:13:18 -050031 ~GrAtlasManager() override;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050032
Timothy Liang91e260f2018-06-15 13:28:35 -040033 // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using
34 // Metal on macOS). The actual conversion of the data is handled in get_packed_glyph_image() in
35 // GrGlyphCache.cpp
36 GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
37 if (kA565_GrMaskFormat == format &&
38 !fProxyProvider->caps()->isConfigTexturable(kRGB_565_GrPixelConfig)) {
39 format = kARGB_GrMaskFormat;
40 }
41 return format;
42 }
43
Robert Phillipsc4039ea2018-03-01 11:36:45 -050044 // if getProxies returns nullptr, the client must not try to use other functions on the
45 // GrGlyphCache which use the atlas. This function *must* be called first, before other
Jim Van Verthcbeae032018-05-16 14:54:41 -040046 // functions which use the atlas. Note that we can have proxies available but none active
47 // (i.e., none instantiated).
48 const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numActiveProxies) {
Timothy Liang91e260f2018-06-15 13:28:35 -040049 format = this->resolveMaskFormat(format);
Robert Phillipsc4039ea2018-03-01 11:36:45 -050050 if (this->initAtlas(format)) {
Jim Van Verthcbeae032018-05-16 14:54:41 -040051 *numActiveProxies = this->getAtlas(format)->numActivePages();
Robert Phillipsc4039ea2018-03-01 11:36:45 -050052 return this->getAtlas(format)->getProxies();
53 }
Jim Van Verthcbeae032018-05-16 14:54:41 -040054 *numActiveProxies = 0;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050055 return nullptr;
56 }
57
58 SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
59
Robert Phillipsc4039ea2018-03-01 11:36:45 -050060 void freeAll();
61
62 bool hasGlyph(GrGlyph* glyph);
63
64 // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
65 // the client must pass in the current op token along with the GrGlyph.
66 // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
67 // For convenience, this function will also set the use token for the current glyph if required
68 // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
69 void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrGlyph*,
70 GrDeferredUploadToken);
71
72 void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
73 GrDeferredUploadToken token,
74 GrMaskFormat format) {
75 this->getAtlas(format)->setLastUseTokenBulk(updater, token);
76 }
77
78 // add to texture atlas that matches this format
Robert Phillipsd2e9f762018-03-07 11:54:37 -050079 GrDrawOpAtlas::ErrorCode addToAtlas(
80 GrResourceProvider*, GrGlyphCache*, GrTextStrike*,
Robert Phillipsc4039ea2018-03-01 11:36:45 -050081 GrDrawOpAtlas::AtlasID*, GrDeferredUploadTarget*, GrMaskFormat,
82 int width, int height, const void* image, SkIPoint16* loc);
83
84 // Some clients may wish to verify the integrity of the texture backing store of the
85 // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
86 // changes every time something is removed from the texture backing store.
87 uint64_t atlasGeneration(GrMaskFormat format) const {
88 return this->getAtlas(format)->atlasGeneration();
89 }
90
91 // GrOnFlushCallbackObject overrides
92
93 void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int,
94 SkTArray<sk_sp<GrRenderTargetContext>>*) override {
95 for (int i = 0; i < kMaskFormatCount; ++i) {
96 if (fAtlases[i]) {
97 fAtlases[i]->instantiate(onFlushResourceProvider);
98 }
99 }
100 }
101
102 void postFlush(GrDeferredUploadToken startTokenForNextFlush,
103 const uint32_t* opListIDs, int numOpListIDs) override {
104 for (int i = 0; i < kMaskFormatCount; ++i) {
105 if (fAtlases[i]) {
106 fAtlases[i]->compact(startTokenForNextFlush);
107 }
108 }
109 }
110
111 // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active
112 // OnFlushCallbackObject list
113 bool retainOnFreeGpuResources() override { return true; }
114
115 ///////////////////////////////////////////////////////////////////////////
116 // Functions intended debug only
117#ifdef SK_DEBUG
118 void dump(GrContext* context) const;
119#endif
120
Herb Derby3c4d5332018-09-07 15:27:57 -0400121 void setAtlasSizesToMinimum_ForTesting();
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500122 void setMaxPages_TestingOnly(uint32_t maxPages);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500123
124private:
Robert Phillips5a66efb2018-03-07 15:13:18 -0500125 bool initAtlas(GrMaskFormat);
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500126
Robert Phillips5a66efb2018-03-07 15:13:18 -0500127 // There is a 1:1 mapping between GrMaskFormats and atlas indices
128 static int MaskFormatToAtlasIndex(GrMaskFormat format) {
129 static const int sAtlasIndices[] = {
130 kA8_GrMaskFormat,
131 kA565_GrMaskFormat,
132 kARGB_GrMaskFormat,
133 };
134 static_assert(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, "array_size_mismatch");
135
136 SkASSERT(sAtlasIndices[format] < kMaskFormatCount);
137 return sAtlasIndices[format];
138 }
139
140 GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
Timothy Liang91e260f2018-06-15 13:28:35 -0400141 format = this->resolveMaskFormat(format);
Robert Phillips5a66efb2018-03-07 15:13:18 -0500142 int atlasIndex = MaskFormatToAtlasIndex(format);
143 SkASSERT(fAtlases[atlasIndex]);
144 return fAtlases[atlasIndex].get();
145 }
146
Robert Phillips5a66efb2018-03-07 15:13:18 -0500147 GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
148 std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
Robert Phillips5a66efb2018-03-07 15:13:18 -0500149 SkScalar fGlyphSizeLimit;
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500150 GrProxyProvider* fProxyProvider;
Herb Derby3c4d5332018-09-07 15:27:57 -0400151 sk_sp<const GrCaps> fCaps;
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500152 GrGlyphCache* fGlyphCache;
Herb Derby3c4d5332018-09-07 15:27:57 -0400153 GrDrawOpAtlasConfig fAtlasConfigs;
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500154
Robert Phillips5a66efb2018-03-07 15:13:18 -0500155 typedef GrOnFlushCallbackObject INHERITED;
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500156};
157
158#endif // GrAtlasManager_DEFINED