From cb251f1d0a8aa7f3e6f685b45046173fc05f4b92 Mon Sep 17 00:00:00 2001 From: jvanverth Date: Wed, 11 Mar 2015 11:18:11 -0700 Subject: [PATCH] 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 --- src/gpu/GrDistanceFieldTextContext.cpp | 7 ++--- src/gpu/GrFontAtlasSizes.h | 30 +++++++++---------- src/gpu/GrFontCache.cpp | 28 ++++++++++++----- src/gpu/effects/GrBitmapTextGeoProc.cpp | 12 ++++++-- .../effects/GrDistanceFieldTextureEffect.cpp | 4 +-- 5 files changed, 48 insertions(+), 33 deletions(-) diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp index a9fe4c9bf6..eb172af1b6 100755 --- a/src/gpu/GrDistanceFieldTextContext.cpp +++ b/src/gpu/GrDistanceFieldTextContext.cpp @@ -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; diff --git a/src/gpu/GrFontAtlasSizes.h b/src/gpu/GrFontAtlasSizes.h index 5a1821cdce..d5c5e287e1 100644 --- a/src/gpu/GrFontAtlasSizes.h +++ b/src/gpu/GrFontAtlasSizes.h @@ -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 diff --git a/src/gpu/GrFontCache.cpp b/src/gpu/GrFontCache.cpp index 2bc5567c19..f5c1c22a3d 100644 --- a/src/gpu/GrFontCache.cpp +++ b/src/gpu/GrFontCache.cpp @@ -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) { diff --git a/src/gpu/effects/GrBitmapTextGeoProc.cpp b/src/gpu/effects/GrBitmapTextGeoProc.cpp index 54e88917ad..2c187a9dcf 100644 --- a/src/gpu/effects/GrBitmapTextGeoProc.cpp +++ b/src/gpu/effects/GrBitmapTextGeoProc.cpp @@ -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(), diff --git a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp index 3b9bc9b6f0..89a634c5c4 100755 --- a/src/gpu/effects/GrDistanceFieldTextureEffect.cpp +++ b/src/gpu/effects/GrDistanceFieldTextureEffect.cpp @@ -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);