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