Re-land "D3D11: Fix readback of BGRA-backed formats."

For some BGRA-backed formats (RGBA4, R5G6B5, RGB5A1), our ReadPixels
implementation wasn't aware the BGRA format didn't exactly match the
RGBA format. For these it would do the 'fast path' memcpy method, when
it should stop and do the slow pixel-by-pixel packing method.

Fixes conformance2/reading/read-pixels-from-fbo-test.html.

Reland: fix empty format info that was causing us to only see the
first pixel in the FBO in a ReadPixels call. Also fix bugs in the
unorm 16-bit format readback code, and add ASSERTs to catch bugs in
subsequent new formats.

BUG=angleproject:1407
BUG=chromium:616176

Change-Id: I9fd55b9e1dd6a306eb4db195d775c02a1eb1f93f
Reviewed-on: https://chromium-review.googlesource.com/357132
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/common/angleutils.h b/src/common/angleutils.h
index 948fd08..3178dda 100644
--- a/src/common/angleutils.h
+++ b/src/common/angleutils.h
@@ -161,6 +161,7 @@
 #define snprintf _snprintf
 #endif
 
+#define GL_BGR565_ANGLEX 0x6ABB
 #define GL_BGRA4_ANGLEX 0x6ABC
 #define GL_BGR5_A1_ANGLEX 0x6ABD
 #define GL_INT_64_ANGLEX 0x6ABE
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
index c9533aa..3fd42d3 100644
--- a/src/libANGLE/formatutils.cpp
+++ b/src/libANGLE/formatutils.cpp
@@ -462,6 +462,9 @@
     map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX,      RGBAFormat( 4,  4,  4,  4, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
     map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX,    RGBAFormat( 5,  5,  5,  1, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExt<&Extensions::textureFormatBGRA8888>, RequireExt<&Extensions::textureFormatBGRA8888>, AlwaysSupported)));
 
+    // Special format which is not really supported, so always false for all supports.
+    map.insert(InternalFormatInfoPair(GL_BGR565_ANGLEX,     RGBAFormat( 5,  6,  5,  1, 0, GL_BGRA_EXT,     GL_UNSIGNED_SHORT_5_6_5,           GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported)));
+
     // Floating point renderability and filtering is provided by OES_texture_float and OES_texture_half_float
     //                               | Internal format     |          | D |S | Format             | Type                                   | Comp   | SRGB |  Texture supported | Renderable                  | Filterable                                    |
     //                               |                     |          |   |  |                    |                                        | type   |      |                    |                             |                                               |
@@ -610,12 +613,15 @@
 {
     FormatSet result;
 
-    const InternalFormatInfoMap &formats = GetInternalFormatMap();
-    for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++)
+    for (auto iter : GetInternalFormatMap())
     {
-        if (i->second.pixelBytes > 0)
+        if (iter.second.pixelBytes > 0)
         {
-            result.insert(i->first);
+            // TODO(jmadill): Fix this hack.
+            if (iter.first == GL_BGR565_ANGLEX)
+                continue;
+
+            result.insert(iter.first);
         }
     }
 
@@ -681,7 +687,7 @@
 const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
 {
     const InternalFormatInfoMap &formatMap = GetInternalFormatMap();
-    InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat);
+    auto iter                              = formatMap.find(internalFormat);
     if (iter != formatMap.end())
     {
         return iter->second;
@@ -689,6 +695,7 @@
     else
     {
         static const InternalFormat defaultInternalFormat;
+        UNREACHABLE();
         return defaultInternalFormat;
     }
 }
diff --git a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
index dee9488..d52fe3c 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -365,7 +365,8 @@
 GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
 {
     RenderTarget11 *renderTarget11 = GetAs<RenderTarget11>(renderTarget);
-    return d3d11::GetANGLEFormatSet(renderTarget11->getANGLEFormat()).glInternalFormat;
+    return d3d11::GetANGLEFormatSet(renderTarget11->getANGLEFormat())
+        .fboImplementationInternalFormat;
 }
 
 void Framebuffer11::updateColorRenderTarget(size_t colorIndex)
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 360b66b..83d54e2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -3729,6 +3729,7 @@
     int inputPitch  = static_cast<int>(mapping.RowPitch);
 
     const auto &angleFormatInfo = d3d11::GetANGLEFormatSet(textureHelper.getANGLEFormat());
+    ASSERT(angleFormatInfo.glInternalFormat != GL_NONE);
     const gl::InternalFormat &sourceFormatInfo =
         gl::GetInternalFormatInfo(angleFormatInfo.glInternalFormat);
     const auto &dxgiFormatInfo          = d3d11::GetDXGIFormatInfo(textureHelper.getFormat());
diff --git a/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py b/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
index b28a9ea..4fbaee2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
+++ b/src/libANGLE/renderer/d3d/d3d11/gen_texture_format_table.py
@@ -12,6 +12,7 @@
 import math
 import pprint
 import re
