Reland "Have GrAtlasManager use legacy behavior"

This is a reland of 4b7b2ceb4a

Original change's description:
> Have GrAtlasManager use legacy behavior
>
> The old code would generate a 1024 x 2048 x 4 atlas given a
> max size of 4MiB. And, the plot sizes would be 256 x 256. This CL
> mimics that behavior.
>
> Change-Id: Iae741d5409daa034c6c3086c8a09476fb343353d
> Reviewed-on: https://skia-review.googlesource.com/c/162321
> Commit-Queue: Herb Derby <herb@google.com>
> Reviewed-by: Mike Klein <mtklein@google.com>

Change-Id: I86cc8d2fb07f5317897f094c6fc172c1ca4c8a1c
Reviewed-on: https://skia-review.googlesource.com/c/162720
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
Herb Derby 2018-10-15 16:39:39 -04:00 committed by Skia Commit-Bot
parent 050be74e6d
commit bbf5fb5be4
2 changed files with 90 additions and 65 deletions

View File

@ -190,7 +190,7 @@ GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider,
, fNumActivePages(0) {
fPlotWidth = fTextureWidth / numPlotsX;
fPlotHeight = fTextureHeight / numPlotsY;
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
SkASSERT(numPlotsX * numPlotsY <= GrDrawOpAtlas::kMaxPlots);
SkASSERT(fPlotWidth * numPlotsX == fTextureWidth);
SkASSERT(fPlotHeight * numPlotsY == fTextureHeight);

View File

@ -21,69 +21,6 @@
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;
};
/**
* This class manages one or more atlas textures on behalf of GrDrawOps. The draw ops that use the
@ -119,6 +56,8 @@ public:
/** Is the atlas allowed to use more than one texture? */
enum class AllowMultitexturing : bool { kNo, kYes };
static constexpr int kMaxPlots = 32;
/**
* An AtlasID is an opaque handle which callers can use to determine if the atlas contains
* a specific piece of data.
@ -265,7 +204,6 @@ public:
}
static constexpr int kMinItems = 4;
static constexpr int kMaxPlots = 32;
SkSTArray<kMinItems, PlotData, true> fPlotsToUpdate;
uint32_t fPlotAlreadyUpdated[kMaxMultitexturePages];
@ -471,4 +409,91 @@ private:
uint32_t fNumActivePages;
};
// 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:
if (fPlotsPerLongDimension * fPlotsPerLongDimension > GrDrawOpAtlas::kMaxPlots) {
return {fPlotsPerLongDimension / 2, fPlotsPerLongDimension / 2};
}
return {fPlotsPerLongDimension, fPlotsPerLongDimension};
// Note: because of the 2048 limit in the longest dimension, the largest atlas can be
// 1024 x 2048. The maximum number of plots will be 32 for 256 x 256 so that plot
// size is always safe.
case kA565_GrMaskFormat:
case kARGB_GrMaskFormat: {
static_assert((kMaxDistanceFieldDim / kPlotSize)
* (kMaxDistanceFieldDim / kPlotSize) / 2 <= GrDrawOpAtlas::kMaxPlots,
"");
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) {
// TODO(herb): remove this legacy fudge factor when the interface is changed to specify
// correct byte use numbers.
maxBytes *= 2;
// Because of limitations of the distance field text, the largest an atlas can be is 2048.
if (maxDimension > kMaxDistanceFieldDim) {
maxDimension = kMaxDistanceFieldDim;
}
// We can't use more bytes than the maxDimension will support.
if (maxBytes > maxDimension * maxDimension) {
maxBytes = maxDimension * maxDimension;
}
// 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));
// 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;
}
static constexpr size_t kMaxDistanceFieldDim = 2048;
// The width and height of a plot.
static constexpr int kPlotSize = 256;
// This is the height (longest dimension) of the ARGB atlas divided by the plot size.
const int fPlotsPerLongDimension;
};
#endif