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 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;

View File

@ -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. */

View File

@ -8,11 +8,7 @@
#ifndef GrDrawOpAtlas_DEFINED
#define GrDrawOpAtlas_DEFINED
#include <cmath>
#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<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;
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 };

View File

@ -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;
}

View File

@ -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<const GrCaps> fCaps;
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount];
SkScalar fGlyphSizeLimit;
GrProxyProvider* fProxyProvider;
sk_sp<const GrCaps> fCaps;
GrGlyphCache* fGlyphCache;
GrDrawOpAtlasConfig fAtlasConfigs;
typedef GrOnFlushCallbackObject INHERITED;
};

View File

@ -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) {

View File

@ -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);
}

View File

@ -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() {