Adjust atlas sizes to fix Mali400 precision issues

The previous change to atlas sizes introduced an issue where texture
coordinates for glyphs stored on the right side of the atlas were being
computed in an imprecise manner on Mali400 chips.

The only reasonable fix appears to be to use power-of-two texture sizes.
This widens the glyph atlas to the next power of 2 (or 2048) for A8 glyphs
only, and widens each GrPlot by 2x as well. By doing this, we can fit 3-4 large
distance field glyphs into a single GrPlot, which gives us 100-128 total large
glyphs at one time.

The 565 and 8888 glyph atlases are kept in their original size to preserve
space.

BUG=skia:3523

Review URL: https://codereview.chromium.org/994303003
This commit is contained in:
jvanverth 2015-03-11 11:18:11 -07:00 committed by Commit bot
parent 6ba791f661
commit cb251f1d0a
5 changed files with 48 additions and 33 deletions

View File

@ -34,10 +34,9 @@ SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
static const int kSmallDFFontSize = 32;
static const int kSmallDFFontLimit = 32;
static const int kMediumDFFontSize = 70;
static const int kMediumDFFontLimit = 70;
static const int kLargeDFFontSize = 156;
SK_COMPILE_ASSERT(GR_SDF_MAX_SIZE >= kLargeDFFontSize, sdf_too_big);
static const int kMediumDFFontSize = 72;
static const int kMediumDFFontLimit = 72;
static const int kLargeDFFontSize = 162;
static const int kVerticesPerGlyph = 4;
static const int kIndicesPerGlyph = 6;

View File

@ -9,27 +9,25 @@
#ifndef GrFontAtlasSizes_DEFINED
#define GrFontAtlasSizes_DEFINED
#include "SkDistanceFieldGen.h"
#define GR_FONT_ATLAS_TEXTURE_WIDTH 1024
#define GR_FONT_ATLAS_A8_TEXTURE_WIDTH 2048
#define GR_FONT_ATLAS_TEXTURE_HEIGHT 2048
#define GR_SDF_MAX_SIZE 156
#define GR_FONT_ATLAS_PLOT_WIDTH 256
#define GR_FONT_ATLAS_A8_PLOT_WIDTH 512
#define GR_FONT_ATLAS_PLOT_HEIGHT 256
// allows us to fit four of the largest distance field glyphs
#define GR_FONT_ATLAS_PLOT_WIDTH (2*(GR_SDF_MAX_SIZE+2*SK_DistanceFieldPad))
#define GR_FONT_ATLAS_PLOT_HEIGHT (2*(GR_SDF_MAX_SIZE+2*SK_DistanceFieldPad))
#define GR_FONT_ATLAS_NUM_PLOTS_X 5
#define GR_FONT_ATLAS_NUM_PLOTS_Y 6
#define GR_FONT_ATLAS_TEXTURE_WIDTH (GR_FONT_ATLAS_PLOT_WIDTH*GR_FONT_ATLAS_NUM_PLOTS_X)
SK_COMPILE_ASSERT(GR_FONT_ATLAS_TEXTURE_WIDTH == 1640, font_atlas_unexpected_size);
#define GR_FONT_ATLAS_TEXTURE_HEIGHT (GR_FONT_ATLAS_PLOT_HEIGHT*GR_FONT_ATLAS_NUM_PLOTS_Y)
SK_COMPILE_ASSERT(GR_FONT_ATLAS_TEXTURE_HEIGHT == 1968, font_atlas_unexpected_size);
#define GR_FONT_ATLAS_NUM_PLOTS_X (GR_FONT_ATLAS_TEXTURE_WIDTH / GR_FONT_ATLAS_PLOT_WIDTH)
#define GR_FONT_ATLAS_A8_NUM_PLOTS_X (GR_FONT_ATLAS_A8_TEXTURE_WIDTH / GR_FONT_ATLAS_A8_PLOT_WIDTH)
#define GR_FONT_ATLAS_NUM_PLOTS_Y (GR_FONT_ATLAS_TEXTURE_HEIGHT / GR_FONT_ATLAS_PLOT_HEIGHT)
// one over width and height
#define GR_FONT_ATLAS_RECIP_WIDTH "0.00060975609"
#define GR_FONT_ATLAS_RECIP_HEIGHT "0.00050813008"
#define GR_FONT_ATLAS_RECIP_WIDTH "0.0009765625"
#define GR_FONT_ATLAS_A8_RECIP_WIDTH "0.00048828125"
#define GR_FONT_ATLAS_RECIP_HEIGHT "0.00048828125"
// 1/(3*width)
#define GR_FONT_ATLAS_LCD_DELTA "0.00020325203"
// only used for distance fields, which are A8
#define GR_FONT_ATLAS_LCD_DELTA "0.000162760417"
#endif

