Fission GrAtlasGlyphCache in two (take 2)
Reland all the things
This CL splits the old GrAtlasGlyphCache into a GrAtlasGlyphCache and an GrAtlasManager.
The GrAtlasManager itself is split into a rather limited base class (GrRestrictedAtlasManager)
and the all powerful GrAtlasManager. The GrRestrictedAtlasManager is available at op creation
time and provides access to the proxies backing the atlases. The full GrAtlasManager is
only available at flush time and allows instantiation of the proxies and uploading to them.
In the DDL world all of the DDL Contexts will receive a GrRestrictedAtlasManager-version of the
GrAtlasManager in the main thread. This future atlas manager will have had all of its
GrDrawOpAtlases created (but not instantiated) so there should be no race conditions.
TBR=jvanverth@google.com
Change-Id: I05c6cd8d301bf2decca39765e5cae62993d9da04
Reviewed-on: https://skia-review.googlesource.com/111362
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/text/GrAtlasManager.h b/src/gpu/text/GrAtlasManager.h
new file mode 100644
index 0000000..4629cb1
--- /dev/null
+++ b/src/gpu/text/GrAtlasManager.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrAtlasManager_DEFINED
+#define GrAtlasManager_DEFINED
+
+#include "GrDrawOpAtlas.h"
+#include "GrOnFlushResourceProvider.h"
+
+class GrAtlasGlypCache;
+class GrAtlasTextStrike;
+struct GrGlyph;
+
+ /** The GrAtlasManager classes manage the lifetime of and access to GrDrawOpAtlases.
+ * The restricted version is available at op creation time and only allows basic access
+ * to the proxies (so the created ops can reference them). The full GrAtlasManager class
+ * is only available at flush time and only via the GrOpFlushState.
+ *
+ * This organization implies that all of the advanced atlasManager functionality (i.e.,
+ * adding glyphs to the atlas) are only available at flush time.
+ */
+class GrRestrictedAtlasManager : public GrOnFlushCallbackObject {
+public:
+ GrRestrictedAtlasManager(sk_sp<const GrCaps>, float maxTextureBytes,
+ GrDrawOpAtlas::AllowMultitexturing);
+ ~GrRestrictedAtlasManager() override;
+
+ // if getProxies returns nullptr, the client must not try to use other functions on the
+ // GrGlyphCache which use the atlas. This function *must* be called first, before other
+ // functions which use the atlas.
+ const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numProxies) {
+ if (this->initAtlas(format)) {
+ *numProxies = this->getAtlas(format)->numActivePages();
+ return this->getAtlas(format)->getProxies();
+ }
+ *numProxies = 0;
+ return nullptr;
+ }
+
+ SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
+
+protected:
+ // There is a 1:1 mapping between GrMaskFormats and atlas indices
+ static int MaskFormatToAtlasIndex(GrMaskFormat format) {
+ static const int sAtlasIndices[] = {
+ kA8_GrMaskFormat,
+ kA565_GrMaskFormat,
+ kARGB_GrMaskFormat,
+ };
+ static_assert(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, "array_size_mismatch");
+
+ SkASSERT(sAtlasIndices[format] < kMaskFormatCount);
+ return sAtlasIndices[format];
+ }
+
+ GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
+ int atlasIndex = MaskFormatToAtlasIndex(format);
+ SkASSERT(fAtlases[atlasIndex]);
+ return fAtlases[atlasIndex].get();
+ }
+
+ sk_sp<const GrCaps> fCaps;
+ GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
+ std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
+ GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];
+ SkScalar fGlyphSizeLimit;
+
+private:
+ virtual bool initAtlas(GrMaskFormat) = 0;
+
+ typedef GrOnFlushCallbackObject INHERITED;
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+class GrAtlasManager : public GrRestrictedAtlasManager {
+public:
+ GrAtlasManager(GrProxyProvider*, GrGlyphCache*,
+ float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
+
+ void freeAll();
+
+ bool hasGlyph(GrGlyph* glyph);
+
+ // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store,
+ // the client must pass in the current op token along with the GrGlyph.
+ // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
+ // For convenience, this function will also set the use token for the current glyph if required
+ // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
+ void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrGlyph*,
+ GrDeferredUploadToken);
+
+ void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
+ GrDeferredUploadToken token,
+ GrMaskFormat format) {
+ this->getAtlas(format)->setLastUseTokenBulk(updater, token);
+ }
+
+ // add to texture atlas that matches this format
+ bool addToAtlas(GrResourceProvider*, GrGlyphCache*, GrAtlasTextStrike*,
+ GrDrawOpAtlas::AtlasID*, GrDeferredUploadTarget*, GrMaskFormat,
+ int width, int height, const void* image, SkIPoint16* loc);
+
+ // Some clients may wish to verify the integrity of the texture backing store of the
+ // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which
+ // changes every time something is removed from the texture backing store.
+ uint64_t atlasGeneration(GrMaskFormat format) const {
+ return this->getAtlas(format)->atlasGeneration();
+ }
+
+ // GrOnFlushCallbackObject overrides
+
+ void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int,
+ SkTArray<sk_sp<GrRenderTargetContext>>*) override {
+ for (int i = 0; i < kMaskFormatCount; ++i) {
+ if (fAtlases[i]) {
+ fAtlases[i]->instantiate(onFlushResourceProvider);
+ }
+ }
+ }
+
+ void postFlush(GrDeferredUploadToken startTokenForNextFlush,
+ const uint32_t* opListIDs, int numOpListIDs) override {
+ for (int i = 0; i < kMaskFormatCount; ++i) {
+ if (fAtlases[i]) {
+ fAtlases[i]->compact(startTokenForNextFlush);
+ }
+ }
+ }
+
+ // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active
+ // OnFlushCallbackObject list
+ bool retainOnFreeGpuResources() override { return true; }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Functions intended debug only
+#ifdef SK_DEBUG
+ void dump(GrContext* context) const;
+#endif
+
+ void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]);
+
+private:
+ bool initAtlas(GrMaskFormat) override;
+
+ GrProxyProvider* fProxyProvider;
+ GrGlyphCache* fGlyphCache;
+
+ typedef GrRestrictedAtlasManager INHERITED;
+};
+
+#endif // GrAtlasManager_DEFINED