Revert "Simplify plots to always be 512x512 and simplify GrDrawOpAtlasConfig"

This reverts commit a2bc1ca21b.

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 <jvanverth@google.com>
> Reviewed-by: Herb Derby <herb@google.com>
> Commit-Queue: Herb Derby <herb@google.com>

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 <caryclark@skia.org>
Commit-Queue: Cary Clark <caryclark@skia.org>
This commit is contained in:
Cary Clark 2018-09-10 20:28:05 +00:00 committed by Skia Commit-Bot
parent 303e83e6b3
commit aa5f38f0ba
8 changed files with 126 additions and 96 deletions

View File

@ -27,15 +27,19 @@ class GrContextPriv;
class GrContextThreadSafeProxy; class GrContextThreadSafeProxy;
class GrContextThreadSafeProxyPriv; class GrContextThreadSafeProxyPriv;
class GrDrawingManager; class GrDrawingManager;
struct GrDrawOpAtlasConfig;
class GrFragmentProcessor; class GrFragmentProcessor;
struct GrGLInterface; struct GrGLInterface;
class GrGlyphCache; class GrGlyphCache;
class GrGpu; class GrGpu;
class GrIndexBuffer;
struct GrMockOptions; struct GrMockOptions;
class GrOpMemoryPool; class GrOpMemoryPool;
class GrOvalRenderer;
class GrPath; class GrPath;
class GrProxyProvider; class GrProxyProvider;
class GrRenderTargetContext; class GrRenderTargetContext;
class GrResourceEntry;
class GrResourceCache; class GrResourceCache;
class GrResourceProvider; class GrResourceProvider;
class GrSamplerState; class GrSamplerState;
@ -44,6 +48,7 @@ class GrSwizzle;
class GrTextBlobCache; class GrTextBlobCache;
class GrTextContext; class GrTextContext;
class GrTextureProxy; class GrTextureProxy;
class GrVertexBuffer;
struct GrVkBackendContext; struct GrVkBackendContext;
class SkImage; class SkImage;

View File

@ -263,6 +263,10 @@ public:
this is for testing only */ this is for testing only */
void setTextBlobCacheLimit_ForTesting(size_t bytes); 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 /** 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 actively mutating texture in an SkImage. This could yield unexpected results
if it gets cached or used more generally. */ if it gets cached or used more generally. */

View File

@ -8,11 +8,7 @@
#ifndef GrDrawOpAtlas_DEFINED #ifndef GrDrawOpAtlas_DEFINED
#define GrDrawOpAtlas_DEFINED #define GrDrawOpAtlas_DEFINED
#include <cmath>
#include "SkGlyphRun.h"
#include "SkIPoint16.h" #include "SkIPoint16.h"
#include "SkSize.h"
#include "SkTDArray.h" #include "SkTDArray.h"
#include "SkTInternalLList.h" #include "SkTInternalLList.h"
@ -21,68 +17,13 @@
class GrOnFlushResourceProvider; class GrOnFlushResourceProvider;
class GrRectanizer; class GrRectanizer;
// There are three atlases (A8, 565, ARGB) that are kept in relation with one another. In struct GrDrawOpAtlasConfig {
// general, the A8 dimensions are NxN and 565 and ARGB are N/2xN with the constraint that an atlas int numPlotsX() const { return fWidth / fPlotWidth; }
// size will always contain at least one plot. Since the ARGB atlas takes the most space, its int numPlotsY() const { return fHeight / fPlotHeight; }
// dimensions are used to size the other two atlases. int fWidth;
class GrDrawOpAtlasConfig { int fHeight;
public: int fPlotWidth;
GrDrawOpAtlasConfig(int maxDimension, size_t maxBytes) int fPlotHeight;
: 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<size_t>(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;
}; };
/** /**
@ -114,7 +55,6 @@ class GrDrawOpAtlas {
private: private:
static constexpr auto kMaxMultitexturePages = 4; static constexpr auto kMaxMultitexturePages = 4;
public: public:
/** Is the atlas allowed to use more than one texture? */ /** Is the atlas allowed to use more than one texture? */
enum class AllowMultitexturing : bool { kNo, kYes }; enum class AllowMultitexturing : bool { kNo, kYes };

View File