+import sys
 
 template_texture_format_table_autogen_h = """// GENERATED FILE - DO NOT EDIT.
 // Generated by gen_texture_format_table.py using data from texture_format_data.json
@@ -141,6 +142,7 @@
 ANGLEFormatSet::ANGLEFormatSet()
     : format(ANGLE_FORMAT_NONE),
       glInternalFormat(GL_NONE),
+      fboImplementationInternalFormat(GL_NONE),
       texFormat(DXGI_FORMAT_UNKNOWN),
       srvFormat(DXGI_FORMAT_UNKNOWN),
       rtvFormat(DXGI_FORMAT_UNKNOWN),
@@ -167,11 +169,12 @@
     // Gather all the load functions for this internal format
     loadFunctions = GetLoadFunctionsMap(internalFormat, formatSet->texFormat);
 
-    ASSERT(loadFunctions.size() != 0 || internalFormat == GL_NONE);
+    ASSERT(loadFunctions.size() != 0 || angleFormat == ANGLE_FORMAT_NONE);
 }}
 
 ANGLEFormatSet::ANGLEFormatSet(ANGLEFormat format,
                                GLenum glInternalFormat,
+                               GLenum fboImplementationInternalFormat,
                                DXGI_FORMAT texFormat,
                                DXGI_FORMAT srvFormat,
                                DXGI_FORMAT rtvFormat,
@@ -182,6 +185,7 @@
                                ColorReadFunction colorReadFunction)
     : format(format),
       glInternalFormat(glInternalFormat),
+      fboImplementationInternalFormat(fboImplementationInternalFormat),
       texFormat(texFormat),
       srvFormat(srvFormat),
       rtvFormat(rtvFormat),
@@ -217,6 +221,7 @@
     {{
 {texture_format_info_cases}
         default:
+            UNREACHABLE();
             break;
     }}
     // clang-format on
@@ -461,19 +466,25 @@
     table_data = ''
     for angle_format_item in sorted(json_data.iteritems()):
         table_data += '        case ' + angle_format_item[0] + ':\n'
+        format_name = angle_format_item[0]
         angle_format = angle_format_item[1]
-        gl_internal_format = angle_format["glInternalFormat"] if "glInternalFormat" in angle_format else "GL_NONE"
+        if (format_name != "ANGLE_FORMAT_NONE") and ("glInternalFormat" not in angle_format):
+            print("Missing 'glInternalFormat' from " + format_name)
+            sys.exit(1)
+        gl_internal_format = "GL_NONE" if format_name == "ANGLE_FORMAT_NONE" else angle_format["glInternalFormat"]
+        fbo_internal_format = angle_format["fboImplementationInternalFormat"] if "fboImplementationInternalFormat" in angle_format else gl_internal_format
         tex_format = angle_format["texFormat"] if "texFormat" in angle_format else "DXGI_FORMAT_UNKNOWN"
         srv_format = angle_format["srvFormat"] if "srvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN"
         rtv_format = angle_format["rtvFormat"] if "rtvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN"
         dsv_format = angle_format["dsvFormat"] if "dsvFormat" in angle_format else "DXGI_FORMAT_UNKNOWN"
         blit_srv_format = get_blit_srv_format(angle_format)
-        swizzle_format = get_swizzle_format_id(angle_format_item[0], angle_format)
+        swizzle_format = get_swizzle_format_id(format_name, angle_format)
         mip_generation_function = get_mip_generation_function(angle_format)
         color_read_function = get_color_read_function(angle_format)
         table_data += '        {\n'
-        table_data += '            static const ANGLEFormatSet formatInfo(' + angle_format_item[0] + ',\n'
+        table_data += '            static const ANGLEFormatSet formatInfo(' + format_name + ',\n'
         table_data += '                                                   ' + gl_internal_format + ',\n'
+        table_data += '                                                   ' + fbo_internal_format + ',\n'
         table_data += '                                                   ' + tex_format + ',\n'
         table_data += '                                                   ' + srv_format + ',\n'
         table_data += '                                                   ' + rtv_format + ',\n'
diff --git a/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json b/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
index bef8980..74bb2ca 100644
--- a/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
+++ b/src/libANGLE/renderer/d3d/d3d11/load_functions_data.json
@@ -680,6 +680,22 @@
       }
     ]
   },
+  "GL_BGR565_ANGLEX": {
+    "GL_UNSIGNED_SHORT_5_6_5": [
+      {
+        "loadFunction": "LoadRGB565ToBGR565",
+        "dxgiFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+        "requiresConversion": "true"
+      }
+    ],
+    "GL_UNSIGNED_BYTE": [
+      {
+        "loadFunction": "LoadToNative<GLushort,1>",
+        "dxgiFormat": "DXGI_FORMAT_B5G6R5_UNORM",
+        "requiresConversion": "false"
+      }
+    ]
+  },
   "GL_COMPRESSED_RG11_EAC": {
     "GL_UNSIGNED_BYTE": [
       {
diff --git a/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp b/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
index 9b03083..2c9956f 100644
--- a/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/load_functions_table_autogen.cpp
@@ -177,6 +177,23 @@
                     break;
             }
         }
+        case GL_BGR565_ANGLEX:
+        {
+            switch (dxgiFormat)
+            {
+                case DXGI_FORMAT_B5G6R5_UNORM:
+                {
+                    static const std::map<GLenum, LoadImageFunctionInfo> loadFunctionsMap = {
+                        { GL_UNSIGNED_SHORT_5_6_5, LoadImageFunctionInfo(LoadRGB565ToBGR565, true) },
+                        { GL_UNSIGNED_BYTE, LoadImageFunctionInfo(LoadToNative<GLushort,1>, false) },
+                    };
+
+                    return loadFunctionsMap;
+                }
+                default:
+                    break;
+            }
+        }
         case GL_BGR5_A1_ANGLEX:
         {
             switch (dxgiFormat)
diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json b/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
index 9deb477..3ee7064 100644
--- a/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
+++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_data.json
@@ -26,7 +26,8 @@
     "rtvFormat": "DXGI_FORMAT_R16G16B16A16_UNORM",
     "channels": "rgba",
     "componentType": "unorm",
-    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 }
+    "bits": { "red": 16, "green": 16, "blue": 16, "alpha": 16 },
+    "glInternalFormat": "GL_RGBA16_EXT"
   },
   "ANGLE_FORMAT_R16G16B16A16_FLOAT": {
     "texFormat": "DXGI_FORMAT_R16G16B16A16_FLOAT",
@@ -424,8 +425,9 @@
     "channels": "bgr",
     "componentType":  "unorm",
     "bits": { "red": 5, "green": 6, "blue": 5 },
-    "glInternalFormat": "GL_RGB565",
-    "channelStruct": "R5G6B5"
+    "glInternalFormat": "GL_BGR565_ANGLEX",
+    "fboImplementationInternalFormat": "GL_RGB565",
+    "channelStruct": "B5G6R5"
   },
   "ANGLE_FORMAT_B5G5R5A1_UNORM": {
     "texFormat": "DXGI_FORMAT_B5G5R5A1_UNORM",
@@ -434,7 +436,8 @@
     "channels": "bgra",
     "componentType": "unorm",
     "bits": { "red": 5, "green": 5, "blue": 5, "alpha": 1 },
-    "glInternalFormat": "GL_RGB5_A1",
+    "glInternalFormat": "GL_BGR5_A1_ANGLEX",
+    "fboImplementationInternalFormat": "GL_RGB5_A1",
     "channelStruct": "A1R5G5B5"
   },
   "ANGLE_FORMAT_R8G8B8A8_SINT": {
@@ -479,7 +482,8 @@
     "channels": "bgra",
     "componentType":  "unorm",
     "bits": { "red": 4, "green": 4, "blue": 4, "alpha": 4 },
-    "glInternalFormat": "GL_RGBA4",
+    "glInternalFormat": "GL_BGRA4_ANGLEX",
+    "fboImplementationInternalFormat": "GL_RGBA4",
     "channelStruct":  "A4R4G4B4"
   },
   "ANGLE_FORMAT_R8G8B8A8_UNORM_SRGB": {
@@ -505,7 +509,8 @@
     "rtvFormat": "DXGI_FORMAT_R16_UNORM",
     "channels": "r",
     "componentType": "unorm",
-    "bits": { "red": 16 }
+    "bits": { "red": 16 },
+    "glInternalFormat": "GL_R16_EXT"
   },
   "ANGLE_FORMAT_R16G16_UNORM": {
     "texFormat": "DXGI_FORMAT_R16G16_UNORM",
@@ -513,7 +518,8 @@
     "rtvFormat": "DXGI_FORMAT_R16G16_UNORM",
     "channels": "rg",
     "componentType": "unorm",
-    "bits": { "red": 16, "green": 16 }
+    "bits": { "red": 16, "green": 16 },
+    "glInternalFormat": "GL_RG16_EXT"
   },
   "ANGLE_FORMAT_R16_SNORM": {
     "texFormat": "DXGI_FORMAT_R16_SNORM",
diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json b/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
index 5ef0787..401edb2 100644
--- a/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
+++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_map.json
@@ -9,6 +9,7 @@
     "OnlyFL10Plus": "ANGLE_FORMAT_A8_UNORM",
     "OnlyFL9_3": "ANGLE_FORMAT_R8G8B8A8_UNORM"
   },
+  "GL_BGR565_ANGLEX": "ANGLE_FORMAT_B5G6R5_UNORM",
   "GL_BGR5_A1_ANGLEX": "ANGLE_FORMAT_B8G8R8A8_UNORM",
   "GL_BGRA4_ANGLEX": "ANGLE_FORMAT_B8G8R8A8_UNORM",
   "GL_BGRA8_EXT": "ANGLE_FORMAT_B8G8R8A8_UNORM",
@@ -31,6 +32,20 @@
   "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT": "ANGLE_FORMAT_BC1_UNORM",
   "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE": "ANGLE_FORMAT_BC2_UNORM",
   "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE": "ANGLE_FORMAT_BC3_UNORM",
+  "GL_COMPRESSED_RGBA_ASTC_4x4_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_5x4_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_5x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_6x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_6x6_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_8x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_8x6_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_8x8_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x6_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x8_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_10x10_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_12x10_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_RGBA_ASTC_12x12_KHR": "ANGLE_FORMAT_NONE",
   "GL_COMPRESSED_RGB_S3TC_DXT1_EXT": "ANGLE_FORMAT_BC1_UNORM",
   "GL_COMPRESSED_SIGNED_R11_EAC": {
     "OnlyFL10Plus": "ANGLE_FORMAT_R8_SNORM_NONRENDERABLE"
@@ -38,6 +53,20 @@
   "GL_COMPRESSED_SIGNED_RG11_EAC": {
     "OnlyFL10Plus": "ANGLE_FORMAT_R8G8_SNORM_NONRENDERABLE"
   },
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR": "ANGLE_FORMAT_NONE",
+  "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR": "ANGLE_FORMAT_NONE",
   "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC": {
     "OnlyFL10Plus": "ANGLE_FORMAT_R8G8B8A8_UNORM_SRGB_NONRENDERABLE"
   },
diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h b/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
index 95d104f..77f7e52 100644
--- a/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
+++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_table.h
@@ -43,6 +43,7 @@
     ANGLEFormatSet();
     ANGLEFormatSet(ANGLEFormat format,
                    GLenum glInternalFormat,
+                   GLenum fboImplementationInternalFormat,
                    DXGI_FORMAT texFormat,
                    DXGI_FORMAT srvFormat,
                    DXGI_FORMAT rtvFormat,
@@ -60,6 +61,11 @@
     // may be a different internal format than the one this ANGLE format is used for.
     GLenum glInternalFormat;
 
+    // The format we should report to the GL layer when querying implementation formats from a FBO.
+    // This might not be the same as the glInternalFormat, since some DXGI formats don't have
+    // matching GL format enums, like BGRA4, BGR5A1 and B5G6R6.
+    GLenum fboImplementationInternalFormat;
+
     DXGI_FORMAT texFormat;
     DXGI_FORMAT srvFormat;
     DXGI_FORMAT rtvFormat;
diff --git a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
index b559db3..e878d19 100644
--- a/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
+++ b/src/libANGLE/renderer/d3d/d3d11/texture_format_table_autogen.cpp
@@ -102,6 +102,7 @@
 ANGLEFormatSet::ANGLEFormatSet()
     : format(ANGLE_FORMAT_NONE),
       glInternalFormat(GL_NONE),
+      fboImplementationInternalFormat(GL_NONE),
       texFormat(DXGI_FORMAT_UNKNOWN),
       srvFormat(DXGI_FORMAT_UNKNOWN),
       rtvFormat(DXGI_FORMAT_UNKNOWN),
@@ -128,11 +129,12 @@
     // Gather all the load functions for this internal format
     loadFunctions = GetLoadFunctionsMap(internalFormat, formatSet->texFormat);
 
-    ASSERT(loadFunctions.size() != 0 || internalFormat == GL_NONE);
+    ASSERT(loadFunctions.size() != 0 || angleFormat == ANGLE_FORMAT_NONE);
 }
 
 ANGLEFormatSet::ANGLEFormatSet(ANGLEFormat format,
                                GLenum glInternalFormat,
+                               GLenum fboImplementationInternalFormat,
                                DXGI_FORMAT texFormat,
                                DXGI_FORMAT srvFormat,
                                DXGI_FORMAT rtvFormat,
@@ -143,6 +145,7 @@
                                ColorReadFunction colorReadFunction)
     : format(format),
       glInternalFormat(glInternalFormat),
+      fboImplementationInternalFormat(fboImplementationInternalFormat),
       texFormat(texFormat),
       srvFormat(srvFormat),
       rtvFormat(rtvFormat),
@@ -163,6 +166,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_A8_UNORM,
                                                    GL_ALPHA8_EXT,
+                                                   GL_ALPHA8_EXT,
                                                    DXGI_FORMAT_A8_UNORM,
                                                    DXGI_FORMAT_A8_UNORM,
                                                    DXGI_FORMAT_A8_UNORM,
@@ -176,6 +180,7 @@
         case ANGLE_FORMAT_B4G4R4A4_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_B4G4R4A4_UNORM,
+                                                   GL_BGRA4_ANGLEX,
                                                    GL_RGBA4,
                                                    DXGI_FORMAT_B4G4R4A4_UNORM,
                                                    DXGI_FORMAT_B4G4R4A4_UNORM,
@@ -190,6 +195,7 @@
         case ANGLE_FORMAT_B5G5R5A1_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_B5G5R5A1_UNORM,
+                                                   GL_BGR5_A1_ANGLEX,
                                                    GL_RGB5_A1,
                                                    DXGI_FORMAT_B5G5R5A1_UNORM,
                                                    DXGI_FORMAT_B5G5R5A1_UNORM,
@@ -204,6 +210,7 @@
         case ANGLE_FORMAT_B5G6R5_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_B5G6R5_UNORM,
+                                                   GL_BGR565_ANGLEX,
                                                    GL_RGB565,
                                                    DXGI_FORMAT_B5G6R5_UNORM,
                                                    DXGI_FORMAT_B5G6R5_UNORM,
@@ -211,14 +218,15 @@
                                                    DXGI_FORMAT_UNKNOWN,
                                                    DXGI_FORMAT_B5G6R5_UNORM,
                                                    ANGLE_FORMAT_R8G8B8A8_UNORM,
-                                                   GenerateMip<R5G6B5>,
-                                                   ReadColor<R5G6B5, GLfloat>);
+                                                   GenerateMip<B5G6R5>,
+                                                   ReadColor<B5G6R5, GLfloat>);
             return formatInfo;
         }
         case ANGLE_FORMAT_B8G8R8A8_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_B8G8R8A8_UNORM,
                                                    GL_BGRA8_EXT,
+                                                   GL_BGRA8_EXT,
                                                    DXGI_FORMAT_B8G8R8A8_UNORM,
                                                    DXGI_FORMAT_B8G8R8A8_UNORM,
                                                    DXGI_FORMAT_B8G8R8A8_UNORM,
@@ -233,6 +241,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_BC1_UNORM,
                                                    GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
+                                                   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
                                                    DXGI_FORMAT_BC1_UNORM,
                                                    DXGI_FORMAT_BC1_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -247,6 +256,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_BC2_UNORM,
                                                    GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
+                                                   GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE,
                                                    DXGI_FORMAT_BC2_UNORM,
                                                    DXGI_FORMAT_BC2_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -261,6 +271,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_BC3_UNORM,
                                                    GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
+                                                   GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE,
                                                    DXGI_FORMAT_BC3_UNORM,
                                                    DXGI_FORMAT_BC3_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -275,6 +286,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_D16_UNORM_FL10,
                                                    GL_DEPTH_COMPONENT16,
+                                                   GL_DEPTH_COMPONENT16,
                                                    DXGI_FORMAT_R16_TYPELESS,
                                                    DXGI_FORMAT_R16_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -289,6 +301,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_D16_UNORM_FL9_3,
                                                    GL_DEPTH_COMPONENT16,
+                                                   GL_DEPTH_COMPONENT16,
                                                    DXGI_FORMAT_D16_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -303,6 +316,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_D24_UNORM_S8_UINT_FL10,
                                                    GL_DEPTH24_STENCIL8_OES,
+                                                   GL_DEPTH24_STENCIL8_OES,
                                                    DXGI_FORMAT_R24G8_TYPELESS,
                                                    DXGI_FORMAT_R24_UNORM_X8_TYPELESS,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -317,6 +331,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_D24_UNORM_S8_UINT_FL9_3,
                                                    GL_DEPTH24_STENCIL8_OES,
+                                                   GL_DEPTH24_STENCIL8_OES,
                                                    DXGI_FORMAT_D24_UNORM_S8_UINT,
                                                    DXGI_FORMAT_UNKNOWN,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -331,6 +346,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_D32_FLOAT,
                                                    GL_DEPTH_COMPONENT32F,
+                                                   GL_DEPTH_COMPONENT32F,
                                                    DXGI_FORMAT_R32_TYPELESS,
                                                    DXGI_FORMAT_R32_FLOAT,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -345,6 +361,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_D32_FLOAT_S8X24_UINT_FL10,
                                                    GL_DEPTH32F_STENCIL8,
+                                                   GL_DEPTH32F_STENCIL8,
                                                    DXGI_FORMAT_R32G8X24_TYPELESS,
                                                    DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -359,6 +376,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_NONE,
                                                    GL_NONE,
+                                                   GL_NONE,
                                                    DXGI_FORMAT_UNKNOWN,
                                                    DXGI_FORMAT_UNKNOWN,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -373,6 +391,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R10G10B10A2_UINT,
                                                    GL_RGB10_A2UI,
+                                                   GL_RGB10_A2UI,
                                                    DXGI_FORMAT_R10G10B10A2_UINT,
                                                    DXGI_FORMAT_R10G10B10A2_UINT,
                                                    DXGI_FORMAT_R10G10B10A2_UINT,
@@ -387,6 +406,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R10G10B10A2_UNORM,
                                                    GL_RGB10_A2,
+                                                   GL_RGB10_A2,
                                                    DXGI_FORMAT_R10G10B10A2_UNORM,
                                                    DXGI_FORMAT_R10G10B10A2_UNORM,
                                                    DXGI_FORMAT_R10G10B10A2_UNORM,
@@ -401,6 +421,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R11G11B10_FLOAT,
                                                    GL_R11F_G11F_B10F,
+                                                   GL_R11F_G11F_B10F,
                                                    DXGI_FORMAT_R11G11B10_FLOAT,
                                                    DXGI_FORMAT_R11G11B10_FLOAT,
                                                    DXGI_FORMAT_R11G11B10_FLOAT,
@@ -415,6 +436,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16B16A16_FLOAT,
                                                    GL_RGBA16F,
+                                                   GL_RGBA16F,
                                                    DXGI_FORMAT_R16G16B16A16_FLOAT,
                                                    DXGI_FORMAT_R16G16B16A16_FLOAT,
                                                    DXGI_FORMAT_R16G16B16A16_FLOAT,
@@ -429,6 +451,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16B16A16_SINT,
                                                    GL_RGBA16I,
+                                                   GL_RGBA16I,
                                                    DXGI_FORMAT_R16G16B16A16_SINT,
                                                    DXGI_FORMAT_R16G16B16A16_SINT,
                                                    DXGI_FORMAT_R16G16B16A16_SINT,
@@ -443,6 +466,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16B16A16_SNORM,
                                                    GL_RGBA16_SNORM_EXT,
+                                                   GL_RGBA16_SNORM_EXT,
                                                    DXGI_FORMAT_R16G16B16A16_SNORM,
                                                    DXGI_FORMAT_R16G16B16A16_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -457,6 +481,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16B16A16_UINT,
                                                    GL_RGBA16UI,
+                                                   GL_RGBA16UI,
                                                    DXGI_FORMAT_R16G16B16A16_UINT,
                                                    DXGI_FORMAT_R16G16B16A16_UINT,
                                                    DXGI_FORMAT_R16G16B16A16_UINT,
@@ -470,7 +495,8 @@
         case ANGLE_FORMAT_R16G16B16A16_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16B16A16_UNORM,
-                                                   GL_NONE,
+                                                   GL_RGBA16_EXT,
+                                                   GL_RGBA16_EXT,
                                                    DXGI_FORMAT_R16G16B16A16_UNORM,
                                                    DXGI_FORMAT_R16G16B16A16_UNORM,
                                                    DXGI_FORMAT_R16G16B16A16_UNORM,
@@ -485,6 +511,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16_FLOAT,
                                                    GL_RG16F,
+                                                   GL_RG16F,
                                                    DXGI_FORMAT_R16G16_FLOAT,
                                                    DXGI_FORMAT_R16G16_FLOAT,
                                                    DXGI_FORMAT_R16G16_FLOAT,
@@ -499,6 +526,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16_SINT,
                                                    GL_RG16I,
+                                                   GL_RG16I,
                                                    DXGI_FORMAT_R16G16_SINT,
                                                    DXGI_FORMAT_R16G16_SINT,
                                                    DXGI_FORMAT_R16G16_SINT,
@@ -513,6 +541,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16_SNORM,
                                                    GL_RG16_SNORM_EXT,
+                                                   GL_RG16_SNORM_EXT,
                                                    DXGI_FORMAT_R16G16_SNORM,
                                                    DXGI_FORMAT_R16G16_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -527,6 +556,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16_UINT,
                                                    GL_RG16UI,
+                                                   GL_RG16UI,
                                                    DXGI_FORMAT_R16G16_UINT,
                                                    DXGI_FORMAT_R16G16_UINT,
                                                    DXGI_FORMAT_R16G16_UINT,
@@ -540,7 +570,8 @@
         case ANGLE_FORMAT_R16G16_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16G16_UNORM,
-                                                   GL_NONE,
+                                                   GL_RG16_EXT,
+                                                   GL_RG16_EXT,
                                                    DXGI_FORMAT_R16G16_UNORM,
                                                    DXGI_FORMAT_R16G16_UNORM,
                                                    DXGI_FORMAT_R16G16_UNORM,
@@ -555,6 +586,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16_FLOAT,
                                                    GL_R16F,
+                                                   GL_R16F,
                                                    DXGI_FORMAT_R16_FLOAT,
                                                    DXGI_FORMAT_R16_FLOAT,
                                                    DXGI_FORMAT_R16_FLOAT,
@@ -569,6 +601,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16_SINT,
                                                    GL_R16I,
+                                                   GL_R16I,
                                                    DXGI_FORMAT_R16_SINT,
                                                    DXGI_FORMAT_R16_SINT,
                                                    DXGI_FORMAT_R16_SINT,
@@ -583,6 +616,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16_SNORM,
                                                    GL_R16_SNORM_EXT,
+                                                   GL_R16_SNORM_EXT,
                                                    DXGI_FORMAT_R16_SNORM,
                                                    DXGI_FORMAT_R16_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -597,6 +631,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16_UINT,
                                                    GL_R16UI,
+                                                   GL_R16UI,
                                                    DXGI_FORMAT_R16_UINT,
                                                    DXGI_FORMAT_R16_UINT,
                                                    DXGI_FORMAT_R16_UINT,
@@ -610,7 +645,8 @@
         case ANGLE_FORMAT_R16_UNORM:
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R16_UNORM,
-                                                   GL_NONE,
+                                                   GL_R16_EXT,
+                                                   GL_R16_EXT,
                                                    DXGI_FORMAT_R16_UNORM,
                                                    DXGI_FORMAT_R16_UNORM,
                                                    DXGI_FORMAT_R16_UNORM,
@@ -625,6 +661,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32G32B32A32_FLOAT,
                                                    GL_RGBA32F,
+                                                   GL_RGBA32F,
                                                    DXGI_FORMAT_R32G32B32A32_FLOAT,
                                                    DXGI_FORMAT_R32G32B32A32_FLOAT,
                                                    DXGI_FORMAT_R32G32B32A32_FLOAT,
@@ -639,6 +676,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32G32B32A32_SINT,
                                                    GL_RGBA32I,
+                                                   GL_RGBA32I,
                                                    DXGI_FORMAT_R32G32B32A32_SINT,
                                                    DXGI_FORMAT_R32G32B32A32_SINT,
                                                    DXGI_FORMAT_R32G32B32A32_SINT,
@@ -653,6 +691,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32G32B32A32_UINT,
                                                    GL_RGBA32UI,
+                                                   GL_RGBA32UI,
                                                    DXGI_FORMAT_R32G32B32A32_UINT,
                                                    DXGI_FORMAT_R32G32B32A32_UINT,
                                                    DXGI_FORMAT_R32G32B32A32_UINT,
@@ -667,6 +706,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32G32_FLOAT,
                                                    GL_RG32F,
+                                                   GL_RG32F,
                                                    DXGI_FORMAT_R32G32_FLOAT,
                                                    DXGI_FORMAT_R32G32_FLOAT,
                                                    DXGI_FORMAT_R32G32_FLOAT,
@@ -681,6 +721,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32G32_SINT,
                                                    GL_RG32I,
+                                                   GL_RG32I,
                                                    DXGI_FORMAT_R32G32_SINT,
                                                    DXGI_FORMAT_R32G32_SINT,
                                                    DXGI_FORMAT_R32G32_SINT,
@@ -695,6 +736,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32G32_UINT,
                                                    GL_RG32UI,
+                                                   GL_RG32UI,
                                                    DXGI_FORMAT_R32G32_UINT,
                                                    DXGI_FORMAT_R32G32_UINT,
                                                    DXGI_FORMAT_R32G32_UINT,
@@ -709,6 +751,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32_FLOAT,
                                                    GL_R32F,
+                                                   GL_R32F,
                                                    DXGI_FORMAT_R32_FLOAT,
                                                    DXGI_FORMAT_R32_FLOAT,
                                                    DXGI_FORMAT_R32_FLOAT,
@@ -723,6 +766,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32_SINT,
                                                    GL_R32I,
+                                                   GL_R32I,
                                                    DXGI_FORMAT_R32_SINT,
                                                    DXGI_FORMAT_R32_SINT,
                                                    DXGI_FORMAT_R32_SINT,
@@ -737,6 +781,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R32_UINT,
                                                    GL_R32UI,
+                                                   GL_R32UI,
                                                    DXGI_FORMAT_R32_UINT,
                                                    DXGI_FORMAT_R32_UINT,
                                                    DXGI_FORMAT_R32_UINT,
@@ -751,6 +796,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_SINT,
                                                    GL_RGBA8I,
+                                                   GL_RGBA8I,
                                                    DXGI_FORMAT_R8G8B8A8_SINT,
                                                    DXGI_FORMAT_R8G8B8A8_SINT,
                                                    DXGI_FORMAT_R8G8B8A8_SINT,
@@ -765,6 +811,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_SNORM,
                                                    GL_RGBA8_SNORM,
+                                                   GL_RGBA8_SNORM,
                                                    DXGI_FORMAT_R8G8B8A8_SNORM,
                                                    DXGI_FORMAT_R8G8B8A8_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -779,6 +826,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_UINT,
                                                    GL_RGBA8UI,
+                                                   GL_RGBA8UI,
                                                    DXGI_FORMAT_R8G8B8A8_UINT,
                                                    DXGI_FORMAT_R8G8B8A8_UINT,
                                                    DXGI_FORMAT_R8G8B8A8_UINT,
@@ -793,6 +841,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_UNORM,
                                                    GL_RGBA8,
+                                                   GL_RGBA8,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM,
@@ -807,6 +856,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_UNORM_NONRENDERABLE,
                                                    GL_RGBA8,
+                                                   GL_RGBA8,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -821,6 +871,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_UNORM_SRGB,
                                                    GL_SRGB8_ALPHA8,
+                                                   GL_SRGB8_ALPHA8,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
@@ -835,6 +886,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8B8A8_UNORM_SRGB_NONRENDERABLE,
                                                    GL_SRGB8_ALPHA8,
+                                                   GL_SRGB8_ALPHA8,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
                                                    DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -849,6 +901,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8_SINT,
                                                    GL_RG8I,
+                                                   GL_RG8I,
                                                    DXGI_FORMAT_R8G8_SINT,
                                                    DXGI_FORMAT_R8G8_SINT,
                                                    DXGI_FORMAT_R8G8_SINT,
@@ -863,6 +916,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8_SNORM,
                                                    GL_RG8_SNORM,
+                                                   GL_RG8_SNORM,
                                                    DXGI_FORMAT_R8G8_SNORM,
                                                    DXGI_FORMAT_R8G8_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -877,6 +931,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8_SNORM_NONRENDERABLE,
                                                    GL_RG8_SNORM,
+                                                   GL_RG8_SNORM,
                                                    DXGI_FORMAT_R8G8_SNORM,
                                                    DXGI_FORMAT_R8G8_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -891,6 +946,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8_UINT,
                                                    GL_RG8UI,
+                                                   GL_RG8UI,
                                                    DXGI_FORMAT_R8G8_UINT,
                                                    DXGI_FORMAT_R8G8_UINT,
                                                    DXGI_FORMAT_R8G8_UINT,
@@ -905,6 +961,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8_UNORM,
                                                    GL_RG8,
+                                                   GL_RG8,
                                                    DXGI_FORMAT_R8G8_UNORM,
                                                    DXGI_FORMAT_R8G8_UNORM,
                                                    DXGI_FORMAT_R8G8_UNORM,
@@ -919,6 +976,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8G8_UNORM_NONRENDERABLE,
                                                    GL_RG8,
+                                                   GL_RG8,
                                                    DXGI_FORMAT_R8G8_UNORM,
                                                    DXGI_FORMAT_R8G8_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -933,6 +991,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8_SINT,
                                                    GL_R8I,
+                                                   GL_R8I,
                                                    DXGI_FORMAT_R8_SINT,
                                                    DXGI_FORMAT_R8_SINT,
                                                    DXGI_FORMAT_R8_SINT,
@@ -947,6 +1006,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8_SNORM,
                                                    GL_R8_SNORM,
+                                                   GL_R8_SNORM,
                                                    DXGI_FORMAT_R8_SNORM,
                                                    DXGI_FORMAT_R8_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -961,6 +1021,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8_SNORM_NONRENDERABLE,
                                                    GL_R8_SNORM,
+                                                   GL_R8_SNORM,
                                                    DXGI_FORMAT_R8_SNORM,
                                                    DXGI_FORMAT_R8_SNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -975,6 +1036,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8_UINT,
                                                    GL_R8UI,
+                                                   GL_R8UI,
                                                    DXGI_FORMAT_R8_UINT,
                                                    DXGI_FORMAT_R8_UINT,
                                                    DXGI_FORMAT_R8_UINT,
@@ -989,6 +1051,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8_UNORM,
                                                    GL_R8,
+                                                   GL_R8,
                                                    DXGI_FORMAT_R8_UNORM,
                                                    DXGI_FORMAT_R8_UNORM,
                                                    DXGI_FORMAT_R8_UNORM,
@@ -1003,6 +1066,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R8_UNORM_NONRENDERABLE,
                                                    GL_R8,
+                                                   GL_R8,
                                                    DXGI_FORMAT_R8_UNORM,
                                                    DXGI_FORMAT_R8_UNORM,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -1017,6 +1081,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_R9G9B9E5_SHAREDEXP,
                                                    GL_RGB9_E5,
+                                                   GL_RGB9_E5,
                                                    DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
                                                    DXGI_FORMAT_R9G9B9E5_SHAREDEXP,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -1031,6 +1096,7 @@
         {
             static const ANGLEFormatSet formatInfo(ANGLE_FORMAT_X24_TYPELESS_G8_UINT,
                                                    GL_DEPTH24_STENCIL8_OES,
+                                                   GL_DEPTH24_STENCIL8_OES,
                                                    DXGI_FORMAT_R24G8_TYPELESS,
                                                    DXGI_FORMAT_X24_TYPELESS_G8_UINT,
                                                    DXGI_FORMAT_UNKNOWN,
@@ -1114,6 +1180,13 @@
                 break;
             }
         }
+        case GL_BGR565_ANGLEX:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_B5G6R5_UNORM,
+                                                     nullptr);
+            return textureFormat;
+        }
         case GL_BGR5_A1_ANGLEX:
         {
             static const TextureFormat textureFormat(internalFormat,
@@ -1212,6 +1285,104 @@
                 break;
             }
         }
+        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
         case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
         {
             static const TextureFormat textureFormat(internalFormat,
@@ -1268,6 +1439,104 @@
                 break;
             }
         }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
+        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
+        {
+            static const TextureFormat textureFormat(internalFormat,
+                                                     ANGLE_FORMAT_NONE,
+                                                     nullptr);
+            return textureFormat;
+        }
         case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
         {
             if (OnlyFL10Plus(renderer11DeviceCaps))
@@ -1984,6 +2253,7 @@
         }
 
         default:
+            UNREACHABLE();
             break;
     }
     // clang-format on
diff --git a/src/libANGLE/renderer/d3d/loadimage.cpp b/src/libANGLE/renderer/d3d/loadimage.cpp
index e36ac9e..3f5bdb0 100644
--- a/src/libANGLE/renderer/d3d/loadimage.cpp
+++ b/src/libANGLE/renderer/d3d/loadimage.cpp
@@ -256,6 +256,38 @@
     }
 }
 
+void LoadRGB565ToBGR565(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch)
+{
+    for (size_t z = 0; z < depth; z++)
+    {
+        for (size_t y = 0; y < height; y++)
+        {
+            const uint16_t *source =
+                OffsetDataPointer<uint16_t>(input, y, z, inputRowPitch, inputDepthPitch);
+            uint16_t *dest =
+                OffsetDataPointer<uint16_t>(output, y, z, outputRowPitch, outputDepthPitch);
+            for (size_t x = 0; x < width; x++)
+            {
+                // The GL type RGB is packed with with red in the MSB, while the D3D11 type BGR
+                // is packed with red in the LSB
+                auto rgb    = source[x];
+                uint16_t r5 = gl::getShiftedData<5, 11>(rgb);
+                uint16_t g6 = gl::getShiftedData<6, 5>(rgb);
+                uint16_t b5 = gl::getShiftedData<5, 0>(rgb);
+                dest[x]     = (r5 << 11) | (g6 << 5) | b5;
+            }
+        }
+    }
+}
+
 void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth,
                      const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
                      uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
diff --git a/src/libANGLE/renderer/d3d/loadimage.h b/src/libANGLE/renderer/d3d/loadimage.h
index 86ca1ba..a12c345 100644
--- a/src/libANGLE/renderer/d3d/loadimage.h
+++ b/src/libANGLE/renderer/d3d/loadimage.h
@@ -90,6 +90,16 @@
                       size_t outputRowPitch,
                       size_t outputDepthPitch);
 
+void LoadRGB565ToBGR565(size_t width,
+                        size_t height,
+                        size_t depth,
+                        const uint8_t *input,
+                        size_t inputRowPitch,
+                        size_t inputDepthPitch,
+                        uint8_t *output,
+                        size_t outputRowPitch,
+                        size_t outputDepthPitch);
+
 void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth,
                        const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
                        uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
diff --git a/src/libANGLE/renderer/imageformats.h b/src/libANGLE/renderer/imageformats.h
index efcf0de..dd184c3 100644
--- a/src/libANGLE/renderer/imageformats.h
+++ b/src/libANGLE/renderer/imageformats.h
@@ -295,7 +295,7 @@
     // most significant
     // bits of the bitfield, and successive component occupying progressively less significant
     // locations"
-    unsigned short RGB;
+    uint16_t RGB;
 
     static void readColor(gl::ColorF *dst, const R5G6B5 *src)
     {
@@ -307,9 +307,9 @@
 
     static void writeColor(R5G6B5 *dst, const gl::ColorF *src)
     {
-        dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) |
-                   gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) |
-                   gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue));
+        dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, uint16_t>(src->red)) |
+                   gl::shiftData<6, 5>(gl::floatToNormalized<6, uint16_t>(src->green)) |
+                   gl::shiftData<5, 0>(gl::floatToNormalized<5, uint16_t>(src->blue));
     }
 
     static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2)
@@ -323,6 +323,36 @@
     }
 };
 
+struct B5G6R5
+{
+    uint16_t BGR;
+
+    static void readColor(gl::ColorF *dst, const B5G6R5 *src)
+    {
+        dst->red   = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->BGR));
+        dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->BGR));
+        dst->blue  = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGR));
+        dst->alpha = 1.0f;
+    }
+
+    static void writeColor(B5G6R5 *dst, const gl::ColorF *src)
+    {
+        dst->BGR = gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)) |
+                   gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) |
+                   gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red));
+    }
+
+    static void average(B5G6R5 *dst, const B5G6R5 *src1, const B5G6R5 *src2)
+    {
+        dst->BGR = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->BGR),
+                                                    gl::getShiftedData<5, 11>(src2->BGR))) |
+                   gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->BGR),
+                                                   gl::getShiftedData<6, 5>(src2->BGR))) |
+                   gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGR),
+                                                   gl::getShiftedData<5, 0>(src2->BGR)));
+    }
+};
+
 struct A8R8G8B8
 {
     unsigned char A;
@@ -621,7 +651,7 @@
 
 struct A4R4G4B4
 {
-    unsigned short ARGB;
+    uint16_t ARGB;
 
     static void readColor(gl::ColorF *dst, const A4R4G4B4 *src)
     {
@@ -633,10 +663,10 @@
 
     static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src)
     {
-        dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, unsigned short>(src->alpha)) |
-                    gl::shiftData<4, 8>(gl::floatToNormalized<4, unsigned short>(src->red)) |
-                    gl::shiftData<4, 4>(gl::floatToNormalized<4, unsigned short>(src->green)) |
-                    gl::shiftData<4, 0>(gl::floatToNormalized<4, unsigned short>(src->blue));
+        dst->ARGB = gl::shiftData<4, 12>(gl::floatToNormalized<4, uint16_t>(src->alpha)) |
+                    gl::shiftData<4, 8>(gl::floatToNormalized<4, uint16_t>(src->red)) |
+                    gl::shiftData<4, 4>(gl::floatToNormalized<4, uint16_t>(src->green)) |
+                    gl::shiftData<4, 0>(gl::floatToNormalized<4, uint16_t>(src->blue));
     }
 
     static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2)
diff --git a/src/libANGLE/renderer/renderer_utils.cpp b/src/libANGLE/renderer/renderer_utils.cpp
index ea6fee7..89aa9e1 100644
--- a/src/libANGLE/renderer/renderer_utils.cpp
+++ b/src/libANGLE/renderer/renderer_utils.cpp
@@ -194,6 +194,8 @@
         return;
     }
 
+    ASSERT(sourceFormatInfo.pixelBytes > 0);
+
     gl::FormatType formatType(params.format, params.type);
     ColorCopyFunction fastCopyFunc = GetFastCopyFunction(fastCopyFunctionsMap, formatType);
     GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(formatType.format, formatType.type);
diff --git a/src/tests/gl_tests/SixteenBppTextureTest.cpp b/src/tests/gl_tests/SixteenBppTextureTest.cpp
index 7266eed..34fde78 100644
--- a/src/tests/gl_tests/SixteenBppTextureTest.cpp
+++ b/src/tests/gl_tests/SixteenBppTextureTest.cpp
@@ -9,11 +9,30 @@
 #include "test_utils/ANGLETest.h"
 #include "test_utils/gl_raii.h"
 
+#include "libANGLE/renderer/imageformats.h"
+
 using namespace angle;
 
 namespace
 {
 
+GLColor Convert565(const rx::R5G6B5 &rgb565)
+{
+    gl::ColorF colorf;
+    rx::R5G6B5::readColor(&colorf, &rgb565);
+    Vector4 vecColor(colorf.red, colorf.green, colorf.blue, colorf.alpha);
+    return GLColor(vecColor);
+}
+
+rx::R5G6B5 Convert565(const GLColor &glColor)
+{
+    const Vector4 &vecColor = glColor.toNormalizedVector();
+    gl::ColorF colorf(vecColor.x, vecColor.y, vecColor.z, vecColor.w);
+    rx::R5G6B5 rgb565;
+    rx::R5G6B5::writeColor(&rgb565, &colorf);
+    return rgb565;
+}
+
 class SixteenBppTextureTest : public ANGLETest
 {
   protected:
@@ -143,13 +162,11 @@
         return;
     }
 
-    GLushort pixels[4] =
-    {
-        0xF800, // Red
-        0x07E0, // Green
-        0x001F, // Blue
-        0xFFE0  // Red + Green
-    };
+    GLuint test;
+    memcpy(&test, &GLColor::black, 4);
+
+    rx::R5G6B5 pixels[4] = {Convert565(GLColor::red), Convert565(GLColor::green),
+                            Convert565(GLColor::blue), Convert565(GLColor::yellow)};
 
     glClearColor(0, 0, 0, 0);
 
@@ -379,6 +396,148 @@
     simpleValidationBase(tex.get());
 }
 
+// Test reading from RGBA4 textures attached to FBO.
+TEST_P(SixteenBppTextureTestES3, RGBA4FramebufferReadback)
+{
+    // TODO(jmadill): Fix bug with GLES
+    if (IsOpenGLES())
+    {
+        std::cout << "Test skipped on GLES." << std::endl;
+        return;
+    }
+
+    Vector4 rawColor(0.5f, 0.7f, 1.0f, 0.0f);
+    GLColor expectedColor(rawColor);
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA4, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.get(), 0);
+
+    glClearColor(rawColor.x, rawColor.y, rawColor.z, rawColor.w);
+    glClear(GL_COLOR_BUFFER_BIT);
+
+    ASSERT_GL_NO_ERROR();
+
+    GLenum colorReadFormat = GL_NONE;
+    GLenum colorReadType   = GL_NONE;
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, reinterpret_cast<GLint *>(&colorReadFormat));
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, reinterpret_cast<GLint *>(&colorReadType));
+
+    if (colorReadFormat == GL_RGBA && colorReadType == GL_UNSIGNED_BYTE)
+    {
+        GLColor actualColor = GLColor::black;
+        glReadPixels(0, 0, 1, 1, colorReadFormat, colorReadType, &actualColor);
+        EXPECT_COLOR_NEAR(expectedColor, actualColor, 20);
+    }
+    else
+    {
+        ASSERT_GLENUM_EQ(GL_RGBA, colorReadFormat);
+        ASSERT_TRUE(colorReadType == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT ||
+                    colorReadType == GL_UNSIGNED_SHORT_4_4_4_4);
+
+        uint16_t rgba = 0;
+        glReadPixels(0, 0, 1, 1, colorReadFormat, colorReadType, &rgba);
+
+        GLubyte r8 = static_cast<GLubyte>((rgba & 0xF000) >> 12);
+        GLubyte g8 = static_cast<GLubyte>((rgba & 0x0F00) >> 8);
+        GLubyte b8 = static_cast<GLubyte>((rgba & 0x00F0) >> 4);
+        GLubyte a8 = static_cast<GLubyte>((rgba & 0x000F));
+
+        GLColor actualColor(r8 << 4, g8 << 4, b8 << 4, a8 << 4);
+        EXPECT_COLOR_NEAR(expectedColor, actualColor, 20);
+    }
+
+    ASSERT_GL_NO_ERROR();
+}
+
+// Test reading from RGB565 textures attached to FBO.
+TEST_P(SixteenBppTextureTestES3, RGB565FramebufferReadback)
+{
+    // TODO(jmadill): Fix bug with GLES
+    if (IsOpenGLES())
+    {
+        std::cout << "Test skipped on GLES." << std::endl;
+        return;
+    }
+
+    GLFramebuffer fbo;
+    glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
+
+    std::vector<GLColor> fourColors;
+    fourColors.push_back(GLColor::red);
+    fourColors.push_back(GLColor::green);
+    fourColors.push_back(GLColor::blue);
+    fourColors.push_back(GLColor::white);
+
+    const std::string &vertexShader =
+        "#version 300 es\n"
+        "in vec4 color;\n"
+        "in vec2 position;\n"
+        "out vec4 fcolor;\n"
+        "void main() {\n"
+        "    fcolor = color;\n"
+        "    gl_Position = vec4(position, 0.5, 1.0);\n"
+        "}";
+    const std::string &fragmentShader =
+        "#version 300 es\n"
+        "in mediump vec4 fcolor;\n"
+        "out mediump vec4 color;\n"
+        "void main() {\n"
+        "    color = fcolor;\n"
+        "}";
+
+    GLuint program = CompileProgram(vertexShader, fragmentShader);
+    glUseProgram(program);
+
+    GLint colorLocation = glGetAttribLocation(program, "color");
+    ASSERT_NE(-1, colorLocation);
+    glEnableVertexAttribArray(colorLocation);
+    glVertexAttribPointer(colorLocation, 4, GL_UNSIGNED_BYTE, GL_TRUE, 0, fourColors.data());
+
+    int w = getWindowWidth();
+    int h = getWindowHeight();
+
+    glViewport(0, 0, w, h);
+
+    GLTexture tex;
+    glBindTexture(GL_TEXTURE_2D, tex.get());
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.get(), 0);
+
+    drawIndexedQuad(program, "position", 0.5f);
+
+    ASSERT_GL_NO_ERROR();
+
+    int t = 12;
+    EXPECT_PIXEL_COLOR_NEAR(0, h - 1, GLColor::red, t);
+    EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor::green, t);
+    EXPECT_PIXEL_COLOR_NEAR(w - 1, 0, GLColor::blue, t);
+    EXPECT_PIXEL_COLOR_NEAR(w - 1, h - 1, GLColor::white, t);
+
+    GLenum colorReadFormat = GL_NONE;
+    GLenum colorReadType   = GL_NONE;
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, reinterpret_cast<GLint *>(&colorReadFormat));
+    glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, reinterpret_cast<GLint *>(&colorReadType));
+
+    if (colorReadFormat == GL_RGB && colorReadType == GL_UNSIGNED_SHORT_5_6_5)
+    {
+        std::vector<rx::R5G6B5> readColors(w * h);
+        glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, readColors.data());
+
+        int hoffset = (h - 1) * w;
+        EXPECT_COLOR_NEAR(GLColor::red, Convert565(readColors[hoffset]), t);
+        EXPECT_COLOR_NEAR(GLColor::green, Convert565(readColors[0]), t);
+        EXPECT_COLOR_NEAR(GLColor::blue, Convert565(readColors[w - 1]), t);
+        EXPECT_COLOR_NEAR(GLColor::white, Convert565(readColors[w - 1 + hoffset]), t);
+    }
+
+    glDeleteProgram(program);
+}
+
 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
 ANGLE_INSTANTIATE_TEST(SixteenBppTextureTest,
                        ES2_D3D9(),
diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp
index c8236d9..1b13834 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -15,6 +15,7 @@
 namespace angle
 {
 
+const GLColorRGB GLColorRGB::black(0u, 0u, 0u);
 const GLColorRGB GLColorRGB::blue(0u, 0u, 255u);
 const GLColorRGB GLColorRGB::green(0u, 255u, 0u);
 const GLColorRGB GLColorRGB::red(255u, 0u, 0u);
@@ -37,6 +38,11 @@
     return static_cast<float>(channelValue) / 255.0f;
 }
 
+GLubyte ColorDenorm(float colorValue)
+{
+    return static_cast<GLubyte>(colorValue * 255.0f);
+}
+
 // Use a custom ANGLE platform class to capture and report internal errors.
 class TestPlatform : public angle::Platform
 {
@@ -89,6 +95,17 @@
 }
 
 TestPlatform g_testPlatformInstance;
+
+std::array<Vector3, 4> GetIndexedQuadVertices()
+{
+    std::array<Vector3, 4> vertices;
+    vertices[0] = Vector3(-1.0f, 1.0f, 0.5f);
+    vertices[1] = Vector3(-1.0f, -1.0f, 0.5f);
+    vertices[2] = Vector3(1.0f, -1.0f, 0.5f);
+    vertices[3] = Vector3(1.0f, 1.0f, 0.5f);
+    return vertices;
+}
+
 }  // anonymous namespace
 
 GLColorRGB::GLColorRGB() : R(0), G(0), B(0)
@@ -99,6 +116,11 @@
 {
 }
 
+GLColorRGB::GLColorRGB(const Vector3 &floatColor)
+    : R(ColorDenorm(floatColor.x)), G(ColorDenorm(floatColor.y)), B(ColorDenorm(floatColor.z))
+{
+}
+
 GLColor::GLColor() : R(0), G(0), B(0), A(0)
 {
 }
@@ -107,6 +129,22 @@
 {
 }
 
+GLColor::GLColor(const Vector4 &floatColor)
+    : R(ColorDenorm(floatColor.x)),
+      G(ColorDenorm(floatColor.y)),
+      B(ColorDenorm(floatColor.z)),
+      A(ColorDenorm(floatColor.w))
+{
+}
+
+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));
@@ -169,6 +207,19 @@
 
 }  // namespace angle
 
+// static
+std::array<Vector3, 6> ANGLETest::GetQuadVertices()
+{
+    std::array<Vector3, 6> vertices;
+    vertices[0] = Vector3(-1.0f, 1.0f, 0.5f);
+    vertices[1] = Vector3(-1.0f, -1.0f, 0.5f);
+    vertices[2] = Vector3(1.0f, -1.0f, 0.5f);
+    vertices[3] = Vector3(-1.0f, 1.0f, 0.5f);
+    vertices[4] = Vector3(1.0f, -1.0f, 0.5f);
+    vertices[5] = Vector3(1.0f, 1.0f, 0.5f);
+    return vertices;
+}
+
 ANGLETest::ANGLETest()
     : mEGLWindow(nullptr),
       mWidth(16),
@@ -261,19 +312,6 @@
     }
 }
 
-// static
-std::array<Vector3, 6> ANGLETest::GetQuadVertices()
-{
-    std::array<Vector3, 6> vertices;
-    vertices[0] = Vector3(-1.0f, 1.0f, 0.5f);
-    vertices[1] = Vector3(-1.0f, -1.0f, 0.5f);
-    vertices[2] = Vector3(1.0f, -1.0f, 0.5f);
-    vertices[3] = Vector3(-1.0f, 1.0f, 0.5f);
-    vertices[4] = Vector3(1.0f, -1.0f, 0.5f);
-    vertices[5] = Vector3(1.0f, 1.0f, 0.5f);
-    return vertices;
-}
-
 void ANGLETest::setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
 {
     if (mQuadVertexBuffer == 0)
@@ -293,6 +331,25 @@
     glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 6, quadVertices.data(), GL_STATIC_DRAW);
 }
 
+void ANGLETest::setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale)
+{
+    if (mQuadVertexBuffer == 0)
+    {
+        glGenBuffers(1, &mQuadVertexBuffer);
+    }
+
+    auto quadVertices = angle::GetIndexedQuadVertices();
+    for (Vector3 &vertex : quadVertices)
+    {
+        vertex.x *= positionAttribXYScale;
+        vertex.y *= positionAttribXYScale;
+        vertex.z = positionAttribZ;
+    }
+
+    glBindBuffer(GL_ARRAY_BUFFER, mQuadVertexBuffer);
+    glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 3 * 4, quadVertices.data(), GL_STATIC_DRAW);
+}
+
 // static
 void ANGLETest::drawQuad(GLuint program,
                          const std::string &positionAttribName,
@@ -380,7 +437,7 @@
     GLuint prevBinding = 0;
     glGetIntegerv(GL_ARRAY_BUFFER_BINDING, reinterpret_cast<GLint *>(&prevBinding));
 
-    setupQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
+    setupIndexedQuadVertexBuffer(positionAttribZ, positionAttribXYScale);
 
     glVertexAttribPointer(positionLocation, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
     glEnableVertexAttribArray(positionLocation);
diff --git a/src/tests/test_utils/ANGLETest.h b/src/tests/test_utils/ANGLETest.h
index c82375b..502b803 100644
--- a/src/tests/test_utils/ANGLETest.h
+++ b/src/tests/test_utils/ANGLETest.h
@@ -48,19 +48,25 @@
 {
     GLColorRGB();
     GLColorRGB(GLubyte r, GLubyte g, GLubyte b);
+    GLColorRGB(const Vector3 &floatColor);
 
     GLubyte R, G, B;
 
+    static const GLColorRGB black;
     static const GLColorRGB blue;
     static const GLColorRGB green;
     static const GLColorRGB red;
     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;
@@ -119,7 +125,6 @@
 
 #define EXPECT_PIXEL_COLOR_EQ(x, y, angleColor) EXPECT_EQ(angleColor, angle::ReadColor(x, y))
 
-// TODO(jmadill): Figure out how we can use GLColor's nice printing with EXPECT_NEAR.
 #define EXPECT_PIXEL_NEAR(x, y, r, g, b, a, abs_error) \
 { \
     GLubyte pixel[4]; \
@@ -131,8 +136,22 @@
     EXPECT_NEAR((a), pixel[3], abs_error); \
 }
 
+// TODO(jmadill): Figure out how we can use GLColor's nice printing with EXPECT_NEAR.
+#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) \
+    \
+{                                               \
+        EXPECT_NEAR(expected.R, actual.R, abs_error);  \
+        EXPECT_NEAR(expected.G, actual.G, abs_error);  \
+        EXPECT_NEAR(expected.B, actual.B, abs_error);  \
+        EXPECT_NEAR(expected.A, actual.A, abs_error);  \
+    \
+}
+
 class EGLWindow;
 class OSWindow;
 
@@ -155,6 +174,7 @@
     virtual void swapBuffers();
 
     void setupQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);
+    void setupIndexedQuadVertexBuffer(GLfloat positionAttribZ, GLfloat positionAttribXYScale);
 
     void drawQuad(GLuint program, const std::string &positionAttribName, GLfloat positionAttribZ);
     void drawQuad(GLuint program,