Add new method for storing DrawOpAtlas texture index.

Storing the texture index in the lower bit of each texture coordinate
seems to have issues on certain iOS devices. Rather than do that, we
use the sign of the texture coordinate to act as our storage bit.
To manage encoding 0 we map [0, N] to [-1, -N-1] to represent a bit.

Change-Id: Ic588ee92cf858915a1833cf482d4b23bd11c1000
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/263561
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 90f3f3b..7a41cac 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -192,17 +192,22 @@
             // In the LCD case the color will be garbage, but we'll overwrite it with the texcoords
             // and it avoids a lot of conditionals.
             auto color = *reinterpret_cast<const SkColor*>(blobVertices + sizeof(SkPoint));
-            size_t coordOffset = vertexStride - 2*sizeof(uint16_t);
-            auto* blobCoordsLT = reinterpret_cast<const uint16_t*>(blobVertices + coordOffset);
-            auto* blobCoordsRB = reinterpret_cast<const uint16_t*>(blobVertices + 3 * vertexStride +
+            size_t coordOffset = vertexStride - 2*sizeof(int16_t);
+            auto* blobCoordsLT = reinterpret_cast<const int16_t*>(blobVertices + coordOffset);
+            auto* blobCoordsRB = reinterpret_cast<const int16_t*>(blobVertices + 3 * vertexStride +
                                                                    coordOffset);
             // Pull out the texel coordinates and texture index bits
-            uint16_t coordsRectL = blobCoordsLT[0] >> 1;
-            uint16_t coordsRectT = blobCoordsLT[1] >> 1;
-            uint16_t coordsRectR = blobCoordsRB[0] >> 1;
-            uint16_t coordsRectB = blobCoordsRB[1] >> 1;
-            uint16_t pageIndexX = blobCoordsLT[0] & 0x1;
-            uint16_t pageIndexY = blobCoordsLT[1] & 0x1;
+            int16_t coordsRectL = blobCoordsLT[0];
+            int16_t coordsRectT = blobCoordsLT[1];
+            int16_t coordsRectR = blobCoordsRB[0];
+            int16_t coordsRectB = blobCoordsRB[1];
+            int index0, index1;
+
+            std::tie(coordsRectL, coordsRectT, index0) =
+                    GrDrawOpAtlas::UnpackIndexFromTexCoords(coordsRectL, coordsRectT);
+            std::tie(coordsRectR, coordsRectB, index1) =
+                    GrDrawOpAtlas::UnpackIndexFromTexCoords(coordsRectR, coordsRectB);
+            SkASSERT(index0 == index1);
 
             int positionRectWidth = positionRect.width();
             int positionRectHeight = positionRect.height();
@@ -228,10 +233,10 @@
             positionRect.fBottom -= delta;
 
             // Repack texel coordinates and index
-            coordsRectL = coordsRectL << 1 | pageIndexX;
-            coordsRectT = coordsRectT << 1 | pageIndexY;
-            coordsRectR = coordsRectR << 1 | pageIndexX;
-            coordsRectB = coordsRectB << 1 | pageIndexY;
+            std::tie(coordsRectL, coordsRectT) =
+                    GrDrawOpAtlas::PackIndexInTexCoords(coordsRectL, coordsRectT, index0);
+            std::tie(coordsRectR, coordsRectB) =
+                    GrDrawOpAtlas::PackIndexInTexCoords(coordsRectR, coordsRectB, index1);
 
             // Set new positions and coords
             SkPoint* currPosition = reinterpret_cast<SkPoint*>(currVertex);