Fix validation of ReadPixels format and type.

The validation for ReadPixels allows for two combations of format/type:
  1. Based on the current framebuffer's component type.
    * GL_RGBA/GL_UNSIGNED_BYTE if the framebuffer is a normalized (signed
      or unsigned).
    * GL_RGBA_INTEGER/GL_INTEGER if the framebuffer is an
      integer format.
    * GL_RGBA_INTEGER/GL_UNSIGNED_INTEGER if the framebuffer is an
      unsigned integer format.
    * GL_RGBA/GL_FLOAT if the framebuffer is any type of float
      framebuffer (added in EXT_color_buffer_float).
    * These combations are detailed in the ES2 spec on pg 105 or ES3 on pg
      193.
  2. The implementation read format/type returned from glGetIntegerv.
    * These formats are added by specs, OES_texture_float, EXT_texture_rg,
      EXT_read_format_bgra, etc.

Update the GL and D3D backends to perform the conversion from GL_HALF_FLOAT
to GL_HALF_FLOAT_OES.

Continue allowing reading as BGRA_EXT to support Skia.  Should be removed in
the future.

BUG=607283
BUG=angleproject:1478

Change-Id: I0312cad4d5f138ab036f383d221f8ccd19a77f6d
Reviewed-on: https://chromium-review.googlesource.com/346232
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index 0d52428..067b224 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -352,6 +352,26 @@
             (luminanceBits + alphaBits) > 0);
 }
 
+GLenum InternalFormat::getReadPixelsFormat() const
+{
+    return format;
+}
+
+GLenum InternalFormat::getReadPixelsType() const
+{
+    switch (type)
+    {
+        case GL_HALF_FLOAT:
+            // The internal format may have a type of GL_HALF_FLOAT but when exposing this type as
+            // the IMPLEMENTATION_READ_TYPE, only HALF_FLOAT_OES is allowed by
+            // OES_texture_half_float
+            return GL_HALF_FLOAT_OES;
+
+        default:
+            return type;
+    }
+}
+
 Format::Format(GLenum internalFormat) : Format(GetInternalFormatInfo(internalFormat))
 {
 }
diff --git a/src/libANGLE/formatutils.h b/src/libANGLE/formatutils.h
index 24956c6..b5dc6a4 100644
--- a/src/libANGLE/formatutils.h
+++ b/src/libANGLE/formatutils.h
@@ -76,6 +76,8 @@
                                                    const gl::PixelUnpackState &unpack,
                                                    bool applySkipImages) const;
     bool isLUMA() const;
+    GLenum getReadPixelsFormat() const;
+    GLenum getReadPixelsType() const;
 
     bool operator==(const InternalFormat &other) const;
     bool operator!=(const InternalFormat &other) const;
diff --git a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
index a45c945..a272264 100644
--- a/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -207,7 +207,7 @@
     GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
     const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
 
-    return implementationFormatInfo.format;
+    return implementationFormatInfo.getReadPixelsFormat();
 }
 
 GLenum FramebufferD3D::getImplementationColorReadType() const
@@ -229,7 +229,7 @@
     GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
     const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
 
