Use unorm shorts for texture coordinates when rendering text.
authorjvanverth <jvanverth@google.com>
Fri, 19 Feb 2016 14:35:22 +0000 (06:35 -0800)
committerCommit bot <commit-bot@chromium.org>
Fri, 19 Feb 2016 14:35:22 +0000 (06:35 -0800)
There are a couple of reasons for this:
- Vulkan does not guarantee conversions from integral vertex attributes
  to floating point shader variables
- This may be faster and more precise on some platforms, as it avoids
  the aforementioned conversion and changes a multiply by a very small
  value to a multiply by a medium-sized value.
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1713693002
TBR=bsalomon@google.com

Review URL: https://codereview.chromium.org/1713693002

include/gpu/GrTypesPriv.h
src/gpu/GrBatchAtlas.h
src/gpu/GrTest.cpp
src/gpu/effects/GrBitmapTextGeoProc.cpp
src/gpu/effects/GrDistanceFieldGeoProc.cpp
src/gpu/gl/GrGLVertexArray.cpp
src/gpu/text/GrAtlasTextBlob_regenInBatch.cpp
src/gpu/text/GrBatchFontCache.cpp
src/gpu/text/GrBatchFontCache.h

index e04a912..834c185 100644 (file)
@@ -212,7 +212,7 @@ enum GrVertexAttribType {
     kUByte_GrVertexAttribType,   // unsigned byte, e.g. coverage
     kVec4ub_GrVertexAttribType,  // vector of 4 unsigned bytes, e.g. colors
 
-    kVec2s_GrVertexAttribType,   // vector of 2 shorts, e.g. texture coordinates
+    kVec2us_GrVertexAttribType,   // vector of 2 shorts, e.g. texture coordinates
 
     kInt_GrVertexAttribType,
     kUint_GrVertexAttribType,
@@ -235,7 +235,7 @@ static inline int GrVertexAttribTypeVectorCount(GrVertexAttribType type) {
     GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
     GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
     GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
-    GR_STATIC_ASSERT(6 == kVec2s_GrVertexAttribType);
+    GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType);
     GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType);
     GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kCounts) == kGrVertexAttribTypeCount);
@@ -252,7 +252,7 @@ static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
         4*sizeof(float),        // kVec4f_GrVertexAttribType
         1*sizeof(char),         // kUByte_GrVertexAttribType
         4*sizeof(char),         // kVec4ub_GrVertexAttribType
-        2*sizeof(int16_t),      // kVec2s_GrVertexAttribType
+        2*sizeof(int16_t),      // kVec2us_GrVertexAttribType
         sizeof(int32_t),        // kInt_GrVertexAttribType
         sizeof(uint32_t)        // kUint_GrVertexAttribType
     };
@@ -264,7 +264,7 @@ static inline size_t GrVertexAttribTypeSize(GrVertexAttribType type) {
     GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
     GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
     GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
-    GR_STATIC_ASSERT(6 == kVec2s_GrVertexAttribType);
+    GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType);
     GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType);
     GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType);
     GR_STATIC_ASSERT(SK_ARRAY_COUNT(kSizes) == kGrVertexAttribTypeCount);
@@ -283,7 +283,7 @@ static inline bool GrVertexAttribTypeIsIntType(GrVertexAttribType type) {
     GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
     GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
     GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
-    GR_STATIC_ASSERT(6 == kVec2s_GrVertexAttribType);
+    GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType);
     GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType);
     GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType);
     GR_STATIC_ASSERT(9 == kGrVertexAttribTypeCount);