@ -10,17 +10,66 @@
#include "GrGlyph.h" #include "GrGlyph.h"
#include "GrGlyphCache.h" #include "GrGlyphCache.h"
GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* glyphCache, void GrAtlasManager::ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim,
size_t maxTextureBytes, int* minDim, int* maxPlot, int* minPlot) {
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) SkASSERT(maxDim && minDim && maxPlot && minPlot);
: fAllowMultitexturing{allowMultitexturing} // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
, fGlyphSizeLimit{SkGlyphCacheCommon::kSkSideTooBigForAtlas} int log2MaxTextureSize = SkPrevLog2(maxTextureSize);
, fProxyProvider{proxyProvider} int log2MaxDim = 9;
, fCaps{fProxyProvider->refCaps()} static const size_t kOne = 1u;
, fGlyphCache{glyphCache} for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
, fAtlasConfigs{fCaps->maxTextureSize(), maxTextureBytes} { } 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) { static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format) {
switch (format) { switch (format) {
@ -147,28 +196,28 @@ void GrAtlasManager::dump(GrContext* context) const {
} }
#endif #endif
void GrAtlasManager::setAtlasSizesToMinimum_ForTesting() { void GrAtlasManager::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) {
// Delete any old atlases. // Delete any old atlases.
// This should be safe to do as long as we are not in the middle of a flush. // 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++) { for (int i = 0; i < kMaskFormatCount; i++) {
fAtlases[i] = nullptr; fAtlases[i] = nullptr;
} }
memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs));
// Set all the atlas sizes to 1x1 plot each.
new (&fAtlasConfigs) GrDrawOpAtlasConfig{};
} }
bool GrAtlasManager::initAtlas(GrMaskFormat format) { bool GrAtlasManager::initAtlas(GrMaskFormat format) {
int index = MaskFormatToAtlasIndex(format); int index = MaskFormatToAtlasIndex(format);
if (fAtlases[index] == nullptr) { if (!fAtlases[index]) {
GrPixelConfig config = mask_format_to_pixel_config(format); GrPixelConfig config = mask_format_to_pixel_config(format);
SkISize atlasDimensions = fAtlasConfigs.atlasDimensions(format); int width = fAtlasConfigs[index].fWidth;
SkISize numPlots = fAtlasConfigs.numPlots(format); int height = fAtlasConfigs[index].fHeight;
int numPlotsX = fAtlasConfigs[index].numPlotsX();
int numPlotsY = fAtlasConfigs[index].numPlotsY();
fAtlases[index] = GrDrawOpAtlas::Make( fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height,
fProxyProvider, config, atlasDimensions.width(), atlasDimensions.height(), numPlotsX, numPlotsY, fAllowMultitexturing,
numPlots.width(), numPlots.height(), fAllowMultitexturing, &GrGlyphCache::HandleEviction,
&GrGlyphCache::HandleEviction, fGlyphCache); fGlyphCache);
if (!fAtlases[index]) { if (!fAtlases[index]) {
return false; return false;
} }

View File

@ -27,7 +27,7 @@ struct GrGlyph;
class GrAtlasManager : public GrOnFlushCallbackObject { class GrAtlasManager : public GrOnFlushCallbackObject {
public: public:
GrAtlasManager(GrProxyProvider*, GrGlyphCache*, GrAtlasManager(GrProxyProvider*, GrGlyphCache*,
size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing); float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
~GrAtlasManager() override; ~GrAtlasManager() override;
// Change an expected 565 mask format to 8888 if 565 is not supported (will happen when using // 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; } SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; }
static void ComputeAtlasLimits(int maxTextureSize, size_t maxTextureBytes, int* maxDim,
int* minDim, int* maxPlot, int* minPlot);
void freeAll(); void freeAll();
bool hasGlyph(GrGlyph* glyph); bool hasGlyph(GrGlyph* glyph);
@ -118,7 +121,7 @@ public:
void dump(GrContext* context) const; void dump(GrContext* context) const;
#endif #endif
void setAtlasSizesToMinimum_ForTesting(); void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]);
void setMaxPages_TestingOnly(uint32_t maxPages); void setMaxPages_TestingOnly(uint32_t maxPages);
private: private:
@ -144,13 +147,13 @@ private:
return fAtlases[atlasIndex].get(); return fAtlases[atlasIndex].get();
} }
sk_sp<const GrCaps> fCaps;
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing; GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount]; std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];
SkScalar fGlyphSizeLimit; SkScalar fGlyphSizeLimit;
GrProxyProvider* fProxyProvider; GrProxyProvider* fProxyProvider;
sk_sp<const GrCaps> fCaps;
GrGlyphCache* fGlyphCache; GrGlyphCache* fGlyphCache;
GrDrawOpAtlasConfig fAtlasConfigs;
typedef GrOnFlushCallbackObject INHERITED; typedef GrOnFlushCallbackObject INHERITED;
}; };

View File

@ -42,7 +42,10 @@ void GrGlyphCache::freeAll() {
} }
SkScalar GrGlyphCache::ComputeGlyphSizeLimit(int maxTextureSize, size_t maxTextureBytes) { 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) { void GrGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) {

View File

@ -44,7 +44,26 @@ static const int kWidth = 1024;
static const int kHeight = 768; static const int kHeight = 768;
static void setup_always_evict_atlas(GrContext* context) { 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 // 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) { 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) { 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) { 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);
} }

View File

@ -43,6 +43,13 @@ void GrContextPriv::setTextBlobCacheLimit_ForTesting(size_t bytes) {
fContext->fTextBlobCache->setBudget(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() { void GrContextPriv::purgeAllUnlockedResources_ForTesting() {