-    return implementationFormatInfo.type;
+    return implementationFormatInfo.getReadPixelsType();
 }
 
 gl::Error FramebufferD3D::readPixels(ContextImpl *context,
diff --git a/src/libANGLE/renderer/gl/FramebufferGL.cpp b/src/libANGLE/renderer/gl/FramebufferGL.cpp
index 4606114..8d84c60 100644
--- a/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -21,6 +21,7 @@
 #include "libANGLE/renderer/gl/StateManagerGL.h"
 #include "libANGLE/renderer/gl/TextureGL.h"
 #include "libANGLE/renderer/gl/WorkaroundsGL.h"
+#include "libANGLE/renderer/gl/formatutilsgl.h"
 #include "platform/Platform.h"
 
 using namespace gl;
@@ -212,14 +213,14 @@
 {
     const auto *readAttachment = mState.getReadAttachment();
     const Format &format       = readAttachment->getFormat();
-    return format.info->format;
+    return format.info->getReadPixelsFormat();
 }
 
 GLenum FramebufferGL::getImplementationColorReadType() const
 {
     const auto *readAttachment = mState.getReadAttachment();
     const Format &format       = readAttachment->getFormat();
-    return format.info->type;
+    return format.info->getReadPixelsType();
 }
 
 Error FramebufferGL::readPixels(ContextImpl *context,
@@ -234,7 +235,11 @@
     mStateManager->setPixelPackState(packState);
 
     mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
-    mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
+
+    nativegl::ReadPixelsFormat readPixelsFormat =
+        nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
+    mFunctions->readPixels(area.x, area.y, area.width, area.height, readPixelsFormat.format,
+                           readPixelsFormat.type, pixels);
 
     return Error(GL_NO_ERROR);
 }
diff --git a/src/libANGLE/renderer/gl/formatutilsgl.cpp b/src/libANGLE/renderer/gl/formatutilsgl.cpp
index 1688be1..c5219b4 100644
--- a/src/libANGLE/renderer/gl/formatutilsgl.cpp
+++ b/src/libANGLE/renderer/gl/formatutilsgl.cpp
@@ -438,6 +438,32 @@
     return result;
 }
 
+static GLenum GetNativeReadType(const FunctionsGL *functions,
+                                const WorkaroundsGL &workarounds,
+                                GLenum type)
+{
+    GLenum result = type;
+
+    if (functions->standard == STANDARD_GL_DESKTOP)
+    {
+        if (type == GL_HALF_FLOAT_OES)
+        {
+            // The enums differ for the OES half float extensions and desktop GL spec. Update it.
+            result = GL_HALF_FLOAT;
+        }
+    }
+
+    return result;
+}
+
+static GLenum GetNativeReadFormat(const FunctionsGL *functions,
+                                  const WorkaroundsGL &workarounds,
+                                  GLenum format)
+{
+    GLenum result = format;
+    return result;
+}
+
 TexImageFormat GetTexImageFormat(const FunctionsGL *functions,
                                  const WorkaroundsGL &workarounds,
                                  GLenum internalFormat,
@@ -512,6 +538,16 @@
         GetNativeInternalFormat(functions, workarounds, internalFormat, internalFormat);
     return result;
 }
+ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions,
+                                     const WorkaroundsGL &workarounds,
+                                     GLenum format,
+                                     GLenum type)
+{
+    ReadPixelsFormat result;
+    result.format = GetNativeReadFormat(functions, workarounds, format);
+    result.type   = GetNativeReadType(functions, workarounds, type);
+    return result;
+}
 }
 
 }
diff --git a/src/libANGLE/renderer/gl/formatutilsgl.h b/src/libANGLE/renderer/gl/formatutilsgl.h
index 547d478..616f37a 100644
--- a/src/libANGLE/renderer/gl/formatutilsgl.h
+++ b/src/libANGLE/renderer/gl/formatutilsgl.h
@@ -112,6 +112,16 @@
 RenderbufferFormat GetRenderbufferFormat(const FunctionsGL *functions,
                                          const WorkaroundsGL &workarounds,
                                          GLenum internalFormat);
+
+struct ReadPixelsFormat
+{
+    GLenum format;
+    GLenum type;
+};
+ReadPixelsFormat GetReadPixelsFormat(const FunctionsGL *functions,
+                                     const WorkaroundsGL &workarounds,
+                                     GLenum format,
+                                     GLenum type);
 }
 
 }
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 0846f0d..d204d67 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -99,6 +99,38 @@
     return true;
 }
 