@@ -300,7 +300,7 @@ static inline GrSLType GrVertexAttribTypeToSLType(GrVertexAttribType type) {
         case kUByte_GrVertexAttribType:
         case kFloat_GrVertexAttribType:
             return kFloat_GrSLType;
-        case kVec2s_GrVertexAttribType:
+        case kVec2us_GrVertexAttribType:
         case kVec2f_GrVertexAttribType:
             return kVec2f_GrSLType;
         case kVec3f_GrVertexAttribType:
index 61fc7e1..43dd692 100644 (file)
@@ -22,6 +22,8 @@ struct GrBatchAtlasConfig {
     int numPlotsY() const { return fHeight / fPlotWidth; }
     int fWidth;
     int fHeight;
+    int fLog2Width;
+    int fLog2Height;
     int fPlotWidth;
     int fPlotHeight;
 };
index 04122e1..b4fb27b 100644 (file)
@@ -29,16 +29,22 @@ void SetupAlwaysEvictAtlas(GrContext* context) {
     GrBatchAtlasConfig configs[3];
     configs[kA8_GrMaskFormat].fWidth = dim;
     configs[kA8_GrMaskFormat].fHeight = dim;
+    configs[kA8_GrMaskFormat].fLog2Width = SkNextLog2(dim);
+    configs[kA8_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     configs[kA8_GrMaskFormat].fPlotWidth = dim;
     configs[kA8_GrMaskFormat].fPlotHeight = dim;
 
     configs[kA565_GrMaskFormat].fWidth = dim;
     configs[kA565_GrMaskFormat].fHeight = dim;
+    configs[kA565_GrMaskFormat].fLog2Width = SkNextLog2(dim);
+    configs[kA565_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     configs[kA565_GrMaskFormat].fPlotWidth = dim;
     configs[kA565_GrMaskFormat].fPlotHeight = dim;
 
     configs[kARGB_GrMaskFormat].fWidth = dim;
     configs[kARGB_GrMaskFormat].fHeight = dim;
+    configs[kARGB_GrMaskFormat].fLog2Width = SkNextLog2(dim);
+    configs[kARGB_GrMaskFormat].fLog2Height = SkNextLog2(dim);
     configs[kARGB_GrMaskFormat].fPlotWidth = dim;
     configs[kARGB_GrMaskFormat].fPlotHeight = dim;
 
index 263676d..b4f6b7e 100644 (file)
@@ -31,16 +31,12 @@ public:
 
         // compute numbers to be hardcoded to convert texture coordinates from int to float
         SkASSERT(cte.numTextures() == 1);
-        GrTexture* atlas = cte.textureAccess(0).getTexture();
+        SkDEBUGCODE(GrTexture* atlas = cte.textureAccess(0).getTexture());
         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-        SkScalar recipWidth = 1.0f / atlas->width();
-        SkScalar recipHeight = 1.0f / atlas->height();
 
         GrGLSLVertToFrag v(kVec2f_GrSLType);
         varyingHandler->addVarying("TextureCoords", &v);
-        vertBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", v.vsOut(),
-                                 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
-                                 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight,
+        vertBuilder->codeAppendf("%s = %s;", v.vsOut(),
                                  cte.inTextureCoords()->fName);
 
         GrGLSLPPFragmentBuilder* fragBuilder = args.fFragBuilder;
@@ -150,7 +146,7 @@ GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color, GrTexture* texture,
         fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
     }
     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
-                                                        kVec2s_GrVertexAttribType));
+                                                        kVec2us_GrVertexAttribType));
     this->addTextureAccess(&fTextureAccess);
 }
 
index 50e78cc..dc01b62 100644 (file)
@@ -78,23 +78,20 @@ public:
 
         // add varyings
         GrGLSLVertToFrag recipScale(kFloat_GrSLType);
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        GrGLSLVertToFrag uv(kVec2f_GrSLType);
         bool isSimilarity = SkToBool(dfTexEffect.getFlags() & kSimilarity_DistanceFieldEffectFlag);
-        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
+        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
 
         // compute numbers to be hardcoded to convert texture coordinates from int to float
         SkASSERT(dfTexEffect.numTextures() == 1);
         GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture();
         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-        SkScalar recipWidth = 1.0f / atlas->width();
-        SkScalar recipHeight = 1.0f / atlas->height();
 
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(),
-                                 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
-                                 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight,
+        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(),
+                                 atlas->width(), atlas->height(),
                                  dfTexEffect.inTextureCoords()->fName);
         
         // Use highp to work around aliasing issues
@@ -224,7 +221,7 @@ GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(GrColor color,
                                                    kHigh_GrSLPrecision));
     fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
-                                                          kVec2s_GrVertexAttribType));
+                                                          kVec2us_GrVertexAttribType));
     this->addTextureAccess(&fTextureAccess);
 }
 
@@ -522,22 +519,19 @@ public:
         // set up varyings
         bool isUniformScale = SkToBool(dfTexEffect.getFlags() & kUniformScale_DistanceFieldEffectMask);
         GrGLSLVertToFrag recipScale(kFloat_GrSLType);
-        GrGLSLVertToFrag st(kVec2f_GrSLType);
-        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = %s;", st.vsOut(), dfTexEffect.inTextureCoords()->fName);
+        GrGLSLVertToFrag uv(kVec2f_GrSLType);
+        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = %s;", uv.vsOut(), dfTexEffect.inTextureCoords()->fName);
 
         // compute numbers to be hardcoded to convert texture coordinates from int to float
         SkASSERT(dfTexEffect.numTextures() == 1);
         GrTexture* atlas = dfTexEffect.textureAccess(0).getTexture();
         SkASSERT(atlas && SkIsPow2(atlas->width()) && SkIsPow2(atlas->height()));
