Use float textures to render gradients when possible

Float textures offer better precision for dithering.

In addition this change removes two uniforms from gradient shaders.
These uniforms were used to dither gradients but their value is
a build time constant. Instead we hardcode the value directly in
the shader source at compile time.

Change-Id: I05e9fd3eef93771843bbd91b453274452dfaefee
diff --git a/libs/hwui/Dither.cpp b/libs/hwui/Dither.cpp
index e80b325..9bc5c14 100644
--- a/libs/hwui/Dither.cpp
+++ b/libs/hwui/Dither.cpp
@@ -21,38 +21,46 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
-// Defines
-///////////////////////////////////////////////////////////////////////////////
-
-// Must be a power of two
-#define DITHER_KERNEL_SIZE 4
-
-///////////////////////////////////////////////////////////////////////////////
 // Lifecycle
 ///////////////////////////////////////////////////////////////////////////////
 
 void Dither::bindDitherTexture() {
     if (!mInitialized) {
-        const uint8_t pattern[] = {
-             0,  8,  2, 10,
-            12,  4, 14,  6,
-             3, 11,  1,  9,
-            15,  7, 13,  5
-        };
+        bool useFloatTexture = Extensions::getInstance().getMajorGlVersion() >= 3;
 
         glGenTextures(1, &mDitherTexture);
         glBindTexture(GL_TEXTURE_2D, mDitherTexture);
 
-        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
-
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
 
-        glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
-                GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+        if (useFloatTexture) {
+            float dither = 1.0f / (255.0f * DITHER_KERNEL_SIZE * DITHER_KERNEL_SIZE);
+            const GLfloat pattern[] = {
+                 0 * dither,  8 * dither,  2 * dither, 10 * dither,
+                12 * dither,  4 * dither, 14 * dither,  6 * dither,
+                 3 * dither, 11 * dither,  1 * dither,  9 * dither,
+                15 * dither,  7 * dither, 13 * dither,  5 * dither
+            };
+
+            glPixelStorei(GL_UNPACK_ALIGNMENT, sizeof(GLfloat));
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+                    GL_RED, GL_FLOAT, &pattern);
+        } else {
+            const uint8_t pattern[] = {
+                 0,  8,  2, 10,
+                12,  4, 14,  6,
+                 3, 11,  1,  9,
+                15,  7, 13,  5
+            };
+
+            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, DITHER_KERNEL_SIZE, DITHER_KERNEL_SIZE, 0,
+                    GL_ALPHA, GL_UNSIGNED_BYTE, &pattern);
+        }
 
         mInitialized = true;
     } else {
@@ -76,10 +84,7 @@
 
     bindDitherTexture();
 
-    float ditherSize = 1.0f / DITHER_KERNEL_SIZE;
     glUniform1i(program->getUniform("ditherSampler"), textureSlot);
-    glUniform1f(program->getUniform("ditherSize"), ditherSize);
-    glUniform1f(program->getUniform("ditherSizeSquared"), ditherSize * ditherSize);
 }
 
 }; // namespace uirenderer