+bool ValidReadPixelsFormatType(ValidationContext *context,
+                               GLenum framebufferComponentType,
+                               GLenum format,
+                               GLenum type)
+{
+    switch (framebufferComponentType)
+    {
+        case GL_UNSIGNED_NORMALIZED:
+            // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
+            // ReadPixels with BGRA even if the extension is not present
+            return (format == GL_RGBA && type == GL_UNSIGNED_BYTE) ||
+                   (context->getExtensions().readFormatBGRA && format == GL_BGRA_EXT &&
+                    type == GL_UNSIGNED_BYTE);
+
+        case GL_SIGNED_NORMALIZED:
+            return (format == GL_RGBA && type == GL_UNSIGNED_BYTE);
+
+        case GL_INT:
+            return (format == GL_RGBA_INTEGER && type == GL_INT);
+
+        case GL_UNSIGNED_INT:
+            return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
+
+        case GL_FLOAT:
+            return (format == GL_RGBA && type == GL_FLOAT);
+
+        default:
+            UNREACHABLE();
+            return false;
+    }
+}
+
 }  // anonymous namespace
 
 bool ValidCap(const Context *context, GLenum cap)
@@ -1122,12 +1154,12 @@
     GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
     GLenum currentType = framebuffer->getImplementationColorReadType();
     GLenum currentInternalFormat = readBuffer->getFormat().asSized();
-    GLuint clientVersion         = context->getClientMajorVersion();
 
-    bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
-                                                 ValidES3ReadFormatType(context, currentInternalFormat, format, type);
+    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(currentInternalFormat);
+    bool validFormatTypeCombination =
+        ValidReadPixelsFormatType(context, internalFormatInfo.componentType, format, type);
 
-    if (!(currentFormat == format && currentType == type) && !validReadFormat)
+    if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
     {
         context->handleError(Error(GL_INVALID_OPERATION));
         return false;
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 68285ce..e329fd0 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -1187,52 +1187,6 @@
     return true;
 }
 
-// check for combinations of format and type that are valid for ReadPixels
-bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type)
-{
-    switch (format)
-    {
-      case GL_RGBA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-            break;
-          default:
-            return false;
-        }
-        break;
-      case GL_BGRA_EXT:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
-            break;
-          default:
-            return false;
-        }
-        break;
-      case GL_RG_EXT:
-      case GL_RED_EXT:
-        if (!context->getExtensions().textureRG)
-        {
-            return false;
-        }
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-            break;
-          default:
-            return false;
-        }
-        break;
-
-      default:
-        return false;
-    }
-    return true;
-}
-
 bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
                                    const GLenum *attachments)
 {
diff --git a/src/libANGLE/validationES2.h b/src/libANGLE/validationES2.h
index 1ebb262..4e6be10 100644
--- a/src/libANGLE/validationES2.h
+++ b/src/libANGLE/validationES2.h
@@ -38,8 +38,6 @@
 bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
                                                    GLsizei width, GLsizei height);
 
-bool ValidES2ReadFormatType(ValidationContext *context, GLenum format, GLenum type);
-
 bool ValidateDiscardFramebufferEXT(Context *context, GLenum target, GLsizei numAttachments,
                                    const GLenum *attachments);
 
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index c6f645c..c891563 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -204,6 +204,7 @@
     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT32_OES,  GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8_OES         );
     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT,        GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT                );
     InsertES3FormatCombo(&set, GL_DEPTH_COMPONENT,        GL_DEPTH_COMPONENT, GL_UNSIGNED_INT                  );
+    // clang-format on
 
     // From GL_EXT_texture_norm16
     InsertES3FormatCombo(&set, GL_R16_EXT, GL_RED, GL_UNSIGNED_SHORT);
@@ -214,7 +215,6 @@
     InsertES3FormatCombo(&set, GL_RG16_SNORM_EXT, GL_RG, GL_SHORT);
     InsertES3FormatCombo(&set, GL_RGB16_SNORM_EXT, GL_RGB, GL_SHORT);
     InsertES3FormatCombo(&set, GL_RGBA16_SNORM_EXT, GL_RGBA, GL_SHORT);
-    // clang-format on
 
     return set;
 }
@@ -1271,100 +1271,6 @@
     return true;
 }
 
