Adjust atlas sizes to fix Mali400 precision issues
authorjvanverth <jvanverth@google.com>
Wed, 11 Mar 2015 18:18:11 +0000 (11:18 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 11 Mar 2015 18:18:11 +0000 (11:18 -0700)
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
src/gpu/GrFontAtlasSizes.h
src/gpu/GrFontCache.cpp
src/gpu/effects/GrBitmapTextGeoProc.cpp
src/gpu/effects/GrDistanceFieldTextureEffect.cpp

index a9fe4c9..eb172af 100755 (executable)
@@ -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;
index 5a1821c..d5c5e28 100644 (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
index 2bc5567..f5c1c22 100644 (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) {
index 54e8891..2c187a9 100644 (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(),
index 3b9bc9b..89a634c 100755 (executable)
@@ -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);