Modify fontcache GM to actually spill atlas.
Adds an option to GrDrawOpAtlas to disable multitexturing.
Adds option to GrContextOptions to disable multitexturing for glyph atlases.
Change-Id: If413ab7061538fa0e75628d252be4fd14215b6ba
Reviewed-on: https://skia-review.googlesource.com/67802
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 2146858..d3194be 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -204,7 +204,14 @@
}
fDrawingManager.reset(new GrDrawingManager(this, prcOptions, &fSingleOwner));
- fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes);
+ GrDrawOpAtlas::AllowMultitexturing allowMultitexturing;
+ if (options.fAllowMultipleGlyphCacheTextures == GrContextOptions::Enable::kNo) {
+ allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kNo;
+ } else {
+ allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
+ }
+ fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes,
+ allowMultitexturing);
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);
fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this));
diff --git a/src/gpu/GrDrawOpAtlas.cpp b/src/gpu/GrDrawOpAtlas.cpp
index 8d81285..c0358b7 100644
--- a/src/gpu/GrDrawOpAtlas.cpp
+++ b/src/gpu/GrDrawOpAtlas.cpp
@@ -14,13 +14,12 @@
#include "GrTexture.h"
#include "GrTracing.h"
-std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config,
- int width, int height,
- int numPlotsX, int numPlotsY,
- GrDrawOpAtlas::EvictionFunc func,
- void* data) {
- std::unique_ptr<GrDrawOpAtlas> atlas(
- new GrDrawOpAtlas(ctx, config, width, height, numPlotsX, numPlotsY));
+std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config, int width,
+ int height, int numPlotsX, int numPlotsY,
+ AllowMultitexturing allowMultitexturing,
+ GrDrawOpAtlas::EvictionFunc func, void* data) {
+ std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(ctx, config, width, height, numPlotsX,
+ numPlotsY, allowMultitexturing));
if (!atlas->getProxies()[0]) {
return nullptr;
}
@@ -147,13 +146,14 @@
///////////////////////////////////////////////////////////////////////////////
GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width, int height,
- int numPlotsX, int numPlotsY)
+ int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing)
: fContext(context)
, fPixelConfig(config)
, fTextureWidth(width)
, fTextureHeight(height)
, fAtlasGeneration(kInvalidAtlasGeneration + 1)
, fPrevFlushToken(GrDeferredUploadToken::AlreadyFlushedToken())
+ , fAllowMultitexturing(allowMultitexturing)
, fNumPages(0) {
fPlotWidth = fTextureWidth / numPlotsX;
fPlotHeight = fTextureHeight / numPlotsY;
@@ -242,7 +242,7 @@
for (unsigned int pageIdx = 0; pageIdx < fNumPages; ++pageIdx) {
Plot* plot = fPages[pageIdx].fPlotList.tail();
SkASSERT(plot);
- if ((fNumPages == kMaxPages && plot->lastUseToken() < target->nextTokenToFlush()) ||
+ if ((fNumPages == this->maxPages() && plot->lastUseToken() < target->nextTokenToFlush()) ||
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
this->processEvictionAndResetRects(plot);
SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp());
@@ -448,7 +448,7 @@
}
bool GrDrawOpAtlas::createNewPage() {
- if (fNumPages == kMaxPages) {
+ if (fNumPages == this->maxPages()) {
return false;
}
diff --git a/src/gpu/GrDrawOpAtlas.h b/src/gpu/GrDrawOpAtlas.h
index 91a88ec..edab2cb 100644
--- a/src/gpu/GrDrawOpAtlas.h
+++ b/src/gpu/GrDrawOpAtlas.h
@@ -51,7 +51,13 @@
* and passes in the given GrDrawUploadToken.
*/
class GrDrawOpAtlas {
+private:
+ static constexpr auto kMaxMultitexturePages = 4;
+
public:
+ /** Is the atlas allowed to use more than one texture? */
+ enum class AllowMultitexturing : bool { kNo, kYes };
+
/**
* An AtlasID is an opaque handle which callers can use to determine if the atlas contains
* a specific piece of data.
@@ -77,15 +83,16 @@
* direction
* @param numPlotsY The number of plots the atlas should be broken up into in the Y
* direction
+ * @param allowMultitexturing Can the atlas use more than one texture.
* @param func An eviction function which will be called whenever the atlas has to
* evict data
- * @param data User supplied data which will be passed into func whenver an
+ * @param data User supplied data which will be passed into func whenever an
* eviction occurs
* @return An initialized GrDrawOpAtlas, or nullptr if creation fails
*/
- static std::unique_ptr<GrDrawOpAtlas> Make(GrContext*, GrPixelConfig,
- int width, int height,
+ static std::unique_ptr<GrDrawOpAtlas> Make(GrContext*, GrPixelConfig, int width, int height,
int numPlotsX, int numPlotsY,
+ AllowMultitexturing allowMultitexturing,
GrDrawOpAtlas::EvictionFunc func, void* data);
/**
@@ -134,7 +141,6 @@
data->fData = userData;
}
- static constexpr auto kMaxPages = 4;
uint32_t pageCount() { return fNumPages; }
/**
@@ -186,7 +192,7 @@
static constexpr int kMinItems = 4;
static constexpr int kMaxPlots = 32;
SkSTArray<kMinItems, PlotData, true> fPlotsToUpdate;
- uint32_t fPlotAlreadyUpdated[kMaxPages];
+ uint32_t fPlotAlreadyUpdated[kMaxMultitexturePages];
friend class GrDrawOpAtlas;
};
@@ -217,8 +223,12 @@
}
private:
- GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height,
- int numPlotsX, int numPlotsY);
+ uint32_t maxPages() const {
+ return AllowMultitexturing::kYes == fAllowMultitexturing ? kMaxMultitexturePages : 1;
+ }
+
+ GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height, int numPlotsX,
+ int numPlotsY, AllowMultitexturing allowMultitexturing);
/**
* The backing GrTexture for a GrDrawOpAtlas is broken into a spatial grid of Plots. The Plots
@@ -282,7 +292,7 @@
static GrDrawOpAtlas::AtlasID CreateId(uint32_t pageIdx, uint32_t plotIdx,
uint64_t generation) {
SkASSERT(pageIdx < (1 << 8));
- SkASSERT(pageIdx < kMaxPages);
+ SkASSERT(pageIdx < kMaxMultitexturePages);
SkASSERT(plotIdx < (1 << 8));
SkASSERT(generation < ((uint64_t)1 << 48));
return generation << 16 | plotIdx << 8 | pageIdx;
@@ -376,8 +386,9 @@
PlotList fPlotList;
};
// proxies kept separate to make it easier to pass them up to client
- sk_sp<GrTextureProxy> fProxies[kMaxPages];
- Page fPages[kMaxPages];
+ sk_sp<GrTextureProxy> fProxies[kMaxMultitexturePages];
+ Page fPages[kMaxMultitexturePages];
+ AllowMultitexturing fAllowMultitexturing;
uint32_t fNumPages;
};
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index d308498..4f4dcc1 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -181,10 +181,9 @@
fHelper.visitProxies(func);
const sk_sp<GrTextureProxy>* proxies = fAtlas->getProxies();
- for (int i = 0; i < GrDrawOpAtlas::kMaxPages; ++i) {
- if (proxies[i].get()) {
- func(proxies[i].get());
- }
+ for (uint32_t i = 0; i < fAtlas->pageCount(); ++i) {
+ SkASSERT(proxies[i]);
+ func(proxies[i].get());
}
}
@@ -793,6 +792,7 @@
kAlpha_8_GrPixelConfig,
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
NUM_PLOTS_X, NUM_PLOTS_Y,
+ GrDrawOpAtlas::AllowMultitexturing::kYes,
&GrSmallPathRenderer::HandleEviction,
(void*)this);
if (!fAtlas) {
@@ -861,6 +861,7 @@
gTestStruct.fAtlas = GrDrawOpAtlas::Make(context, kAlpha_8_GrPixelConfig,
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
NUM_PLOTS_X, NUM_PLOTS_Y,
+ GrDrawOpAtlas::AllowMultitexturing::kYes,
&PathTestStruct::HandleEviction,
(void*)&gTestStruct);
}
diff --git a/src/gpu/text/GrAtlasGlyphCache.cpp b/src/gpu/text/GrAtlasGlyphCache.cpp
index 25575be..80f4314 100644
--- a/src/gpu/text/GrAtlasGlyphCache.cpp
+++ b/src/gpu/text/GrAtlasGlyphCache.cpp
@@ -25,9 +25,9 @@
int numPlotsX = fAtlasConfigs[index].numPlotsX();
int numPlotsY = fAtlasConfigs[index].numPlotsY();
- fAtlases[index] = GrDrawOpAtlas::Make(
- fContext, config, width, height, numPlotsX, numPlotsY,
- &GrAtlasGlyphCache::HandleEviction, (void*)this);
+ fAtlases[index] = GrDrawOpAtlas::Make(fContext, config, width, height, numPlotsX, numPlotsY,
+ fAllowMultitexturing,
+ &GrAtlasGlyphCache::HandleEviction, (void*)this);
if (!fAtlases[index]) {
return false;
}
@@ -35,11 +35,12 @@
return true;
}
-GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes)
- : fContext(context), fPreserveStrike(nullptr) {
- // Calculate RGBA size. Must be between 1024 x 512 and MaxTextureSize x MaxTextureSize / 2
+GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes,
+ GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
+ : fContext(context), fAllowMultitexturing(allowMultitexturing), fPreserveStrike(nullptr) {
+ // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
int log2MaxTextureSize = SkPrevLog2(context->caps()->maxTextureSize());
- int log2MaxDim = 10;
+ int log2MaxDim = 9;
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
int maxDim = 1 << log2MaxDim;
int minDim = 1 << (log2MaxDim - 1);
@@ -177,17 +178,16 @@
for (int i = 0; i < kMaskFormatCount; ++i) {
if (fAtlases[i]) {
const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies();
- for (int pageIdx = 0; pageIdx < GrDrawOpAtlas::kMaxPages; ++pageIdx) {
- if (proxies[pageIdx]) {
- SkString filename;
+ for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->pageCount(); ++pageIdx) {
+ SkASSERT(proxies[pageIdx]);
+ SkString filename;
#ifdef SK_BUILD_FOR_ANDROID
- filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
+ filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
#else
- filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
+ filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
#endif
- save_pixels(fContext, proxies[pageIdx].get(), filename.c_str());
- }
+ save_pixels(fContext, proxies[pageIdx].get(), filename.c_str());
}
}
}
diff --git a/src/gpu/text/GrAtlasGlyphCache.h b/src/gpu/text/GrAtlasGlyphCache.h
index 20bc32a..a75ef53 100644
--- a/src/gpu/text/GrAtlasGlyphCache.h
+++ b/src/gpu/text/GrAtlasGlyphCache.h
@@ -111,7 +111,7 @@
*/
class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
public:
- GrAtlasGlyphCache(GrContext*, float maxTextureBytes);
+ GrAtlasGlyphCache(GrContext*, 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.
@@ -256,6 +256,7 @@
using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
GrContext* fContext;
StrikeHash fCache;
+ GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
GrAtlasTextStrike* fPreserveStrike;
GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];