-bool ValidES3ReadFormatType(ValidationContext *context,
-                            GLenum internalFormat,
-                            GLenum format,
-                            GLenum type)
-{
-    const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
-
-    switch (format)
-    {
-      case GL_RGBA:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-            break;
-          case GL_UNSIGNED_SHORT:
-              if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
-                  internalFormatInfo.type != GL_UNSIGNED_SHORT)
-              {
-                  return false;
-              }
-              break;
-          case GL_UNSIGNED_INT_2_10_10_10_REV:
-            if (internalFormat != GL_RGB10_A2)
-            {
-                return false;
-            }
-            break;
-          case GL_FLOAT:
-            if (internalFormatInfo.componentType != GL_FLOAT)
-            {
-                return false;
-            }
-            break;
-          default:
-            return false;
-        }
-        break;
-      case GL_RGBA_INTEGER:
-        switch (type)
-        {
-          case GL_INT:
-            if (internalFormatInfo.componentType != GL_INT)
-            {
-                return false;
-            }
-            break;
-          case GL_UNSIGNED_INT:
-            if (internalFormatInfo.componentType != GL_UNSIGNED_INT)
-            {
-                return false;
-            }
-            break;
-          default:
-            return false;
-        }
-        break;
-      case GL_BGRA_EXT:
-        switch (type)
-        {
-          case GL_UNSIGNED_BYTE:
-          case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
-          case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
-            break;
-          default:
-            return false;
-        }
-        break;
-      case GL_RG_EXT:
-      case GL_RED_EXT:
-        if (!context->getExtensions().textureRG)
-        {
-            return false;
-        }
-        switch (type)
-        {
-        case GL_UNSIGNED_BYTE:
-            break;
-        case GL_UNSIGNED_SHORT:
-            if (internalFormatInfo.componentType != GL_UNSIGNED_NORMALIZED &&
-                internalFormatInfo.type != GL_UNSIGNED_SHORT)
-            {
-                return false;
-            }
-            break;
-        default:
-            return false;
-        }
-        break;
-      default:
-        return false;
-    }
-    return true;
-}
-
 bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
                                               GLenum internalformat, GLsizei width, GLsizei height)
 {
diff --git a/src/libANGLE/validationES3.h b/src/libANGLE/validationES3.h
index eeef800..7e8712b 100644
--- a/src/libANGLE/validationES3.h
+++ b/src/libANGLE/validationES3.h
@@ -153,11 +153,6 @@
 bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment,
                                      GLuint texture, GLint level, GLint layer);
 
-bool ValidES3ReadFormatType(ValidationContext *context,
-                            GLenum internalFormat,
-                            GLenum format,
-                            GLenum type);
-
 bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
                                               GLenum internalformat, GLsizei width, GLsizei height);
 
diff --git a/src/tests/gl_tests/BlendMinMaxTest.cpp b/src/tests/gl_tests/BlendMinMaxTest.cpp
index 8ccaf92..39f5251 100644
--- a/src/tests/gl_tests/BlendMinMaxTest.cpp
+++ b/src/tests/gl_tests/BlendMinMaxTest.cpp
@@ -32,13 +32,12 @@
         float values[4];
     };
 
-    static GLubyte getExpected(bool blendMin, float curColor, GLubyte prevColor)
+    static float getExpected(bool blendMin, float curColor, float prevColor)
     {
-        GLubyte curAsUbyte = static_cast<GLubyte>((curColor * std::numeric_limits<GLubyte>::max()) + 0.5f);
-        return blendMin ? std::min<GLubyte>(curAsUbyte, prevColor) : std::max<GLubyte>(curAsUbyte, prevColor);
+        return blendMin ? std::min(curColor, prevColor) : std::max(curColor, prevColor);
     }
 