View File

@ -113,13 +113,23 @@ GrPlot* GrFontCache::addToAtlas(GrMaskFormat format, GrAtlas::ClientPlotUsage* u
GrPixelConfig config = mask_format_to_pixel_config(format);
int atlasIndex = mask_format_to_atlas_index(format);
if (NULL == fAtlases[atlasIndex]) {
SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_TEXTURE_WIDTH,
GR_FONT_ATLAS_TEXTURE_HEIGHT);
fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSurfaceFlags,
textureSize,
GR_FONT_ATLAS_NUM_PLOTS_X,
GR_FONT_ATLAS_NUM_PLOTS_Y,
true));
if (kA8_GrMaskFormat == format) {
SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_A8_TEXTURE_WIDTH,
GR_FONT_ATLAS_TEXTURE_HEIGHT);
fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSurfaceFlags,
textureSize,
GR_FONT_ATLAS_A8_NUM_PLOTS_X,
GR_FONT_ATLAS_NUM_PLOTS_Y,
true));
} else {
SkISize textureSize = SkISize::Make(GR_FONT_ATLAS_TEXTURE_WIDTH,
GR_FONT_ATLAS_TEXTURE_HEIGHT);
fAtlases[atlasIndex] = SkNEW_ARGS(GrAtlas, (fGpu, config, kNone_GrSurfaceFlags,
textureSize,
GR_FONT_ATLAS_NUM_PLOTS_X,
GR_FONT_ATLAS_NUM_PLOTS_Y,
true));
}
}
return fAtlases[atlasIndex]->addToAtlas(usage, width, height, image, loc);
}
@ -281,7 +291,9 @@ bool GrTextStrike::glyphTooLargeForAtlas(GrGlyph* glyph) {
int width = glyph->fBounds.width();
int height = glyph->fBounds.height();
int pad = fUseDistanceField ? 2 * SK_DistanceFieldPad : 0;
if (width + pad > GR_FONT_ATLAS_PLOT_WIDTH) {
int plotWidth = (kA8_GrMaskFormat == glyph->fMaskFormat) ? GR_FONT_ATLAS_A8_PLOT_WIDTH
: GR_FONT_ATLAS_PLOT_WIDTH;
if (width + pad > plotWidth) {
return true;
}
if (height + pad > GR_FONT_ATLAS_PLOT_HEIGHT) {

View File

@ -39,9 +39,15 @@ public:
GrGLVertToFrag v(kVec2f_GrSLType);
pb->addVarying("TextureCoords", &v);
// this is only used with text, so our texture bounds always match the glyph atlas
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_RECIP_WIDTH ", "
GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", v.vsOut(),
cte.inTextureCoords()->fName);
if (cte.maskFormat() == kA8_GrMaskFormat) {
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", v.vsOut(),
cte.inTextureCoords()->fName);
} else {
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_RECIP_WIDTH ", "
GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", v.vsOut(),
cte.inTextureCoords()->fName);
}
// Setup pass through color
this->setupColorPassThrough(pb, local.fInputColorType, args.fOutputColor, cte.inColor(),

View File

@ -56,7 +56,7 @@ public:
GrGLVertToFrag uv(kVec2f_GrSLType);
args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
// this is only used with text, so our texture bounds always match the glyph atlas
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_RECIP_WIDTH ", "
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
dfTexEffect.inTextureCoords()->fName);
@ -582,7 +582,7 @@ public:
GrGLVertToFrag uv(kVec2f_GrSLType);
args.fPB->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
// this is only used with text, so our texture bounds always match the glyph atlas
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_RECIP_WIDTH ", "
vsBuilder->codeAppendf("%s = vec2(" GR_FONT_ATLAS_A8_RECIP_WIDTH ", "
GR_FONT_ATLAS_RECIP_HEIGHT ")*%s;", uv.vsOut(),
dfTexEffect.inTextureCoords()->fName);