-        SkScalar recipWidth = 1.0f / atlas->width();
-        SkScalar recipHeight = 1.0f / atlas->height();
 
-        GrGLSLVertToFrag uv(kVec2f_GrSLType);
-        varyingHandler->addVarying("TextureCoords", &uv, kHigh_GrSLPrecision);
-        vertBuilder->codeAppendf("%s = vec2(%.*f, %.*f) * %s;", uv.vsOut(),
-                                 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipWidth,
-                                 GR_SIGNIFICANT_POW2_DECIMAL_DIG, recipHeight,
+        GrGLSLVertToFrag st(kVec2f_GrSLType);
+        varyingHandler->addVarying("IntTextureCoords", &st, kHigh_GrSLPrecision);
+        vertBuilder->codeAppendf("%s = vec2(%d, %d) * %s;", st.vsOut(),
+                                 atlas->width(), atlas->height(),
                                  dfTexEffect.inTextureCoords()->fName);
 
         // add frag shader code
@@ -708,7 +702,7 @@ GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
                                                    kHigh_GrSLPrecision));
     fInColor = &this->addVertexAttrib(Attribute("inColor", kVec4ub_GrVertexAttribType));
     fInTextureCoords = &this->addVertexAttrib(Attribute("inTextureCoords",
-                                                        kVec2s_GrVertexAttribType));
+                                                        kVec2us_GrVertexAttribType));
     this->addTextureAccess(&fTextureAccess);
 }
 
index 2048e2c..8f3262d 100644 (file)
@@ -21,7 +21,7 @@ static const AttribLayout gLayouts[kGrVertexAttribTypeCount] = {
     {4, GR_GL_FLOAT, false},         // kVec4f_GrVertexAttribType
     {1, GR_GL_UNSIGNED_BYTE, true},  // kUByte_GrVertexAttribType
     {4, GR_GL_UNSIGNED_BYTE, true},  // kVec4ub_GrVertexAttribType
-    {2, GR_GL_SHORT, false},         // kVec2s_GrVertexAttribType
+    {2, GR_GL_UNSIGNED_SHORT, true},         // kVec2s_GrVertexAttribType
     {1, GR_GL_INT, false},           // kInt_GrVertexAttribType
     {1, GR_GL_UNSIGNED_INT, false},  // kUint_GrVertexAttribType
 };
@@ -32,7 +32,7 @@ GR_STATIC_ASSERT(2 == kVec3f_GrVertexAttribType);
 GR_STATIC_ASSERT(3 == kVec4f_GrVertexAttribType);
 GR_STATIC_ASSERT(4 == kUByte_GrVertexAttribType);
 GR_STATIC_ASSERT(5 == kVec4ub_GrVertexAttribType);
-GR_STATIC_ASSERT(6 == kVec2s_GrVertexAttribType);
+GR_STATIC_ASSERT(6 == kVec2us_GrVertexAttribType);
 GR_STATIC_ASSERT(7 == kInt_GrVertexAttribType);
 GR_STATIC_ASSERT(8 == kUint_GrVertexAttribType);
 
index 14bf4a5..18eb23c 100644 (file)
@@ -21,6 +21,7 @@
 template <bool regenPos, bool regenCol, bool regenTexCoords>
 inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexStride,
                            bool useDistanceFields, SkScalar transX, SkScalar transY,
+                           int32_t log2Width, int32_t log2Height,
                            GrColor color) {
     int u0, v0, u1, v1;
     if (regenTexCoords) {
@@ -39,6 +40,20 @@ inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
             u1 = u0 + width;
             v1 = v0 + height;
         }
+
+        // normalize
+        u0 *= 65535;
+        u0 >>= log2Width;
+        u1 *= 65535;
+        u1 >>= log2Width;
+        v0 *= 65535;
+        v0 >>= log2Height;
+        v1 *= 65535;
+        v1 >>= log2Height;
+        SkASSERT(u0 >= 0 && u0 <= 65535);
+        SkASSERT(u1 >= 0 && u1 <= 65535);
+        SkASSERT(v0 >= 0 && v0 <= 65535);
+        SkASSERT(v1 >= 0 && v1 <= 65535);
     }
 
     // This is a bit wonky, but sometimes we have LCD text, in which case we won't have color
