From aa5f38f0ba7d3aa1a4a58e34b3add7b8412c1638 Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Mon, 10 Sep 2018 20:28:05 +0000 Subject: [PATCH] Revert "Simplify plots to always be 512x512 and simplify GrDrawOpAtlasConfig" This reverts commit a2bc1ca21bbc354ec6b1d2a3456ef0c367593e8b. Reason for revert: see if make chromecast failures go away Original change's description: > Simplify plots to always be 512x512 and simplify GrDrawOpAtlasConfig > > Change-Id: I1353d3facf191e3323027fc288715672240d1f87 > Reviewed-on: https://skia-review.googlesource.com/152591 > Reviewed-by: Jim Van Verth > Reviewed-by: Herb Derby > Commit-Queue: Herb Derby TBR=jvanverth@google.com,bsalomon@google.com,herb@google.com Change-Id: I970ec86678c97046001889dc436df5307750da1b No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/153180 Reviewed-by: Cary Clark Commit-Queue: Cary Clark --- include/gpu/GrContext.h | 5 ++ src/gpu/GrContextPriv.h | 4 ++ src/gpu/GrDrawOpAtlas.h | 74 +++------------------------ src/gpu/text/GrAtlasManager.cpp | 91 +++++++++++++++++++++++++-------- src/gpu/text/GrAtlasManager.h | 11 ++-- src/gpu/text/GrGlyphCache.cpp | 5 +- tests/TextBlobCacheTest.cpp | 25 +++++++-- tools/gpu/GrTest.cpp | 7 +++ 8 files changed, 126 insertions(+), 96 deletions(-) diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index c22705d95f..55c79bdcea 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -27,15 +27,19 @@ class GrContextPriv; class GrContextThreadSafeProxy; class GrContextThreadSafeProxyPriv; class GrDrawingManager; +struct GrDrawOpAtlasConfig; class GrFragmentProcessor; struct GrGLInterface; class GrGlyphCache; class GrGpu; +class GrIndexBuffer; struct GrMockOptions; class GrOpMemoryPool; +class GrOvalRenderer; class GrPath; class GrProxyProvider; class GrRenderTargetContext; +class GrResourceEntry; class GrResourceCache; class GrResourceProvider; class GrSamplerState; @@ -44,6 +48,7 @@ class GrSwizzle; class GrTextBlobCache; class GrTextContext; class GrTextureProxy; +class GrVertexBuffer; struct GrVkBackendContext; class SkImage; diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h index afb3949f4c..f68cc831e8 100644 --- a/src/gpu/GrContextPriv.h +++ b/src/gpu/GrContextPriv.h @@ -263,6 +263,10 @@ public: this is for testing only */ void setTextBlobCacheLimit_ForTesting(size_t bytes); + /** Specify the sizes of the GrAtlasTextContext atlases. The configs pointer below should be + to an array of 3 entries */ + void setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs); + /** Get pointer to atlas texture for given mask format. Note that this wraps an actively mutating texture in an SkImage. This could yield unexpected results if it gets cached or used more generally. */ diff --git a/src/gpu/GrDrawOpAtlas.h b/src/gpu/GrDrawOpAtlas.h index 41807b3d8e..e1253f02ed 100644 --- a/src/gpu/GrDrawOpAtlas.h +++ b/src/gpu/GrDrawOpAtlas.h @@ -8,11 +8,7 @@ #ifndef GrDrawOpAtlas_DEFINED #define GrDrawOpAtlas_DEFINED -#include - -#include "SkGlyphRun.h" #include "SkIPoint16.h" -#include "SkSize.h" #include "SkTDArray.h" #include "SkTInternalLList.h" @@ -21,68 +17,13 @@ class GrOnFlushResourceProvider; class GrRectanizer; -// There are three atlases (A8, 565, ARGB) that are kept in relation with one another. In -// general, the A8 dimensions are NxN and 565 and ARGB are N/2xN with the constraint that an atlas -// size will always contain at least one plot. Since the ARGB atlas takes the most space, its -// dimensions are used to size the other two atlases. -class GrDrawOpAtlasConfig { -public: - GrDrawOpAtlasConfig(int maxDimension, size_t maxBytes) - : fPlotsPerLongDimension{PlotsPerLongDimensionForARGB(maxDimension, maxBytes)} { - SkASSERT(kPlotSize >= SkGlyphCacheCommon::kSkSideTooBigForAtlas); - } - - // For testing only - make minimum sized atlases -- 1x1 plots wide. - GrDrawOpAtlasConfig() : fPlotsPerLongDimension{1} { - SkASSERT(kPlotSize >= SkGlyphCacheCommon::kSkSideTooBigForAtlas); - } - - SkISize numPlots(GrMaskFormat type) const { - switch(type) { - case kA8_GrMaskFormat: - return {fPlotsPerLongDimension, fPlotsPerLongDimension}; - case kA565_GrMaskFormat: - case kARGB_GrMaskFormat: { - int plotsPerWidth = std::max(1, fPlotsPerLongDimension / 2); - return {plotsPerWidth, fPlotsPerLongDimension}; - } - } - - // This make some compilers happy. - return {1,1}; - } - - SkISize atlasDimensions(GrMaskFormat type) const { - SkISize plots = this->numPlots(type); - return {plots.width() * kPlotSize, plots.height() * kPlotSize}; - } - -private: - static int PlotsPerLongDimensionForARGB(size_t maxDimension, size_t maxBytes) { - // Find the largest area of pixels in a width:height with a proportion of 1:2 that fits in - // maxTextureBytes. In the following P is pixel size, H is height, and W is width. - // P*H*W = maxTextureSize => P*H*(H/2) = maxTextureSize => H = sqrt(2*maxTextureSize/P) - double fitsHeight = - std::sqrt(2.0 * maxBytes / GrMaskFormatBytesPerPixel(kARGB_GrMaskFormat)); - - // Because of limitations of the distance field text, the largest an atlas can be is 2048. - maxDimension = std::min(maxDimension, SkTo(2048)); - - // Limit height to the maximum texture dimension and the minimum atlas size. - double height = std::max(std::min(fitsHeight, (double)maxDimension), (double)kPlotSize); - - // Find the greatest power of 2 that is less than height. - double alignedHeight = std::exp2(std::floor(std::log2(height))); - - // Calculate the atlas dimensions. - return (int)alignedHeight / kPlotSize; - } - - // The width and height of a plot. - static constexpr int kPlotSize = 512; - - // This is the height (longest dimension) of the ARGB atlas divided by the plot size. - const int fPlotsPerLongDimension; +struct GrDrawOpAtlasConfig { + int numPlotsX() const { return fWidth / fPlotWidth; } + int numPlotsY() const { return fHeight / fPlotHeight; } + int fWidth; + int fHeight; + int fPlotWidth; + int fPlotHeight; }; /** @@ -114,7 +55,6 @@ 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 }; diff --git a/src/gpu/text/GrAtlasManager.cpp b/src/gpu/text/GrAtlasManager.cpp index c1b3d7bb40..ddd0b0328b 100644 --- a/src/gpu/text/GrAtlasManager.cpp +++ b/src/gpu/text/GrAtlasManager.cpp @@ -10,17 +10,66 @@ #include "GrGlyph.h" #include "GrGlyphCache.h" -GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* glyphCache, - size_t maxTextureBytes, - GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) - : fAllowMultitexturing{allowMultitexturing} - , fGlyphSizeLimit{SkGlyphCacheCommon::kSkSideTooBigForAtlas} - , fProxyProvider{proxyProvider} - , fCaps{fProxyProvider->refCaps()} - , fGlyphCache{glyphCache} - , fAtlasConfigs{fCaps->maxTextureSize(), maxTextureBytes} { } +void GrAtlasManager::ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim, + int* minDim, int* maxPlot, int* minPlot) { + SkASSERT(maxDim && minDim && maxPlot && minPlot); + // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2 + int log2MaxTextureSize = SkPrevLog2(maxTextureSize); + int log2MaxDim = 9; + static const size_t kOne = 1u; + for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) { + size_t maxDimTmp = kOne << log2MaxDim; + size_t minDimTmp = kOne << (log2MaxDim - 1); -GrAtlasManager::~GrAtlasManager() = default; + if (maxDimTmp * minDimTmp * 4 >= maxTextureBytes) { + break; + } + } + + + int log2MinDim = log2MaxDim - 1; + *maxDim = 1 << log2MaxDim; + *minDim = 1 << log2MinDim; + // Plots are either 256 or 512. + *maxPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 2))); + *minPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 3))); +} + +GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* glyphCache, + float maxTextureBytes, + GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) + : fAllowMultitexturing(allowMultitexturing) + , fProxyProvider(proxyProvider) + , fGlyphCache(glyphCache) { + fCaps = fProxyProvider->refCaps(); + + int maxDim, minDim, maxPlot, minPlot; + ComputeAtlasLimits(fCaps->maxTextureSize(), maxTextureBytes, &maxDim, &minDim, &maxPlot, + &minPlot); + + // 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 = maxPlot; + + // 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; +} + +GrAtlasManager::~GrAtlasManager() { +} static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) { switch (format) { @@ -147,28 +196,28 @@ void GrAtlasManager::dump(GrContext* context) const { } #endif -void GrAtlasManager::setAtlasSizesToMinimum_ForTesting() { +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; } - - // Set all the atlas sizes to 1x1 plot each. - new (&fAtlasConfigs) GrDrawOpAtlasConfig{}; + memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs)); } bool GrAtlasManager::initAtlas(GrMaskFormat format) { int index = MaskFormatToAtlasIndex(format); - if (fAtlases[index] == nullptr) { + if (!fAtlases[index]) { GrPixelConfig config = mask_format_to_pixel_config(format); - SkISize atlasDimensions = fAtlasConfigs.atlasDimensions(format); - SkISize numPlots = fAtlasConfigs.numPlots(format); + 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, atlasDimensions.width(), atlasDimensions.height(), - numPlots.width(), numPlots.height(), fAllowMultitexturing, - &GrGlyphCache::HandleEviction, fGlyphCache); + fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height, + numPlotsX, numPlotsY, fAllowMultitexturing, + &GrGlyphCache::HandleEviction, + fGlyphCache); if (!fAtlases[index]) { return false; } diff --git a/src/gpu/text/GrAtlasManager.h b/src/gpu/text/GrAtlasManager.h index e857ae825d..6c168534ad 100644 --- a/src/gpu/text/GrAtlasManager.h +++ b/src/gpu/text/GrAtlasManager.h @@ -27,7 +27,7 @@ struct GrGlyph; class GrAtlasManager : public GrOnFlushCallbackObject { public: GrAtlasManager(GrProxyProvider*, GrGlyphCache*, - size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing); + float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing); ~GrAtlasManager() override; // Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using @@ -57,6 +57,9 @@ public: SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; } + static void ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim, + int* minDim, int* maxPlot, int* minPlot); + void freeAll(); bool hasGlyph(GrGlyph* glyph); @@ -118,7 +121,7 @@ public: void dump(GrContext* context) const; #endif - void setAtlasSizesToMinimum_ForTesting(); + void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]); void setMaxPages_TestingOnly(uint32_t maxPages); private: @@ -144,13 +147,13 @@ private: return fAtlases[atlasIndex].get(); } + sk_sp fCaps; GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing; std::unique_ptr fAtlases[kMaskFormatCount]; + GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount]; SkScalar fGlyphSizeLimit; GrProxyProvider* fProxyProvider; - sk_sp fCaps; GrGlyphCache* fGlyphCache; - GrDrawOpAtlasConfig fAtlasConfigs; typedef GrOnFlushCallbackObject INHERITED; }; diff --git a/src/gpu/text/GrGlyphCache.cpp b/src/gpu/text/GrGlyphCache.cpp index 933a1c0434..4890804fc0 100644 --- a/src/gpu/text/GrGlyphCache.cpp +++ b/src/gpu/text/GrGlyphCache.cpp @@ -42,7 +42,10 @@ void GrGlyphCache::freeAll() { } SkScalar GrGlyphCache::ComputeGlyphSizeLimit(int maxTextureSize, size_t maxTextureBytes) { - return SkGlyphCacheCommon::kSkSideTooBigForAtlas; + int maxDim, minDim, maxPlot, minPlot; + GrAtlasManager::ComputeAtlasLimits(maxTextureSize, maxTextureBytes, &maxDim, &minDim, &maxPlot, + &minPlot); + return minPlot; } void GrGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) { diff --git a/tests/TextBlobCacheTest.cpp b/tests/TextBlobCacheTest.cpp index b7f85ca3bf..4e8a704dc0 100644 --- a/tests/TextBlobCacheTest.cpp +++ b/tests/TextBlobCacheTest.cpp @@ -44,7 +44,26 @@ static const int kWidth = 1024; static const int kHeight = 768; static void setup_always_evict_atlas(GrContext* context) { - context->contextPriv().getAtlasManager()->setAtlasSizesToMinimum_ForTesting(); + int dim = SkGlyphCacheCommon::kSkSideTooBigForAtlas; + // These sizes were selected because they allow each atlas to hold a single plot and will thus + // stress the atlas + GrDrawOpAtlasConfig configs[3]; + configs[kA8_GrMaskFormat].fWidth = dim; + configs[kA8_GrMaskFormat].fHeight = dim; + configs[kA8_GrMaskFormat].fPlotWidth = dim; + configs[kA8_GrMaskFormat].fPlotHeight = dim; + + configs[kA565_GrMaskFormat].fWidth = dim; + configs[kA565_GrMaskFormat].fHeight = dim; + configs[kA565_GrMaskFormat].fPlotWidth = dim; + configs[kA565_GrMaskFormat].fPlotHeight = dim; + + configs[kARGB_GrMaskFormat].fWidth = dim; + configs[kARGB_GrMaskFormat].fHeight = dim; + configs[kARGB_GrMaskFormat].fPlotWidth = dim; + configs[kARGB_GrMaskFormat].fPlotHeight = dim; + + context->contextPriv().setTextContextAtlasSizes_ForTesting(configs); } // This test hammers the GPU textblobcache and font atlas @@ -156,7 +175,7 @@ DEF_GPUTEST_FOR_NULLGL_CONTEXT(TextBlobCache, reporter, ctxInfo) { } DEF_GPUTEST_FOR_NULLGL_CONTEXT(TextBlobStressCache, reporter, ctxInfo) { - text_blob_cache_inner(reporter, ctxInfo.grContext(), 1024, 256, 10, true, true); + text_blob_cache_inner(reporter, ctxInfo.grContext(), 256, 256, 10, true, true); } DEF_GPUTEST_FOR_NULLGL_CONTEXT(TextBlobAbnormal, reporter, ctxInfo) { @@ -164,5 +183,5 @@ DEF_GPUTEST_FOR_NULLGL_CONTEXT(TextBlobAbnormal, reporter, ctxInfo) { } DEF_GPUTEST_FOR_NULLGL_CONTEXT(TextBlobStressAbnormal, reporter, ctxInfo) { - text_blob_cache_inner(reporter, ctxInfo.grContext(), 1024, 256, 10, false, true); + text_blob_cache_inner(reporter, ctxInfo.grContext(), 256, 256, 10, false, true); } diff --git a/tools/gpu/GrTest.cpp b/tools/gpu/GrTest.cpp index d1ed6205b8..088dd3019c 100644 --- a/tools/gpu/GrTest.cpp +++ b/tools/gpu/GrTest.cpp @@ -43,6 +43,13 @@ void GrContextPriv::setTextBlobCacheLimit_ForTesting(size_t bytes) { fContext->fTextBlobCache->setBudget(bytes); } +void GrContextPriv::setTextContextAtlasSizes_ForTesting(const GrDrawOpAtlasConfig* configs) { + GrAtlasManager* atlasManager = this->getAtlasManager(); + if (atlasManager) { + atlasManager->setAtlasSizes_ForTesting(configs); + } +} + /////////////////////////////////////////////////////////////////////////////// void GrContextPriv::purgeAllUnlockedResources_ForTesting() {