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:
parent
303e83e6b3
commit
aa5f38f0ba
@ -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;
|
||||
|
@ -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. */
|
||||
|
@ -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 };
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user