@@ -59,8 +74,9 @@ inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
     }
 
     if (regenTexCoords) {
-        SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
-        textureCoords->set(u0, v0);
+        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
+        textureCoords[0] = (uint16_t) u0;
+        textureCoords[1] = (uint16_t) v0;
     }
     vertex += vertexStride;
 
@@ -77,8 +93,9 @@ inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
     }
 
     if (regenTexCoords) {
-        SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
-        textureCoords->set(u0, v1);
+        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
+        textureCoords[0] = (uint16_t)u0;
+        textureCoords[1] = (uint16_t)v1;
     }
     vertex += vertexStride;
 
@@ -95,8 +112,9 @@ inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
     }
 
     if (regenTexCoords) {
-        SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
-        textureCoords->set(u1, v1);
+        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
+        textureCoords[0] = (uint16_t)u1;
+        textureCoords[1] = (uint16_t)v1;
     }
     vertex += vertexStride;
 
@@ -113,8 +131,9 @@ inline void regen_vertices(intptr_t vertex, const GrGlyph* glyph, size_t vertexS
     }
 
     if (regenTexCoords) {
-        SkIPoint16* textureCoords = reinterpret_cast<SkIPoint16*>(vertex + texCoordOffset);
-        textureCoords->set(u1, v0);
+        uint16_t* textureCoords = reinterpret_cast<uint16_t*>(vertex + texCoordOffset);
+        textureCoords[0] = (uint16_t)u1;
+        textureCoords[1] = (uint16_t)v0;
     }
 }
 
@@ -161,6 +180,7 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
     bool brokenRun = false;
     for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
         GrGlyph* glyph = nullptr;
+        int log2Width = 0, log2Height = 0;
         if (regenTexCoords) {
             size_t glyphOffset = glyphIdx + info->glyphStartIndex();
 
@@ -187,6 +207,8 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
             }
             fontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph,
                                                     target->currentToken());
+            log2Width = fontCache->log2Width(info->maskFormat());
+            log2Height = fontCache->log2Height(info->maskFormat());
         }
 
         intptr_t vertex = reinterpret_cast<intptr_t>(fVertices);
@@ -194,7 +216,7 @@ void GrAtlasTextBlob::regenInBatch(GrDrawBatch::Target* target,
         vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph;
         regen_vertices<regenPos, regenCol, regenTexCoords>(vertex, glyph, vertexStride,
                                                            info->drawAsDistanceFields(), transX,
-                                                           transY, color);
+                                                           transY, log2Width, log2Height, color);
         helper->incGlyphCount();
     }
 
index ad76e4d..d99df1d 100644 (file)
@@ -48,16 +48,22 @@ GrBatchFontCache::GrBatchFontCache(GrContext* context)
     // setup default atlas configs
     fAtlasConfigs[kA8_GrMaskFormat].fWidth = 2048;
     fAtlasConfigs[kA8_GrMaskFormat].fHeight = 2048;
+    fAtlasConfigs[kA8_GrMaskFormat].fLog2Width = 11;
+    fAtlasConfigs[kA8_GrMaskFormat].fLog2Height = 11;
     fAtlasConfigs[kA8_GrMaskFormat].fPlotWidth = 512;
     fAtlasConfigs[kA8_GrMaskFormat].fPlotHeight = 256;
 
     fAtlasConfigs[kA565_GrMaskFormat].fWidth = 1024;
     fAtlasConfigs[kA565_GrMaskFormat].fHeight = 2048;
+    fAtlasConfigs[kA565_GrMaskFormat].fLog2Width = 10;
+    fAtlasConfigs[kA565_GrMaskFormat].fLog2Height = 11;
     fAtlasConfigs[kA565_GrMaskFormat].fPlotWidth = 256;
     fAtlasConfigs[kA565_GrMaskFormat].fPlotHeight = 256;
 
     fAtlasConfigs[kARGB_GrMaskFormat].fWidth = 1024;
     fAtlasConfigs[kARGB_GrMaskFormat].fHeight = 2048;
+    fAtlasConfigs[kARGB_GrMaskFormat].fLog2Width = 10;
+    fAtlasConfigs[kARGB_GrMaskFormat].fLog2Height = 11;
     fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = 256;
     fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = 256;
 }
index 46ab1c8..7ff1b9e 100644 (file)
@@ -171,6 +171,9 @@ public:
         return this->getAtlas(format)->atlasGeneration();
     }
 
+    int log2Width(GrMaskFormat format) { return fAtlasConfigs[format].fLog2Width; }
+    int log2Height(GrMaskFormat format) { return fAtlasConfigs[format].fLog2Height; }
+
     ///////////////////////////////////////////////////////////////////////////
     // Functions intended debug only
     void dump() const;