-    void runTest(GLenum colorFormat)
+    void runTest(GLenum colorFormat, GLenum type)
     {
         if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_blend_minmax"))
         {
@@ -55,17 +54,26 @@
 
         SetUpFramebuffer(colorFormat);
 
-        const size_t colorCount = 1024;
+        int minValue = 0;
+        int maxValue = 1;
+        if (type == GL_FLOAT)
+        {
+            minValue = -1024;
+            maxValue = 1024;
+        }
+
+        const size_t colorCount = 128;
         Color colors[colorCount];
         for (size_t i = 0; i < colorCount; i++)
         {
             for (size_t j = 0; j < 4; j++)
             {
-                colors[i].values[j] = (rand() % 255) / 255.0f;
+                colors[i].values[j] =
+                    static_cast<float>(minValue + (rand() % (maxValue - minValue)));
             }
         }
 
-        GLubyte prevColor[4];
+        float prevColor[4];
         for (size_t i = 0; i < colorCount; i++)
         {
             const Color &color = colors[i];
@@ -77,16 +85,37 @@
 
             drawQuad(mProgram, "aPosition", 0.5f);
 
-            if (i > 0)
+            float pixel[4];
+            if (type == GL_UNSIGNED_BYTE)
             {
-                EXPECT_PIXEL_EQ(0, 0,
-                                getExpected(blendMin, color.values[0], prevColor[0]),
-                                getExpected(blendMin, color.values[1], prevColor[1]),
-                                getExpected(blendMin, color.values[2], prevColor[2]),
-                                getExpected(blendMin, color.values[3], prevColor[3]));
+                GLubyte ubytePixel[4];
+                glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, ubytePixel);
+                for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
+                {
+                    pixel[componentIdx] = ubytePixel[componentIdx] / 255.0f;
+                }
+            }
+            else if (type == GL_FLOAT)
+            {
+                glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
+            }
+            else
+            {
+                FAIL() << "Unexpected pixel type";
             }
 
-            glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, prevColor);
+            if (i > 0)
+            {
+                const float errorRange = 1.0f / 255.0f;
+                for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
+                {
+                    EXPECT_NEAR(
+                        getExpected(blendMin, color.values[componentIdx], prevColor[componentIdx]),
+                        pixel[componentIdx], errorRange);
+                }
+            }
+
+            memcpy(prevColor, pixel, sizeof(pixel));
         }
     }
 
@@ -142,6 +171,9 @@
         glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, getWindowWidth(), getWindowHeight());
         glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbuffer);
 
+        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+        glClear(GL_COLOR_BUFFER_BIT);
+
         ASSERT_GL_NO_ERROR();
     }
 
@@ -163,10 +195,10 @@
 
 TEST_P(BlendMinMaxTest, RGBA8)
 {
-    runTest(GL_RGBA8);
+    runTest(GL_RGBA8, GL_UNSIGNED_BYTE);
 }
 
-TEST_P(BlendMinMaxTest, RGBA32f)
+TEST_P(BlendMinMaxTest, RGBA32F)
 {
     if (getClientMajorVersion() < 3 || !extensionEnabled("GL_EXT_color_buffer_float"))
     {
@@ -189,7 +221,7 @@
         return;
     }
 
-    runTest(GL_RGBA32F);
+    runTest(GL_RGBA32F, GL_FLOAT);
 }
 
 TEST_P(BlendMinMaxTest, RGBA16F)
@@ -208,21 +240,16 @@
         return;
     }
 
