Use high precision iterators on specific GPUs
Bug #5098359

Change-Id: I52ee8c7b4c9e8d4c7bedb684eaf7bef6c44c74b9
diff --git a/libs/hwui/Debug.h b/libs/hwui/Debug.h
index 5db73db..7cbb39d 100644
--- a/libs/hwui/Debug.h
+++ b/libs/hwui/Debug.h
@@ -20,6 +20,9 @@
 // Turn on to check for OpenGL errors on each frame
 #define DEBUG_OPENGL 1
 
+// Turn on to display informations about the GPU
+#define DEBUG_EXTENSIONS 0
+
 // Turn on to enable initialization information
 #define DEBUG_INIT 0
 
diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h
index eceb5c1..38d1130 100644
--- a/libs/hwui/Extensions.h
+++ b/libs/hwui/Extensions.h
@@ -23,6 +23,8 @@
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
+#include "Debug.h"
+
 namespace android {
 namespace uirenderer {
 
@@ -31,15 +33,20 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 // Debug
-#define DEBUG_EXTENSIONS 0
-
-// Debug
 #if DEBUG_EXTENSIONS
     #define EXT_LOGD(...) LOGD(__VA_ARGS__)
 #else
     #define EXT_LOGD(...)
 #endif
 
+// Vendor strings
+
+#define VENDOR_IMG "Imagination Technologies"
+
+///////////////////////////////////////////////////////////////////////////////
+// Classes
+///////////////////////////////////////////////////////////////////////////////
+
 class Extensions {
 public:
     Extensions() {
@@ -58,17 +65,21 @@
         } while (head);
 
         mHasNPot = hasExtension("GL_OES_texture_npot");
-        mHasDrawPath = hasExtension("GL_NV_draw_path");
-        mHasCoverageSample = hasExtension("GL_NV_coverage_sample");
         mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch");
 
+        const char* vendor = (const char*) glGetString(GL_VENDOR);
+        EXT_LOGD("Vendor: %s", vendor);
+        mNeedsHighpTexCoords = strcmp(vendor, VENDOR_IMG) == 0;
+
+        // We don't need to copy the string, the OpenGL ES spec
+        // guarantees the result of glGetString to point to a
+        // static string as long as our OpenGL context is valid
         mExtensions = buffer;
     }
 
     inline bool hasNPot() const { return mHasNPot; }
-    inline bool hasDrawPath() const { return mHasDrawPath; }
-    inline bool hasCoverageSample() const { return mHasCoverageSample; }
     inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
+    inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; }
 
     bool hasExtension(const char* extension) const {
         const String8 s(extension);
@@ -85,8 +96,7 @@
     const char* mExtensions;
 
     bool mHasNPot;
-    bool mHasDrawPath;
-    bool mHasCoverageSample;
+    bool mNeedsHighpTexCoords;
     bool mHasFramebufferFetch;
 }; // class Extensions
 
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index d419e3e..c2383f4 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -18,6 +18,7 @@
 
 #include <utils/String8.h>
 
+#include "Caches.h"
 #include "ProgramCache.h"
 
 namespace android {
@@ -64,10 +65,18 @@
 const char* gVS_Header_Varyings_IsAA =
         "varying float widthProportion;\n"
         "varying float lengthProportion;\n";
-const char* gVS_Header_Varyings_HasBitmap =
-        "varying vec2 outBitmapTexCoords;\n";
-const char* gVS_Header_Varyings_PointHasBitmap =
-        "varying vec2 outPointBitmapTexCoords;\n";
+const char* gVS_Header_Varyings_HasBitmap[2] = {
+        // Default precision
+        "varying vec2 outBitmapTexCoords;\n",
+        // High precision
+        "varying highp vec2 outBitmapTexCoords;\n"
+};
+const char* gVS_Header_Varyings_PointHasBitmap[2] = {
+        // Default precision
+        "varying vec2 outPointBitmapTexCoords;\n",
+        // High precision
+        "varying highp vec2 outPointBitmapTexCoords;\n"
+};
 const char* gVS_Header_Varyings_HasGradient[3] = {
         // Linear
         "varying vec2 linear;\n",
@@ -417,9 +426,10 @@
         shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
     }
     if (description.hasBitmap) {
+        int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0;
         shader.append(description.isPoint ?
-                gVS_Header_Varyings_PointHasBitmap :
-                gVS_Header_Varyings_HasBitmap);
+                gVS_Header_Varyings_PointHasBitmap[index] :
+                gVS_Header_Varyings_HasBitmap[index]);
     }
 
     // Begin the shader
@@ -455,7 +465,6 @@
 }
 
 String8 ProgramCache::generateFragmentShader(const ProgramDescription& description) {
-    // Set the default precision
     String8 shader;
 
     const bool blendFramebuffer = description.framebufferMode >= SkXfermode::kPlus_Mode;
@@ -479,9 +488,10 @@
         shader.append(gVS_Header_Varyings_HasGradient[description.gradientType]);
     }
     if (description.hasBitmap) {
+        int index = Caches::getInstance().extensions.needsHighpTexCoords() ? 1 : 0;
         shader.append(description.isPoint ?
-                gVS_Header_Varyings_PointHasBitmap :
-                gVS_Header_Varyings_HasBitmap);
+                gVS_Header_Varyings_PointHasBitmap[index] :
+                gVS_Header_Varyings_HasBitmap[index]);
     }
 
     // Uniforms