aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/text
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/text')
-rw-r--r--src/gpu/text/GrAtlasGlyphCache.h270
-rw-r--r--src/gpu/text/GrAtlasManager.cpp222
-rw-r--r--src/gpu/text/GrAtlasManager.h155
-rw-r--r--src/gpu/text/GrAtlasTextBlob.cpp21
-rw-r--r--src/gpu/text/GrAtlasTextBlob.h24
-rw-r--r--src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp29
-rw-r--r--src/gpu/text/GrAtlasTextContext.cpp121
-rw-r--r--src/gpu/text/GrAtlasTextContext.h27
-rw-r--r--src/gpu/text/GrGlyphCache.cpp (renamed from src/gpu/text/GrAtlasGlyphCache.cpp)191
-rw-r--r--src/gpu/text/GrGlyphCache.h148
-rw-r--r--src/gpu/text/GrTextUtils.h2
11 files changed, 661 insertions, 549 deletions
diff --git a/src/gpu/text/GrAtlasGlyphCache.h b/src/gpu/text/GrAtlasGlyphCache.h
deleted file mode 100644
index 84b7d1b249..0000000000
--- a/src/gpu/text/GrAtlasGlyphCache.h
+++ /dev/null
@@ -1,270 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrAtlasGlyphCache_DEFINED
-#define GrAtlasGlyphCache_DEFINED
-
-#include "GrCaps.h"
-#include "GrDrawOpAtlas.h"
-#include "GrGlyph.h"
-#include "GrOnFlushResourceProvider.h"
-#include "SkArenaAlloc.h"
-#include "SkGlyphCache.h"
-#include "SkTDynamicHash.h"
-
-class GrAtlasGlyphCache;
-class GrGpu;
-
-/**
- * The GrAtlasTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory
- * is indexed by a PackedID and SkGlyphCache. The SkGlyphCache is what actually creates the mask.
- * The GrAtlasTextStrike may outlive the generating SkGlyphCache. However, it retains a copy
- * of it's SkDescriptor as a key to access (or regenerate) the SkGlyphCache. GrAtlasTextStrike are
- * created by and owned by a GrAtlasGlyphCache.
- */
-class GrAtlasTextStrike : public SkNVRefCnt<GrAtlasTextStrike> {
-public:
- GrAtlasTextStrike(const SkDescriptor& fontScalerKey);
- ~GrAtlasTextStrike();
-
- inline GrGlyph* getGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed,
- SkGlyphCache* cache) {
- GrGlyph* glyph = fCache.find(packed);
- if (nullptr == glyph) {
- glyph = this->generateGlyph(skGlyph, packed, cache);
- }
- return glyph;
- }
-
- // This variant of the above function is called by GrAtlasTextOp. At this point, it is possible
- // that the maskformat of the glyph differs from what we expect. In these cases we will just
- // draw a clear square.
- // skbug:4143 crbug:510931
- inline GrGlyph* getGlyph(GrGlyph::PackedID packed,
- GrMaskFormat expectedMaskFormat,
- SkGlyphCache* cache) {
- GrGlyph* glyph = fCache.find(packed);
- if (nullptr == glyph) {
- // We could return this to the caller, but in practice it adds code complexity for
- // potentially little benefit(ie, if the glyph is not in our font cache, then its not
- // in the atlas and we're going to be doing a texture upload anyways).
- const SkGlyph& skGlyph = GrToSkGlyph(cache, packed);
- glyph = this->generateGlyph(skGlyph, packed, cache);
- glyph->fMaskFormat = expectedMaskFormat;
- }
- return glyph;
- }
-
- // returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's
- // mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never
- // happen.
- // TODO we can handle some of these cases if we really want to, but the long term solution is to
- // get the actual glyph image itself when we get the glyph metrics.
- bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*,
- SkGlyphCache*, GrMaskFormat expectedMaskFormat);
-
- // testing
- int countGlyphs() const { return fCache.count(); }
-
- // remove any references to this plot
- void removeID(GrDrawOpAtlas::AtlasID);
-
- // If a TextStrike is abandoned by the cache, then the caller must get a new strike
- bool isAbandoned() const { return fIsAbandoned; }
-
- static const SkDescriptor& GetKey(const GrAtlasTextStrike& ts) {
- return *ts.fFontScalerKey.getDesc();
- }
-
- static uint32_t Hash(const SkDescriptor& desc) { return desc.getChecksum(); }
-
-private:
- SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
- SkAutoDescriptor fFontScalerKey;
- SkArenaAlloc fPool{512};
-
- int fAtlasedGlyphs;
- bool fIsAbandoned;
-
- static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, GrGlyph::PackedID id) {
- return cache->getGlyphIDMetrics(GrGlyph::UnpackID(id),
- GrGlyph::UnpackFixedX(id),
- GrGlyph::UnpackFixedY(id));
- }
-
- GrGlyph* generateGlyph(const SkGlyph&, GrGlyph::PackedID, SkGlyphCache*);
-
- friend class GrAtlasGlyphCache;
-};
-
-/**
- * GrAtlasGlyphCache manages strikes which are indexed by a SkGlyphCache. These strikes can then be
- * used to generate individual Glyph Masks. The GrAtlasGlyphCache also manages GrDrawOpAtlases,
- * though this is more or less transparent to the client(aside from atlasGeneration, described
- * below).
- */
-class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
-public:
- GrAtlasGlyphCache(GrProxyProvider*, float maxTextureBytes,
- GrDrawOpAtlas::AllowMultitexturing);
- ~GrAtlasGlyphCache() override;
- // The user of the cache may hold a long-lived ref to the returned strike. However, actions by
- // another client of the cache may cause the strike to be purged while it is still reffed.
- // Therefore, the caller must check GrAtlasTextStrike::isAbandoned() if there are other
- // interactions with the cache since the strike was received.
- inline GrAtlasTextStrike* getStrike(const SkGlyphCache* cache) {
- GrAtlasTextStrike* strike = fCache.find(cache->getDescriptor());
- if (nullptr == strike) {
- strike = this->generateStrike(cache);
- }
- return strike;
- }
-
- void freeAll();
-
- // if getProxies returns nullptr, the client must not try to use other functions on the
- // GrAtlasGlyphCache 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) {
- SkASSERT(numProxies);
-
- if (this->initAtlas(format)) {
- *numProxies = this->getAtlas(format)->numActivePages();
- return this->getAtlas(format)->getProxies();
- }
- *numProxies = 0;
- return nullptr;
- }
-
- SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
-
- bool hasGlyph(GrGlyph* glyph) {
- SkASSERT(glyph);
- return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
- }
-
- // 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* updater, GrGlyph* glyph,
- GrDeferredUploadToken token) {
- SkASSERT(glyph);
- updater->add(glyph->fID);
- this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
- }
-
- 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* resourceProvider, GrAtlasTextStrike* strike,
- GrDrawOpAtlas::AtlasID* id,
- GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height,
- const void* image, SkIPoint16* loc) {
- fPreserveStrike = strike;
- return this->getAtlas(format)->addToAtlas(resourceProvider, id, target,
- width, height, image, 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*, int) 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*) const;
-#endif
-
- void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]);
-
-private:
- static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) {
- switch (format) {
- case kA8_GrMaskFormat:
- return kAlpha_8_GrPixelConfig;
- case kA565_GrMaskFormat:
- return kRGB_565_GrPixelConfig;
- case kARGB_GrMaskFormat:
- return caps.srgbSupport() ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
- default:
- SkDEBUGFAIL("unsupported GrMaskFormat");
- return kAlpha_8_GrPixelConfig;
- }
- }
-
- // 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];
- }
-
- bool initAtlas(GrMaskFormat);
-
- GrAtlasTextStrike* generateStrike(const SkGlyphCache* cache) {
- GrAtlasTextStrike* strike = new GrAtlasTextStrike(cache->getDescriptor());
- fCache.add(strike);
- return strike;
- }
-
- GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
- int atlasIndex = MaskFormatToAtlasIndex(format);
- SkASSERT(fAtlases[atlasIndex]);
- return fAtlases[atlasIndex].get();
- }
-
- static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
-
- using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
- GrProxyProvider* fProxyProvider;
- StrikeHash fCache;
- GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
- std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
- GrAtlasTextStrike* fPreserveStrike;
- GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];
- SkScalar fGlyphSizeLimit;
-};
-
-#endif
diff --git a/src/gpu/text/GrAtlasManager.cpp b/src/gpu/text/GrAtlasManager.cpp
new file mode 100644
index 0000000000..6e227a94a2
--- /dev/null
+++ b/src/gpu/text/GrAtlasManager.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrAtlasManager.h"
+
+#include "GrCaps.h"
+#include "GrGlyph.h"
+#include "GrGlyphCache.h"
+#include "GrProxyProvider.h"
+
+GrRestrictedAtlasManager::GrRestrictedAtlasManager(
+ sk_sp<const GrCaps> caps,
+ float maxTextureBytes,
+ GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
+ : fCaps(std::move(caps))
+ , fAllowMultitexturing(allowMultitexturing) {
+ // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
+ int log2MaxTextureSize = SkPrevLog2(fCaps->maxTextureSize());
+ int log2MaxDim = 9;
+ for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
+ int maxDim = 1 << log2MaxDim;
+ int minDim = 1 << (log2MaxDim - 1);
+
+ if (maxDim * minDim * 4 >= maxTextureBytes) break;
+ }
+
+ int log2MinDim = log2MaxDim - 1;
+ int maxDim = 1 << log2MaxDim;
+ int minDim = 1 << log2MinDim;
+ // Plots are either 256 or 512.
+ int maxPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 2)));
+ int minPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 3)));
+
+ // Setup default atlas configs. The A8 atlas uses maxDim for both width and height, as the A8
+ // format is already very compact.
+ fAtlasConfigs[kA8_GrMaskFormat].fWidth = maxDim;
+ fAtlasConfigs[kA8_GrMaskFormat].fHeight = maxDim;
+ fAtlasConfigs[kA8_GrMaskFormat].fPlotWidth = maxPlot;
+ fAtlasConfigs[kA8_GrMaskFormat].fPlotHeight = minPlot;
+
+ // A565 and ARGB use maxDim x minDim.
+ fAtlasConfigs[kA565_GrMaskFormat].fWidth = minDim;
+ fAtlasConfigs[kA565_GrMaskFormat].fHeight = maxDim;
+ fAtlasConfigs[kA565_GrMaskFormat].fPlotWidth = minPlot;
+ fAtlasConfigs[kA565_GrMaskFormat].fPlotHeight = minPlot;
+
+ fAtlasConfigs[kARGB_GrMaskFormat].fWidth = minDim;
+ fAtlasConfigs[kARGB_GrMaskFormat].fHeight = maxDim;
+ fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = minPlot;
+ fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = minPlot;
+
+ fGlyphSizeLimit = minPlot;
+}
+
+GrRestrictedAtlasManager::~GrRestrictedAtlasManager() {
+}
+
+static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format, const GrCaps& caps) {
+ switch (format) {
+ case kA8_GrMaskFormat:
+ return kAlpha_8_GrPixelConfig;
+ case kA565_GrMaskFormat:
+ return kRGB_565_GrPixelConfig;
+ case kARGB_GrMaskFormat:
+ return caps.srgbSupport() ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig;
+ default:
+ SkDEBUGFAIL("unsupported GrMaskFormat");
+ return kAlpha_8_GrPixelConfig;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* glyphCache,
+ float maxTextureBytes,
+ GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
+ : INHERITED(proxyProvider->refCaps(), maxTextureBytes, allowMultitexturing)
+ , fProxyProvider(proxyProvider)
+ , fGlyphCache(glyphCache) {
+}
+
+void GrAtlasManager::freeAll() {
+ for (int i = 0; i < kMaskFormatCount; ++i) {
+ fAtlases[i] = nullptr;
+ }
+}
+
+bool GrAtlasManager::hasGlyph(GrGlyph* glyph) {
+ SkASSERT(glyph);
+ return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
+}
+
+// add to texture atlas that matches this format
+bool GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider,
+ GrGlyphCache* glyphCache,
+ GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
+ GrDeferredUploadTarget* target, GrMaskFormat format,
+ int width, int height, const void* image, SkIPoint16* loc) {
+ glyphCache->setStrikeToPreserve(strike);
+ return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, width, height,
+ image, loc);
+}
+
+void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater,
+ GrGlyph* glyph,
+ GrDeferredUploadToken token) {
+ SkASSERT(glyph);
+ updater->add(glyph->fID);
+ this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
+}
+
+#ifdef SK_DEBUG
+#include "GrContextPriv.h"
+#include "GrSurfaceProxy.h"
+#include "GrSurfaceContext.h"
+#include "GrTextureProxy.h"
+
+#include "SkBitmap.h"
+#include "SkImageEncoder.h"
+#include "SkStream.h"
+#include <stdio.h>
+
+/**
+ * Write the contents of the surface proxy to a PNG. Returns true if successful.
+ * @param filename Full path to desired file
+ */
+static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) {
+ if (!sProxy) {
+ return false;
+ }
+
+ SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(),
+ kRGBA_8888_SkColorType, kPremul_SkAlphaType);
+ SkBitmap bm;
+ if (!bm.tryAllocPixels(ii)) {
+ return false;
+ }
+
+ sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
+ sk_ref_sp(sProxy)));
+ if (!sContext || !sContext->asTextureProxy()) {
+ return false;
+ }
+
+ bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0);
+ if (!result) {
+ SkDebugf("------ failed to read pixels for %s\n", filename);
+ return false;
+ }
+
+ // remove any previous version of this file
+ remove(filename);
+
+ SkFILEWStream file(filename);
+ if (!file.isValid()) {
+ SkDebugf("------ failed to create file: %s\n", filename);
+ remove(filename); // remove any partial file
+ return false;
+ }
+
+ if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
+ SkDebugf("------ failed to encode %s\n", filename);
+ remove(filename); // remove any partial file
+ return false;
+ }
+
+ return true;
+}
+
+void GrAtlasManager::dump(GrContext* context) const {
+ static int gDumpCount = 0;
+ for (int i = 0; i < kMaskFormatCount; ++i) {
+ if (fAtlases[i]) {
+ const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies();
+ for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
+ SkASSERT(proxies[pageIdx]);
+ SkString filename;
+#ifdef SK_BUILD_FOR_ANDROID
+ filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
+#else
+ filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
+#endif
+
+ save_pixels(context, proxies[pageIdx].get(), filename.c_str());
+ }
+ }
+ }
+ ++gDumpCount;
+}
+#endif
+
+void GrAtlasManager::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) {
+ // Delete any old atlases.
+ // This should be safe to do as long as we are not in the middle of a flush.
+ for (int i = 0; i < kMaskFormatCount; i++) {
+ fAtlases[i] = nullptr;
+ }
+ memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs));
+}
+
+bool GrAtlasManager::initAtlas(GrMaskFormat format) {
+ int index = MaskFormatToAtlasIndex(format);
+ if (!fAtlases[index]) {
+ GrPixelConfig config = mask_format_to_pixel_config(format, *fCaps);
+ int width = fAtlasConfigs[index].fWidth;
+ int height = fAtlasConfigs[index].fHeight;
+ int numPlotsX = fAtlasConfigs[index].numPlotsX();
+ int numPlotsY = fAtlasConfigs[index].numPlotsY();
+
+ fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height,
+ numPlotsX, numPlotsY, fAllowMultitexturing,
+ &GrGlyphCache::HandleEviction,
+ fGlyphCache);
+ if (!fAtlases[index]) {
+ return false;
+ }
+ }
+ return true;
+}
diff --git a/src/gpu/text/GrAtlasManager.h b/src/gpu/text/GrAtlasManager.h
new file mode 100644
index 0000000000..4629cb173b
--- /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
diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp
index 90bcf5a224..35e783019f 100644
--- a/src/gpu/text/GrAtlasTextBlob.cpp
+++ b/src/gpu/text/GrAtlasTextBlob.cpp
@@ -250,8 +250,8 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp(
const Run::SubRunInfo& info, int glyphCount, uint16_t run, uint16_t subRun,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
- GrTextUtils::Target* target) {
+ const GrDistanceFieldAdjustTable* distanceAdjustTable,
+ GrRestrictedAtlasManager* restrictedAtlasManager, GrTextUtils::Target* target) {
GrMaskFormat format = info.maskFormat();
GrPaint grPaint;
@@ -260,11 +260,12 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp(
if (info.drawAsDistanceFields()) {
bool useBGR = SkPixelGeometryIsBGR(props.pixelGeometry());
op = GrAtlasTextOp::MakeDistanceField(
- std::move(grPaint), glyphCount, cache, distanceAdjustTable,
+ std::move(grPaint), glyphCount, restrictedAtlasManager, distanceAdjustTable,
target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(),
info.hasUseLCDText(), useBGR, info.isAntiAliased());
} else {
- op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount, cache);
+ op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format,
+ glyphCount, restrictedAtlasManager);
}
GrAtlasTextOp::Geometry& geometry = op->geometry();
geometry.fViewMatrix = viewMatrix;
@@ -300,8 +301,8 @@ static void calculate_translation(bool applyVM,
}
}
-void GrAtlasTextBlob::flush(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Target* target,
- const SkSurfaceProps& props,
+void GrAtlasTextBlob::flush(GrRestrictedAtlasManager* restrictedAtlasManager,
+ GrTextUtils::Target* target, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
const GrTextUtils::Paint& paint, const GrClip& clip,
const SkMatrix& viewMatrix, const SkIRect& clipBounds,
@@ -376,7 +377,7 @@ void GrAtlasTextBlob::flush(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Tar
if (submitOp) {
auto op = this->makeOp(info, glyphCount, runIndex, subRun, viewMatrix, x, y,
clipRect, std::move(paint), props, distanceAdjustTable,
- atlasGlyphCache, target);
+ restrictedAtlasManager, target);
if (op) {
if (skipClip) {
target->addDrawOp(GrNoClip(), std::move(op));
@@ -394,12 +395,12 @@ void GrAtlasTextBlob::flush(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Tar
std::unique_ptr<GrDrawOp> GrAtlasTextBlob::test_makeOp(
int glyphCount, uint16_t run, uint16_t subRun, const SkMatrix& viewMatrix,
SkScalar x, SkScalar y, const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
- GrTextUtils::Target* target) {
+ const GrDistanceFieldAdjustTable* distanceAdjustTable,
+ GrRestrictedAtlasManager* restrictedAtlasManager, GrTextUtils::Target* target) {
const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun];
SkIRect emptyRect = SkIRect::MakeEmpty();
return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, emptyRect, paint, props,
- distanceAdjustTable, cache, target);
+ distanceAdjustTable, restrictedAtlasManager, target);
}
void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlob& r) {
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 0fae3cd8c7..9f91cae957 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -8,9 +8,9 @@
#ifndef GrAtlasTextBlob_DEFINED
#define GrAtlasTextBlob_DEFINED
-#include "GrAtlasGlyphCache.h"
#include "GrColor.h"
#include "GrDrawOpAtlas.h"
+#include "GrGlyphCache.h"
#include "GrMemoryPool.h"
#include "GrTextUtils.h"
#include "SkDescriptor.h"
@@ -22,8 +22,13 @@
#include "SkSurfaceProps.h"
#include "SkTInternalLList.h"
+class GrAtlasManager;
struct GrDistanceFieldAdjustTable;
+struct GrGlyph;
+class GrGlyphCache;
class GrMemoryPool;
+class GrRestrictedAtlasManager;
+
class SkDrawFilter;
class SkTextBlob;
class SkTextBlobRunIterator;
@@ -201,7 +206,7 @@ public:
bool mustRegenerate(const GrTextUtils::Paint&, const SkMaskFilterBase::BlurRec& blurRec,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
- void flush(GrAtlasGlyphCache*, GrTextUtils::Target*, const SkSurfaceProps& props,
+ void flush(GrRestrictedAtlasManager*, GrTextUtils::Target*, const SkSurfaceProps& props,
const GrDistanceFieldAdjustTable* distanceAdjustTable,
const GrTextUtils::Paint& paint, const GrClip& clip,
const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x,
@@ -276,8 +281,8 @@ public:
std::unique_ptr<GrDrawOp> test_makeOp(int glyphCount, uint16_t run, uint16_t subRun,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y,
const GrTextUtils::Paint&, const SkSurfaceProps&,
- const GrDistanceFieldAdjustTable*, GrAtlasGlyphCache*,
- GrTextUtils::Target*);
+ const GrDistanceFieldAdjustTable*,
+ GrRestrictedAtlasManager*, GrTextUtils::Target*);
private:
GrAtlasTextBlob()
@@ -506,9 +511,8 @@ private:
inline std::unique_ptr<GrAtlasTextOp> makeOp(
const Run::SubRunInfo& info, int glyphCount, uint16_t run, uint16_t subRun,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect,
- const GrTextUtils::Paint& paint, const SkSurfaceProps& props,
- const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache,
- GrTextUtils::Target*);
+ const GrTextUtils::Paint&, const SkSurfaceProps&,
+ const GrDistanceFieldAdjustTable*, GrRestrictedAtlasManager* , GrTextUtils::Target*);
struct StrokeInfo {
SkScalar fFrameWidth;
@@ -562,7 +566,8 @@ public:
*/
VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
- GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*);
+ GrDeferredUploadTarget*, GrGlyphCache*, GrAtlasManager*,
+ SkAutoGlyphCache*);
struct Result {
/**
@@ -593,7 +598,8 @@ private:
const SkMatrix& fViewMatrix;
GrAtlasTextBlob* fBlob;
GrDeferredUploadTarget* fUploadTarget;
- GrAtlasGlyphCache* fGlyphCache;
+ GrGlyphCache* fGlyphCache;
+ GrAtlasManager* fFullAtlasManager;
SkAutoGlyphCache* fLazyCache;
Run* fRun;
Run::SubRunInfo* fSubRun;
diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
index 500ae31703..54001c2628 100644
--- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
+++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "GrAtlasManager.h"
#include "GrAtlasTextBlob.h"
#include "GrTextUtils.h"
#include "SkDistanceFieldGen.h"
@@ -193,13 +194,14 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob,
int runIdx, int subRunIdx,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
- GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
- SkAutoGlyphCache* lazyCache)
+ GrDeferredUploadTarget* uploadTarget, GrGlyphCache* glyphCache,
+ GrAtlasManager* fullAtlasManager, SkAutoGlyphCache* lazyCache)
: fResourceProvider(resourceProvider)
, fViewMatrix(viewMatrix)
, fBlob(blob)
, fUploadTarget(uploadTarget)
, fGlyphCache(glyphCache)
+ , fFullAtlasManager(fullAtlasManager)
, fLazyCache(lazyCache)
, fRun(&blob->fRuns[runIdx])
, fSubRun(&blob->fRuns[runIdx].fSubRunInfo[subRunIdx])
@@ -207,7 +209,7 @@ Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasText
// Compute translation if any
fSubRun->computeTranslation(fViewMatrix, x, y, &fTransX, &fTransY);
- // Because the GrAtlasGlyphCache may evict the strike a blob depends on using for
+ // Because the GrGlyphCache may evict the strike a blob depends on using for
// generating its texture coords, we have to track whether or not the strike has
// been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is
// otherwise we have to get the new strike, and use that to get the correct glyphs.
@@ -275,16 +277,17 @@ Regenerator::Result Regenerator::doRegen() {
glyph = fBlob->fGlyphs[glyphOffset];
SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat());
- if (!fGlyphCache->hasGlyph(glyph) &&
- !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph,
+ if (!fFullAtlasManager->hasGlyph(glyph) &&
+ !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache,
+ fFullAtlasManager, glyph,
fLazyCache->get(), fSubRun->maskFormat())) {
fBrokenRun = glyphIdx > 0;
result.fFinished = false;
return result;
}
auto tokenTracker = fUploadTarget->tokenTracker();
- fGlyphCache->addGlyphToBulkAndSetUseToken(fSubRun->bulkUseToken(), glyph,
- tokenTracker->nextDrawToken());
+ fFullAtlasManager->addGlyphToBulkAndSetUseToken(fSubRun->bulkUseToken(), glyph,
+ tokenTracker->nextDrawToken());
}
regen_vertices<regenPos, regenCol, regenTexCoords>(currVertex, glyph, vertexStride,
@@ -302,14 +305,14 @@ Regenerator::Result Regenerator::doRegen() {
fSubRun->setStrike(strike);
}
fSubRun->setAtlasGeneration(fBrokenRun
- ? GrDrawOpAtlas::kInvalidAtlasGeneration
- : fGlyphCache->atlasGeneration(fSubRun->maskFormat()));
+ ? GrDrawOpAtlas::kInvalidAtlasGeneration
+ : fFullAtlasManager->atlasGeneration(fSubRun->maskFormat()));
}
return result;
}
Regenerator::Result Regenerator::regenerate() {
- uint64_t currentAtlasGen = fGlyphCache->atlasGeneration(fSubRun->maskFormat());
+ uint64_t currentAtlasGen = fFullAtlasManager->atlasGeneration(fSubRun->maskFormat());
// If regenerate() is called multiple times then the atlas gen may have changed. So we check
// this each time.
if (fSubRun->atlasGeneration() != currentAtlasGen) {
@@ -352,9 +355,9 @@ Regenerator::Result Regenerator::regenerate() {
// set use tokens for all of the glyphs in our subrun. This is only valid if we
// have a valid atlas generation
- fGlyphCache->setUseTokenBulk(*fSubRun->bulkUseToken(),
- fUploadTarget->tokenTracker()->nextDrawToken(),
- fSubRun->maskFormat());
+ fFullAtlasManager->setUseTokenBulk(*fSubRun->bulkUseToken(),
+ fUploadTarget->tokenTracker()->nextDrawToken(),
+ fSubRun->maskFormat());
return result;
}
}
diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp
index 06282e103e..aadc2dc0c1 100644
--- a/src/gpu/text/GrAtlasTextContext.cpp
+++ b/src/gpu/text/GrAtlasTextContext.cpp
@@ -118,7 +118,8 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t
drawFilter);
SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo());
- auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache();
+ auto glyphCache = context->contextPriv().getGlyphCache();
+ auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager();
GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache();
if (canCache) {
@@ -151,7 +152,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t
// but we'd have to clear the subrun information
textBlobCache->remove(cacheBlob.get());
cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint);
- this->regenerateTextBlob(cacheBlob.get(), atlasGlyphCache,
+ this->regenerateTextBlob(cacheBlob.get(), glyphCache,
*context->caps()->shaderCaps(), paint, scalerContextFlags,
viewMatrix, props, blob, x, y, drawFilter);
} else {
@@ -163,7 +164,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t
GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
sk_sp<GrAtlasTextBlob> sanityBlob(textBlobCache->makeBlob(glyphCount, runCount));
sanityBlob->setupKey(key, blurRec, skPaint);
- this->regenerateTextBlob(sanityBlob.get(), atlasGlyphCache,
+ this->regenerateTextBlob(sanityBlob.get(), glyphCache,
*context->caps()->shaderCaps(), paint, scalerContextFlags,
viewMatrix, props, blob, x, y, drawFilter);
GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
@@ -175,17 +176,17 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t
} else {
cacheBlob = textBlobCache->makeBlob(blob);
}
- this->regenerateTextBlob(cacheBlob.get(), atlasGlyphCache,
+ this->regenerateTextBlob(cacheBlob.get(), glyphCache,
*context->caps()->shaderCaps(), paint, scalerContextFlags,
viewMatrix, props, blob, x, y, drawFilter);
}
- cacheBlob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint,
+ cacheBlob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint,
clip, viewMatrix, clipBounds, x, y);
}
void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
- GrAtlasGlyphCache* fontCache,
+ GrGlyphCache* glyphCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
@@ -211,21 +212,21 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
if (this->canDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) {
switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning: {
- this->drawDFText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags,
+ this->drawDFText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(),
y + offset.y());
break;
}
case SkTextBlob::kHorizontal_Positioning: {
SkPoint dfOffset = SkPoint::Make(x, y + offset.y());
- this->drawDFPosText(cacheBlob, run, fontCache, props, runPaint,
+ this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
textLen, it.pos(), 1, dfOffset);
break;
}
case SkTextBlob::kFull_Positioning: {
SkPoint dfOffset = SkPoint::Make(x, y);
- this->drawDFPosText(cacheBlob, run, fontCache, props, runPaint,
+ this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint,
scalerContextFlags, viewMatrix, (const char*)it.glyphs(),
textLen, it.pos(), 2, dfOffset);
break;
@@ -234,17 +235,17 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
} else {
switch (it.positioning()) {
case SkTextBlob::kDefault_Positioning:
- DrawBmpText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags,
+ DrawBmpText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(),
y + offset.y());
break;
case SkTextBlob::kHorizontal_Positioning:
- DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags,
+ DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1,
SkPoint::Make(x, y + offset.y()));
break;
case SkTextBlob::kFull_Positioning:
- DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags,
+ DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags,
viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2,
SkPoint::Make(x, y));
break;
@@ -255,7 +256,7 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob,
inline sk_sp<GrAtlasTextBlob>
GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache,
- GrAtlasGlyphCache* fontCache,
+ GrGlyphCache* glyphCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
@@ -272,10 +273,10 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache,
blob->setRunPaintFlags(0, paint.skPaint().getFlags());
if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) {
- this->drawDFText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix,
+ this->drawDFText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix,
text, byteLength, x, y);
} else {
- DrawBmpText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text,
+ DrawBmpText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text,
byteLength, x, y);
}
return blob;
@@ -283,7 +284,7 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache,
inline sk_sp<GrAtlasTextBlob>
GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
- GrAtlasGlyphCache* fontCache,
+ GrGlyphCache* glyphCache,
const GrShaderCaps& shaderCaps,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
@@ -302,11 +303,11 @@ GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache,
blob->setRunPaintFlags(0, paint.skPaint().getFlags());
if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) {
- this->drawDFPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix,
+ this->drawDFPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix,
text, byteLength, pos, scalarsPerPosition, offset);
} else {
- DrawBmpPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text,
- byteLength, pos, scalarsPerPosition, offset);
+ DrawBmpPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix,
+ text, byteLength, pos, scalarsPerPosition, offset);
}
return blob;
}
@@ -320,17 +321,18 @@ void GrAtlasTextContext::drawText(GrContext* context, GrTextUtils::Target* targe
return;
}
- auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache();
+ auto glyphCache = context->contextPriv().getGlyphCache();
+ auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager();
auto textBlobCache = context->contextPriv().getTextBlobCache();
GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo());
sk_sp<GrAtlasTextBlob> blob(
- this->makeDrawTextBlob(textBlobCache, atlasGlyphCache,
+ this->makeDrawTextBlob(textBlobCache, glyphCache,
*context->caps()->shaderCaps(), paint,
ComputeScalerContextFlags(target->colorSpaceInfo()),
viewMatrix, props, text, byteLength, x, y));
if (blob) {
- blob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint,
+ blob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint,
clip, viewMatrix, regionClipBounds, x, y);
}
}
@@ -346,22 +348,23 @@ void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* ta
return;
}
- auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache();
+ auto glyphCache = context->contextPriv().getGlyphCache();
+ auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager();
auto textBlobCache = context->contextPriv().getTextBlobCache();
sk_sp<GrAtlasTextBlob> blob(this->makeDrawPosTextBlob(
- textBlobCache, atlasGlyphCache,
+ textBlobCache, glyphCache,
*context->caps()->shaderCaps(), paint,
ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text,
byteLength, pos, scalarsPerPosition, offset));
if (blob) {
- blob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint,
+ blob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint,
clip, viewMatrix, regionClipBounds, offset.fX, offset.fY);
}
}
void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
+ GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
@@ -377,7 +380,7 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
blob->setHasBitmap();
if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) {
- DrawBmpTextAsPaths(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix,
+ DrawBmpTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix,
text, byteLength, x, y);
return;
}
@@ -387,7 +390,7 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
viewMatrix, paint.skPaint().getTextAlign(), cache,
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
position += rounding;
- BmpAppendGlyph(blob, runIndex, fontCache, &currStrike,
+ BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike,
glyph, SkScalarFloorToScalar(position.fX),
SkScalarFloorToScalar(position.fY),
paint.filteredPremulColor(), cache,
@@ -398,7 +401,7 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex,
}
void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
+ GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
@@ -416,7 +419,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
blob->setHasBitmap();
if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) {
- DrawBmpPosTextAsPaths(blob, runIndex, fontCache, props, paint, scalerContextFlags,
+ DrawBmpPosTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags,
viewMatrix, text, byteLength, pos, scalarsPerPosition, offset);
return;
}
@@ -429,7 +432,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
scalarsPerPosition, paint.skPaint().getTextAlign(), cache,
[&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
position += rounding;
- BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph,
+ BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph,
SkScalarFloorToScalar(position.fX),
SkScalarFloorToScalar(position.fY),
paint.filteredPremulColor(), cache, SK_Scalar1);
@@ -439,7 +442,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex,
}
void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache,
+ GrGlyphCache* glyphCache,
const SkSurfaceProps& props,
const GrTextUtils::Paint& origPaint,
SkScalerContextFlags scalerContextFlags,
@@ -457,7 +460,7 @@ void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
GrTextUtils::PathTextIter iter(text, byteLength, pathPaint, true);
FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint.getTextSize(),
- fontCache->getGlyphSizeLimit(),
+ glyphCache->getGlyphSizeLimit(),
iter.getPathScale());
const SkGlyph* iterGlyph;
@@ -474,11 +477,11 @@ void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
lastText = iter.getText();
}
- fallbackTextHelper.drawText(blob, runIndex, fontCache, props, origPaint, scalerContextFlags);
+ fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags);
}
void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache,
+ GrGlyphCache* glyphCache,
const SkSurfaceProps& props,
const GrTextUtils::Paint& origPaint,
SkScalerContextFlags scalerContextFlags,
@@ -497,7 +500,7 @@ void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runInd
SkPaint pathPaint(origPaint);
SkScalar matrixScale = pathPaint.setupForAsPaths();
FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint.getTextSize(), matrixScale,
- fontCache->getGlyphSizeLimit());
+ glyphCache->getGlyphSizeLimit());
// Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
pathPaint.setStyle(SkPaint::kFill_Style);
@@ -534,23 +537,23 @@ void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runInd
pos += scalarsPerPosition;
}
- fallbackTextHelper.drawText(blob, runIndex, fontCache, props, origPaint, scalerContextFlags);
+ fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags);
}
void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache, GrAtlasTextStrike** strike,
+ GrGlyphCache* grGlyphCache, GrAtlasTextStrike** strike,
const SkGlyph& skGlyph, SkScalar sx, SkScalar sy,
- GrColor color, SkGlyphCache* glyphCache,
+ GrColor color, SkGlyphCache* skGlyphCache,
SkScalar textRatio) {
if (!*strike) {
- *strike = fontCache->getStrike(glyphCache);
+ *strike = grGlyphCache->getStrike(skGlyphCache);
}
GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(),
skGlyph.getSubXFixed(),
skGlyph.getSubYFixed(),
GrGlyph::kCoverage_MaskStyle);
- GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache);
+ GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, skGlyphCache);
if (!glyph) {
return;
}
@@ -570,7 +573,7 @@ void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height);
- blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, sx, sy,
+ blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy,
textRatio, true);
}
@@ -670,7 +673,7 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob,
}
void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
+ GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
@@ -740,12 +743,12 @@ void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex,
y -= alignY;
SkPoint offset = SkPoint::Make(x, y);
- this->drawDFPosText(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix,
+ this->drawDFPosText(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix,
text, byteLength, positions.begin(), 2, offset);
}
void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
+ GrGlyphCache* glyphCache, const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
@@ -771,7 +774,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
FallbackTextHelper fallbackTextHelper(viewMatrix,
paint.skPaint().getTextSize(),
- fontCache->getGlyphSizeLimit(),
+ glyphCache->getGlyphSizeLimit(),
textRatio);
GrAtlasTextStrike* currStrike = nullptr;
@@ -800,7 +803,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio;
if (glyph.fMaskFormat != SkMask::kARGB32_Format) {
- DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, glyphPos.fX,
+ DfAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, glyphPos.fX,
glyphPos.fY, paint.filteredPremulColor(), cache, textRatio);
} else {
// can't append color glyph to SDF batch, send to fallback
@@ -812,25 +815,24 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex,
SkGlyphCache::AttachCache(cache);
- fallbackTextHelper.drawText(blob, runIndex, fontCache, props, paint,
- scalerContextFlags);
+ fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, paint, scalerContextFlags);
}
// TODO: merge with BmpAppendGlyph
void GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* cache, GrAtlasTextStrike** strike,
+ GrGlyphCache* grGlyphCache, GrAtlasTextStrike** strike,
const SkGlyph& skGlyph, SkScalar sx, SkScalar sy,
- GrColor color, SkGlyphCache* glyphCache,
+ GrColor color, SkGlyphCache* skGlyphCache,
SkScalar textRatio) {
if (!*strike) {
- *strike = cache->getStrike(glyphCache);
+ *strike = grGlyphCache->getStrike(skGlyphCache);
}
GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(),
skGlyph.getSubXFixed(),
skGlyph.getSubYFixed(),
GrGlyph::kDistance_MaskStyle);
- GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache);
+ GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, skGlyphCache);
if (!glyph) {
return;
}
@@ -846,7 +848,7 @@ void GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex,
height *= textRatio;
SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height);
- blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, sx, sy,
+ blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy,
textRatio, false);
}
@@ -871,7 +873,7 @@ void GrAtlasTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, in
}
void GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache,
+ GrGlyphCache* glyphCache,
const SkSurfaceProps& props,
const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags) {
@@ -909,7 +911,7 @@ void GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int
SkPoint* glyphPos = fFallbackPos.begin();
while (text < stop) {
const SkGlyph& glyph = glyphCacheProc(cache, &text);
- GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph,
+ GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph,
glyphPos->fX, glyphPos->fY, textColor,
cache, textRatio);
glyphPos++;
@@ -962,18 +964,19 @@ GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) {
SkScalar x = SkIntToScalar(xInt);
SkScalar y = SkIntToScalar(yInt);
- auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache();
+ auto glyphCache = context->contextPriv().getGlyphCache();
+ auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager();
// right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to
// test the text op with this unit test, that is okay.
sk_sp<GrAtlasTextBlob> blob(gTextContext->makeDrawTextBlob(
- context->contextPriv().getTextBlobCache(), atlasGlyphCache,
+ context->contextPriv().getTextBlobCache(), glyphCache,
*context->caps()->shaderCaps(), utilsPaint,
GrAtlasTextContext::kTextBlobOpScalerContextFlags, viewMatrix, gSurfaceProps, text,
static_cast<size_t>(textLen), x, y));
return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, gSurfaceProps,
- gTextContext->dfAdjustTable(), atlasGlyphCache,
+ gTextContext->dfAdjustTable(), restrictedAtlasManager,
rtc->textTarget());
}
diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h
index 207dd67206..37b7de5357 100644
--- a/src/gpu/text/GrAtlasTextContext.h
+++ b/src/gpu/text/GrAtlasTextContext.h
@@ -74,9 +74,8 @@ private:
}
void appendText(const SkGlyph& glyph, int count, const char* text, SkPoint glyphPos);
- void drawText(GrAtlasTextBlob* blob, int runIndex,
- GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props,
- const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags);
+ void drawText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&,
+ const GrTextUtils::Paint&, SkScalerContextFlags);
private:
SkTDArray<char> fFallbackTxt;
@@ -96,7 +95,7 @@ private:
// Determines if we need to use fake gamma (and contrast boost):
static SkScalerContextFlags ComputeScalerContextFlags(const GrColorSpaceInfo&);
void regenerateTextBlob(GrAtlasTextBlob* bmp,
- GrAtlasGlyphCache*,
+ GrGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
SkScalerContextFlags scalerContextFlags,
@@ -107,7 +106,7 @@ private:
static bool HasLCD(const SkTextBlob*);
- sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*,
+ sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
SkScalerContextFlags scalerContextFlags,
@@ -116,7 +115,7 @@ private:
const char text[], size_t byteLength,
SkScalar x, SkScalar y) const;
- sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*,
+ sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*,
const GrShaderCaps&,
const GrTextUtils::Paint&,
SkScalerContextFlags scalerContextFlags,
@@ -128,24 +127,24 @@ private:
const SkPoint& offset) const;
// Functions for appending BMP text to GrAtlasTextBlob
- static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
const char text[], size_t byteLength, SkScalar x, SkScalar y);
- static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix,
const char text[], size_t byteLength, const SkScalar pos[],
int scalarsPerPosition, const SkPoint& offset);
- static void DrawBmpTextAsPaths(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ static void DrawBmpTextAsPaths(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
size_t byteLength, SkScalar x, SkScalar y);
- static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix,
@@ -157,12 +156,12 @@ private:
bool canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix,
const SkSurfaceProps& props, const GrShaderCaps& caps) const;
- void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&,
+ void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&,
const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x,
SkScalar y) const;
- void drawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*,
+ void drawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*,
const SkSurfaceProps&, const GrTextUtils::Paint& paint,
SkScalerContextFlags scalerContextFlags,
const SkMatrix& viewMatrix, const char text[],
@@ -174,11 +173,11 @@ private:
SkScalar* textRatio,
const SkMatrix& viewMatrix) const;
- static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
GrAtlasTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy,
GrColor color, SkGlyphCache*, SkScalar textRatio);
- static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*,
+ static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*,
GrAtlasTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy,
GrColor color, SkGlyphCache* cache, SkScalar textRatio);
diff --git a/src/gpu/text/GrAtlasGlyphCache.cpp b/src/gpu/text/GrGlyphCache.cpp
index f7b1e1269a..d4440897bc 100644
--- a/src/gpu/text/GrAtlasGlyphCache.cpp
+++ b/src/gpu/text/GrGlyphCache.cpp
@@ -5,81 +5,19 @@
* found in the LICENSE file.
*/
-#include "GrAtlasGlyphCache.h"
-#include "GrContext.h"
+#include "GrAtlasManager.h"
#include "GrDistanceFieldGenFromVector.h"
-#include "GrGpu.h"
-#include "GrProxyProvider.h"
-#include "GrRectanizer.h"
+#include "GrGlyphCache.h"
#include "SkAutoMalloc.h"
#include "SkDistanceFieldGen.h"
-#include "SkMathPriv.h"
-#include "SkString.h"
-
-bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
- int index = MaskFormatToAtlasIndex(format);
- if (!fAtlases[index]) {
- GrPixelConfig config = MaskFormatToPixelConfig(format, *fProxyProvider->caps());
- int width = fAtlasConfigs[index].fWidth;
- int height = fAtlasConfigs[index].fHeight;
- int numPlotsX = fAtlasConfigs[index].numPlotsX();
- int numPlotsY = fAtlasConfigs[index].numPlotsY();
-
- fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height,
- numPlotsX, numPlotsY, fAllowMultitexturing,
- &GrAtlasGlyphCache::HandleEviction, (void*)this);
- if (!fAtlases[index]) {
- return false;
- }
- }
- return true;
-}
-GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes,
- GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
- : fProxyProvider(proxyProvider)
- , fAllowMultitexturing(allowMultitexturing)
- , fPreserveStrike(nullptr) {
- // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
- int log2MaxTextureSize = SkPrevLog2(fProxyProvider->caps()->maxTextureSize());
- int log2MaxDim = 9;
- for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
- int maxDim = 1 << log2MaxDim;
- int minDim = 1 << (log2MaxDim - 1);
-
- if (maxDim * minDim * 4 >= maxTextureBytes) break;
- }
-
- int log2MinDim = log2MaxDim - 1;
- int maxDim = 1 << log2MaxDim;
- int minDim = 1 << log2MinDim;
- // Plots are either 256 or 512.
- int maxPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 2)));
- int minPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 3)));
-
- // Setup default atlas configs. The A8 atlas uses maxDim for both width and height, as the A8
- // format is already very compact.
- fAtlasConfigs[kA8_GrMaskFormat].fWidth = maxDim;
- fAtlasConfigs[kA8_GrMaskFormat].fHeight = maxDim;
- fAtlasConfigs[kA8_GrMaskFormat].fPlotWidth = maxPlot;
- fAtlasConfigs[kA8_GrMaskFormat].fPlotHeight = minPlot;
-
- // A565 and ARGB use maxDim x minDim.
- fAtlasConfigs[kA565_GrMaskFormat].fWidth = minDim;
- fAtlasConfigs[kA565_GrMaskFormat].fHeight = maxDim;
- fAtlasConfigs[kA565_GrMaskFormat].fPlotWidth = minPlot;
- fAtlasConfigs[kA565_GrMaskFormat].fPlotHeight = minPlot;
-
- fAtlasConfigs[kARGB_GrMaskFormat].fWidth = minDim;
- fAtlasConfigs[kARGB_GrMaskFormat].fHeight = maxDim;
- fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = minPlot;
- fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = minPlot;
-
- fGlyphSizeLimit = minPlot;
+GrGlyphCache::GrGlyphCache()
+ : fPreserveStrike(nullptr)
+ , fGlyphSizeLimit(0) {
}
-GrAtlasGlyphCache::~GrAtlasGlyphCache() {
+GrGlyphCache::~GrGlyphCache() {
StrikeHash::Iter iter(&fCache);
while (!iter.done()) {
(*iter).fIsAbandoned = true;
@@ -88,7 +26,7 @@ GrAtlasGlyphCache::~GrAtlasGlyphCache() {
}
}
-void GrAtlasGlyphCache::freeAll() {
+void GrGlyphCache::freeAll() {
StrikeHash::Iter iter(&fCache);
while (!iter.done()) {
(*iter).fIsAbandoned = true;
@@ -96,120 +34,26 @@ void GrAtlasGlyphCache::freeAll() {
++iter;
}
fCache.rewind();
- for (int i = 0; i < kMaskFormatCount; ++i) {
- fAtlases[i] = nullptr;
- }
}
-void GrAtlasGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {
- GrAtlasGlyphCache* fontCache = reinterpret_cast<GrAtlasGlyphCache*>(ptr);
+void GrGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {
+ GrGlyphCache* glyphCache = reinterpret_cast<GrGlyphCache*>(ptr);
- StrikeHash::Iter iter(&fontCache->fCache);
+ StrikeHash::Iter iter(&glyphCache->fCache);
for (; !iter.done(); ++iter) {
GrAtlasTextStrike* strike = &*iter;
strike->removeID(id);
// clear out any empty strikes. We will preserve the strike whose call to addToAtlas
// triggered the eviction
- if (strike != fontCache->fPreserveStrike && 0 == strike->fAtlasedGlyphs) {
- fontCache->fCache.remove(GrAtlasTextStrike::GetKey(*strike));
+ if (strike != glyphCache->fPreserveStrike && 0 == strike->fAtlasedGlyphs) {
+ glyphCache->fCache.remove(GrAtlasTextStrike::GetKey(*strike));
strike->fIsAbandoned = true;
strike->unref();
}
}
}
-#ifdef SK_DEBUG
-#include "GrContextPriv.h"
-#include "GrSurfaceProxy.h"
-#include "GrSurfaceContext.h"
-#include "GrTextureProxy.h"
-
-#include "SkBitmap.h"
-#include "SkImageEncoder.h"
-#include "SkStream.h"
-#include <stdio.h>
-
-/**
- * Write the contents of the surface proxy to a PNG. Returns true if successful.
- * @param filename Full path to desired file
- */
-static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) {
- if (!sProxy) {
- return false;
- }
-
- SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(),
- kRGBA_8888_SkColorType, kPremul_SkAlphaType);
- SkBitmap bm;
- if (!bm.tryAllocPixels(ii)) {
- return false;
- }
-
- sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext(
- sk_ref_sp(sProxy)));
- if (!sContext || !sContext->asTextureProxy()) {
- return false;
- }
-
- bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0);
- if (!result) {
- SkDebugf("------ failed to read pixels for %s\n", filename);
- return false;
- }
-
- // remove any previous version of this file
- remove(filename);
-
- SkFILEWStream file(filename);
- if (!file.isValid()) {
- SkDebugf("------ failed to create file: %s\n", filename);
- remove(filename); // remove any partial file
- return false;
- }
-
- if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) {
- SkDebugf("------ failed to encode %s\n", filename);
- remove(filename); // remove any partial file
- return false;
- }
-
- return true;
-}
-
-void GrAtlasGlyphCache::dump(GrContext* context) const {
- static int gDumpCount = 0;
- for (int i = 0; i < kMaskFormatCount; ++i) {
- if (fAtlases[i]) {
- const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies();
- for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
- SkASSERT(proxies[pageIdx]);
- SkString filename;
-#ifdef SK_BUILD_FOR_ANDROID
- filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
-#else
- filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
-#endif
-
- save_pixels(context, proxies[pageIdx].get(), filename.c_str());
- }
- }
- }
- ++gDumpCount;
-}
-#endif
-
-void GrAtlasGlyphCache::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) {
- // Delete any old atlases.
- // This should be safe to do as long as we are not in the middle of a flush.
- for (int i = 0; i < kMaskFormatCount; i++) {
- fAtlases[i] = nullptr;
- }
- memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs));
-}
-
-///////////////////////////////////////////////////////////////////////////////
-
static inline GrMaskFormat get_packed_glyph_mask_format(const SkGlyph& glyph) {
SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat);
switch (format) {
@@ -450,7 +294,8 @@ void GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) {
bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
GrDeferredUploadTarget* target,
- GrAtlasGlyphCache* atlasGlyphCache,
+ GrGlyphCache* glyphCache,
+ GrAtlasManager* fullAtlasManager,
GrGlyph* glyph,
SkGlyphCache* cache,
GrMaskFormat expectedMaskFormat) {
@@ -477,10 +322,10 @@ bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
}
}
- bool success = atlasGlyphCache->addToAtlas(resourceProvider, this, &glyph->fID, target,
- expectedMaskFormat,
- glyph->width(), glyph->height(),
- storage.get(), &glyph->fAtlasLocation);
+ bool success = fullAtlasManager->addToAtlas(resourceProvider, glyphCache, this,
+ &glyph->fID, target, expectedMaskFormat,
+ glyph->width(), glyph->height(),
+ storage.get(), &glyph->fAtlasLocation);
if (success) {
SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID);
fAtlasedGlyphs++;
diff --git a/src/gpu/text/GrGlyphCache.h b/src/gpu/text/GrGlyphCache.h
new file mode 100644
index 0000000000..169e4b30a5
--- /dev/null
+++ b/src/gpu/text/GrGlyphCache.h
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrAtlasGlyphCache_DEFINED
+#define GrAtlasGlyphCache_DEFINED
+
+#include "GrDrawOpAtlas.h"
+#include "GrGlyph.h"
+#include "SkArenaAlloc.h"
+#include "SkGlyphCache.h"
+#include "SkTDynamicHash.h"
+
+class GrGlyphCache;
+class GrAtlasManager;
+class GrGpu;
+
+/**
+ * The GrAtlasTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory
+ * is indexed by a PackedID and SkGlyphCache. The SkGlyphCache is what actually creates the mask.
+ * The GrAtlasTextStrike may outlive the generating SkGlyphCache. However, it retains a copy
+ * of it's SkDescriptor as a key to access (or regenerate) the SkGlyphCache. GrAtlasTextStrike are
+ * created by and owned by a GrGlyphCache.
+ */
+class GrAtlasTextStrike : public SkNVRefCnt<GrAtlasTextStrike> {
+public:
+ GrAtlasTextStrike(const SkDescriptor& fontScalerKey);
+ ~GrAtlasTextStrike();
+
+ inline GrGlyph* getGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed,
+ SkGlyphCache* cache) {
+ GrGlyph* glyph = fCache.find(packed);
+ if (nullptr == glyph) {
+ glyph = this->generateGlyph(skGlyph, packed, cache);
+ }
+ return glyph;
+ }
+
+ // This variant of the above function is called by GrAtlasTextOp. At this point, it is possible
+ // that the maskformat of the glyph differs from what we expect. In these cases we will just
+ // draw a clear square.
+ // skbug:4143 crbug:510931
+ inline GrGlyph* getGlyph(GrGlyph::PackedID packed,
+ GrMaskFormat expectedMaskFormat,
+ SkGlyphCache* cache) {
+ GrGlyph* glyph = fCache.find(packed);
+ if (nullptr == glyph) {
+ // We could return this to the caller, but in practice it adds code complexity for
+ // potentially little benefit(ie, if the glyph is not in our font cache, then its not
+ // in the atlas and we're going to be doing a texture upload anyways).
+ const SkGlyph& skGlyph = GrToSkGlyph(cache, packed);
+ glyph = this->generateGlyph(skGlyph, packed, cache);
+ glyph->fMaskFormat = expectedMaskFormat;
+ }
+ return glyph;
+ }
+
+ // returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's
+ // mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never
+ // happen.
+ // TODO we can handle some of these cases if we really want to, but the long term solution is to
+ // get the actual glyph image itself when we get the glyph metrics.
+ bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrGlyphCache*,
+ GrAtlasManager*, GrGlyph*,
+ SkGlyphCache*, GrMaskFormat expectedMaskFormat);
+
+ // testing
+ int countGlyphs() const { return fCache.count(); }
+
+ // remove any references to this plot
+ void removeID(GrDrawOpAtlas::AtlasID);
+
+ // If a TextStrike is abandoned by the cache, then the caller must get a new strike
+ bool isAbandoned() const { return fIsAbandoned; }
+
+ static const SkDescriptor& GetKey(const GrAtlasTextStrike& ts) {
+ return *ts.fFontScalerKey.getDesc();
+ }
+
+ static uint32_t Hash(const SkDescriptor& desc) { return desc.getChecksum(); }
+
+private:
+ SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache;
+ SkAutoDescriptor fFontScalerKey;
+ SkArenaAlloc fPool{512};
+
+ int fAtlasedGlyphs;
+ bool fIsAbandoned;
+
+ static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, GrGlyph::PackedID id) {
+ return cache->getGlyphIDMetrics(GrGlyph::UnpackID(id),
+ GrGlyph::UnpackFixedX(id),
+ GrGlyph::UnpackFixedY(id));
+ }
+
+ GrGlyph* generateGlyph(const SkGlyph&, GrGlyph::PackedID, SkGlyphCache*);
+
+ friend class GrGlyphCache;
+};
+
+/**
+ * GrGlyphCache manages strikes which are indexed by a SkGlyphCache. These strikes can then be
+ * used to generate individual Glyph Masks.
+ */
+class GrGlyphCache {
+public:
+ GrGlyphCache();
+ ~GrGlyphCache();
+
+ void setGlyphSizeLimit(SkScalar sizeLimit) { fGlyphSizeLimit = sizeLimit; }
+ SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
+
+ void setStrikeToPreserve(GrAtlasTextStrike* strike) { fPreserveStrike = strike; }
+
+ // The user of the cache may hold a long-lived ref to the returned strike. However, actions by
+ // another client of the cache may cause the strike to be purged while it is still reffed.
+ // Therefore, the caller must check GrAtlasTextStrike::isAbandoned() if there are other
+ // interactions with the cache since the strike was received.
+ inline GrAtlasTextStrike* getStrike(const SkGlyphCache* cache) {
+ GrAtlasTextStrike* strike = fCache.find(cache->getDescriptor());
+ if (nullptr == strike) {
+ strike = this->generateStrike(cache);
+ }
+ return strike;
+ }
+
+ void freeAll();
+
+ static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
+
+private:
+ GrAtlasTextStrike* generateStrike(const SkGlyphCache* cache) {
+ GrAtlasTextStrike* strike = new GrAtlasTextStrike(cache->getDescriptor());
+ fCache.add(strike);
+ return strike;
+ }
+
+ using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
+
+ StrikeHash fCache;
+ GrAtlasTextStrike* fPreserveStrike;
+ SkScalar fGlyphSizeLimit;
+};
+
+#endif
diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h
index 5fe38fe773..69421c2474 100644
--- a/src/gpu/text/GrTextUtils.h
+++ b/src/gpu/text/GrTextUtils.h
@@ -16,13 +16,13 @@
#include "SkTextToPathIter.h"
#include "SkTLazy.h"
-class GrAtlasGlyphCache;
class GrAtlasTextBlob;
class GrAtlasTextOp;
class GrAtlasTextStrike;
class GrClip;
class GrColorSpaceXform;
class GrContext;
+class GrGlyphCache;
class GrPaint;
class GrShaderCaps;
class SkColorSpace;