-    // TODO(geofflang): This fails because readpixels with UNSIGNED_BYTE/RGBA does not work with
-    // half float buffers (http://anglebug.com/1288)
-    if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)
-    {
-        std::cout << "Test skipped on OpenGL ES targets." << std::endl;
-        return;
-    }
-
-    runTest(GL_RGBA16F);
+    runTest(GL_RGBA16F, GL_FLOAT);
 }
 
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(BlendMinMaxTest,
                        ES2_D3D9(),
                        ES2_D3D11(),
+                       ES3_D3D11(),
                        ES2_D3D11_FL9_3(),
                        ES2_OPENGL(),
-                       ES2_OPENGLES());
+                       ES3_OPENGL(),
+                       ES2_OPENGLES(),
+                       ES3_OPENGLES());
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
index ba045af..9d38ad7 100644
--- a/src/tests/gl_tests/TextureTest.cpp
+++ b/src/tests/gl_tests/TextureTest.cpp
@@ -14,24 +14,24 @@
 {
 
 // Take a pixel, and reset the components not covered by the format to default
-// values. In particular, the default value for the alpha component is 65535
+// values. In particular, the default value for the alpha component is 255
 // (1.0 as unsigned normalized fixed point value).
-GLColor16 SliceFormatColor16(GLenum format, GLColor16 full)
+GLColor SliceFormatColor(GLenum format, GLColor full)
 {
     switch (format)
     {
         case GL_RED:
-            return GLColor16(full.R, 0, 0, 65535u);
+            return GLColor(full.R, 0, 0, 255u);
         case GL_RG:
-            return GLColor16(full.R, full.G, 0, 65535u);
+            return GLColor(full.R, full.G, 0, 255u);
         case GL_RGB:
-            return GLColor16(full.R, full.G, full.B, 65535u);
+            return GLColor(full.R, full.G, full.B, 255u);
         case GL_RGBA:
             return full;
         default:
             UNREACHABLE();
+            return GLColor::white;
     }
-    return GLColor16::white;
 }
 
 class TexCoordDrawTest : public ANGLETest
@@ -3248,8 +3248,8 @@
 
     void testNorm16Texture(GLint internalformat, GLenum format, GLenum type)
     {
-        GLushort pixelValue = type == GL_SHORT ? 0x7FFF : 0x6A35;
-        GLColor16 imageData(pixelValue, pixelValue, pixelValue, pixelValue);
+        GLushort pixelValue  = (type == GL_SHORT) ? 0x7FFF : 0x6A35;
+        GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
 
         setUpProgram();
 
@@ -3261,20 +3261,17 @@
         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16_EXT, 1, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT, nullptr);
 
         glBindTexture(GL_TEXTURE_2D, mTextures[1]);
-        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, &imageData.R);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
 
         EXPECT_GL_NO_ERROR();
 
         drawQuad(mProgram, "position", 0.5f);
 
-        GLColor16 expectedValue = imageData;
-        if (type == GL_SHORT)
-        {
-            // sampled as signed value; then stored as unsigned value
-            expectedValue = GLColor16::white;
-        }
+        GLubyte expectedValue = (type == GL_SHORT) ? 0xFF : static_cast<GLubyte>(pixelValue >> 8);
 
-        EXPECT_PIXEL_COLOR16_EQ(0, 0, SliceFormatColor16(format, expectedValue));
+        EXPECT_PIXEL_COLOR_EQ(
+            0, 0, SliceFormatColor(
+                      format, GLColor(expectedValue, expectedValue, expectedValue, expectedValue)));
 
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
@@ -3284,7 +3281,7 @@
     void testNorm16Render(GLint internalformat, GLenum format, GLenum type)
     {
         GLushort pixelValue = 0x6A35;
-        GLColor16 imageData(pixelValue, pixelValue, pixelValue, pixelValue);
+        GLushort imageData[] = {pixelValue, pixelValue, pixelValue, pixelValue};
 
         setUpProgram();
 
@@ -3296,13 +3293,16 @@
                                0);
 
         glBindTexture(GL_TEXTURE_2D, mTextures[2]);
-        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, &imageData.R);
+        glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, format, type, imageData);
 
         EXPECT_GL_NO_ERROR();
 
         drawQuad(mProgram, "position", 0.5f);
 
-        EXPECT_PIXEL_COLOR16_EQ(0, 0, SliceFormatColor16(format, imageData));
+        GLubyte expectedValue = static_cast<GLubyte>(pixelValue >> 8);
+        EXPECT_PIXEL_COLOR_EQ(
+            0, 0, SliceFormatColor(
+                      format, GLColor(expectedValue, expectedValue, expectedValue, expectedValue)));
 
         glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
         glRenderbufferStorage(GL_RENDERBUFFER, internalformat, 1, 1);
@@ -3316,8 +3316,7 @@
 
         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
 
-        GLColor16 expectedValue = GLColor16::white;
-        EXPECT_PIXEL_COLOR16_EQ(0, 0, SliceFormatColor16(format, expectedValue));
+        EXPECT_PIXEL_COLOR_EQ(0, 0, SliceFormatColor(format, GLColor::white));
 
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
 
diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp
index 7bec1e1..d99c25e 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -30,8 +30,6 @@
 const GLColor GLColor::white            = GLColor(255u, 255u, 255u, 255u);
 const GLColor GLColor::yellow           = GLColor(255u, 255u, 0, 255u);
 
-const GLColor16 GLColor16::white = GLColor16(65535u, 65535u, 65535u, 65535u);
-
 namespace
 {
 float ColorNorm(GLubyte channelValue)
@@ -138,14 +136,6 @@
 {
 }
 
-GLColor::GLColor(const GLColor16 &color16)
-    : R(static_cast<GLubyte>(color16.R)),
-      G(static_cast<GLubyte>(color16.G)),
-      B(static_cast<GLubyte>(color16.B)),
-      A(static_cast<GLubyte>(color16.A))
-{
-}
-
 GLColor::GLColor(GLuint colorValue) : R(0), G(0), B(0), A(0)
 {
     memcpy(&R, &colorValue, sizeof(GLuint));
@@ -177,35 +167,6 @@
     return ostream;
 }
 
-GLColor16::GLColor16() : R(0), G(0), B(0), A(0)
-{
-}
-
-GLColor16::GLColor16(GLushort r, GLushort g, GLushort b, GLushort a) : R(r), G(g), B(b), A(a)
-{
-}
-
-GLColor16 ReadColor16(GLint x, GLint y)
-{
-    GLColor16 actual;
-    glReadPixels((x), (y), 1, 1, GL_RGBA, GL_UNSIGNED_SHORT, &actual.R);
-    EXPECT_GL_NO_ERROR();
-    return actual;
-}
-
-bool operator==(const GLColor16 &a, const GLColor16 &b)
-{
-    return a.R == b.R && a.G == b.G && a.B == b.B && a.A == b.A;
-}
-
-std::ostream &operator<<(std::ostream &ostream, const GLColor16 &color)
-{
-    ostream << "(" << static_cast<unsigned int>(color.R) << ", "
-            << static_cast<unsigned int>(color.G) << ", " << static_cast<unsigned int>(color.B)
-            << ", " << static_cast<unsigned int>(color.A) << ")";
-    return ostream;
-}
-
 }  // namespace angle
 
 // static
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index 73b69cd..ffe46fa 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -59,14 +59,11 @@
     static const GLColorRGB yellow;
 };
 
-struct GLColor16;
-
 struct GLColor
 {
     GLColor();
     GLColor(GLubyte r, GLubyte g, GLubyte b, GLubyte a);
     GLColor(const Vector4 &floatColor);
-    GLColor(const GLColor16 &color16);
     GLColor(GLuint colorValue);
 
     Vector4 toNormalizedVector() const;
@@ -95,28 +92,6 @@
 std::ostream &operator<<(std::ostream &ostream, const GLColor &color);
 GLColor ReadColor(GLint x, GLint y);
 
-struct GLColor16
-{
-    GLColor16();
-    GLColor16(GLushort r, GLushort g, GLushort b, GLushort a);
-
-    GLushort R, G, B, A;
-
-    static const GLColor16 white;
-};
-
-// Useful to cast any type to GLushort.
-template <typename TR, typename TG, typename TB, typename TA>
-GLColor16 MakeGLColor16(TR r, TG g, TB b, TA a)
-{
-    return GLColor16(static_cast<GLushort>(r), static_cast<GLushort>(g), static_cast<GLushort>(b),
-                     static_cast<GLushort>(a));
-}
-
-bool operator==(const GLColor16 &a, const GLColor16 &b);
-std::ostream &operator<<(std::ostream &ostream, const GLColor16 &color);
-GLColor16 ReadColor16(GLint x, GLint y);
-
 }  // namespace angle
 
 #define EXPECT_PIXEL_EQ(x, y, r, g, b, a) \
@@ -141,8 +116,6 @@
 #define EXPECT_PIXEL_COLOR_NEAR(x, y, angleColor, abs_error) \
     EXPECT_PIXEL_NEAR(x, y, angleColor.R, angleColor.G, angleColor.B, angleColor.A, abs_error)
 
-#define EXPECT_PIXEL_COLOR16_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor16(x, y))
-
 #define EXPECT_COLOR_NEAR(expected, actual, abs_error) \
     \
 {                                               \