Simplify formatutils.h by exposing the info structures.

Removed all the separate query functions and simply expose the internal
info structures.  This reduces the number of std::map/std::set operations
that were hidden behind the API.

Moved the validation tables for ES3 format combinations and effective
internal formats into validationES3.cpp so that formatutils.h only has
generic GL format queries.

BUG=angle:658

Change-Id: Ieb60d42b8eafcdb4f21dcbec130b39478ce5f7c5
Reviewed-on: https://chromium-review.googlesource.com/206835
Reviewed-by: Nicolas Capens <capn@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
index d6de3bf..98716c1 100644
--- a/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
+++ b/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
@@ -131,7 +131,10 @@
         return GL_OUT_OF_MEMORY;
     }
 
+    const gl::Type &typeInfo = gl::GetTypeInfo(type);
+
     GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT;
+
     unsigned int offset = 0;
     bool alignedOffset = false;
 
@@ -155,16 +158,14 @@
           default: UNREACHABLE(); alignedOffset = false;
         }
 
-        unsigned int typeSize = gl::GetTypeBytes(type);
-
         // check for integer overflows
-        if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeSize) ||
-            typeSize * static_cast<unsigned int>(count) + offset < offset)
+        if (static_cast<unsigned int>(count) > (std::numeric_limits<unsigned int>::max() / typeInfo.bytes) ||
+            typeInfo.bytes * static_cast<unsigned int>(count) + offset < offset)
         {
             return GL_OUT_OF_MEMORY;
         }
 
-        if (typeSize * static_cast<unsigned int>(count) + offset > storage->getSize())
+        if (typeInfo.bytes * static_cast<unsigned int>(count) + offset > storage->getSize())
         {
             return GL_INVALID_OPERATION;
         }
@@ -197,7 +198,7 @@
         if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex,
                                                            &translated->maxIndex, &streamOffset))
         {
-            streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType);
+            streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes;
             computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex);
             staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
                                                          translated->maxIndex, streamOffset);
@@ -217,6 +218,8 @@
         indexBuffer = NULL;
     }
 
+    const gl::Type &destTypeInfo = gl::GetTypeInfo(destinationIndexType);
+
     if (!directStorage && !indexBuffer)
     {
         indexBuffer = (destinationIndexType == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort;
@@ -228,7 +231,7 @@
             if (staticBuffer->getBufferSize() == 0 && alignedOffset)
             {
                 indexBuffer = staticBuffer;
-                convertCount = storage->getSize() / gl::GetTypeBytes(type);
+                convertCount = storage->getSize() / typeInfo.bytes;
             }
             else
             {
@@ -243,14 +246,13 @@
             return GL_INVALID_OPERATION;
         }
 
-        unsigned int indexTypeSize = gl::GetTypeBytes(destinationIndexType);
-        if (convertCount > std::numeric_limits<unsigned int>::max() / indexTypeSize)
+        if (convertCount > std::numeric_limits<unsigned int>::max() / destTypeInfo.bytes)
         {
-            ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize);
+            ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, destTypeInfo.bytes);
             return GL_OUT_OF_MEMORY;
         }
 
-        unsigned int bufferSizeRequired = convertCount * indexTypeSize;
+        unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes;
         if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type))
         {
             ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired);
@@ -274,7 +276,7 @@
 
         if (staticBuffer)
         {
-            streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType);
+            streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes;
             staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex,
                                                          translated->maxIndex, streamOffset);
         }
@@ -283,13 +285,13 @@
     translated->storage = directStorage ? storage : NULL;
     translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL;
     translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
-    translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType);
+    translated->startIndex = streamOffset / destTypeInfo.bytes;
     translated->startOffset = streamOffset;
     translated->indexType = destinationIndexType;
 
     if (storage)
     {
-        storage->promoteStaticUsage(count * gl::GetTypeBytes(type));
+        storage->promoteStaticUsage(count * typeInfo.bytes);
     }
 
     return GL_NO_ERROR;
diff --git a/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
index a813422..4cbe5d6 100644
--- a/src/libGLESv2/renderer/d3d/TextureD3D.cpp
+++ b/src/libGLESv2/renderer/d3d/TextureD3D.cpp
@@ -295,13 +295,13 @@
 
 bool TextureD3D_2D::isDepth(GLint level) const
 {
-    return gl::GetDepthBits(getInternalFormat(level)) > 0;
+    return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
 void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
 {
-    GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat
-                                                                       : gl::GetSizedInternalFormat(format, type);
+    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
     bool fastUnpacked = false;
 
     // Attempt a fast gpu copy of the pixel data to the surface
@@ -414,7 +414,7 @@
             sourceRect.height = height;
 
             mRenderer->copyImage(source, sourceRect,
-                                 gl::GetFormat(getBaseLevelInternalFormat()),
+                                 gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
                                  xoffset, yoffset, mTexStorage, level);
         }
     }
@@ -492,7 +492,8 @@
     // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
     // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
     // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
-    if (gl::GetDepthBits(getInternalFormat(0)) > 0 && mRenderer->getCurrentClientVersion() > 2)
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
+    if (formatInfo.depthBits > 0 && mRenderer->getCurrentClientVersion() > 2)
     {
         if (samplerState.compareMode == GL_NONE)
         {
@@ -886,13 +887,12 @@
 
 bool TextureD3D_Cube::isDepth(GLenum target, GLint level) const
 {
-    return gl::GetDepthBits(getInternalFormat(target, level)) > 0;
+    return gl::GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
 }
 
 void TextureD3D_Cube::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
 {
-    GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat
-                                                                       : gl::GetSizedInternalFormat(format, type);
+    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
 
     redefineImage(faceIndex, level, sizedInternalFormat, width, height);
 
@@ -929,8 +929,8 @@
 void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
 {
     int faceIndex = targetToIndex(target);
-    GLenum sizedInternalFormat = gl::IsSizedInternalFormat(format) ? format
-                                                               : gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+
     redefineImage(faceIndex, level, sizedInternalFormat, width, height);
 
     if (!mImageArray[faceIndex][level]->isRenderableFormat())
@@ -986,7 +986,7 @@
             sourceRect.y = y;
             sourceRect.height = height;
 
-            mRenderer->copyImage(source, sourceRect, gl::GetFormat(getBaseLevelInternalFormat()),
+            mRenderer->copyImage(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
                                  xoffset, yoffset, mTexStorage, target, level);
         }
     }
@@ -1502,13 +1502,13 @@
 
 bool TextureD3D_3D::isDepth(GLint level) const
 {
-    return gl::GetDepthBits(getInternalFormat(level)) > 0;
+    return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
 void TextureD3D_3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
 {
-    GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat
-                                                                       : gl::GetSizedInternalFormat(format, type);
+    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
     redefineImage(level, sizedInternalFormat, width, height, depth);
 
     bool fastUnpacked = false;
@@ -1602,7 +1602,7 @@
             sourceRect.height = height;
 
             mRenderer->copyImage(source, sourceRect,
-                                 gl::GetFormat(getBaseLevelInternalFormat()),
+                                 gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
                                  xoffset, yoffset, zoffset, mTexStorage, level);
         }
     }
@@ -2045,16 +2045,17 @@
 
 bool TextureD3D_2DArray::isDepth(GLint level) const
 {
-    return gl::GetDepthBits(getInternalFormat(level)) > 0;
+    return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
 }
 
 void TextureD3D_2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
 {
-    GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat
-                                                                       : gl::GetSizedInternalFormat(format, type);
+    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
+
     redefineImage(level, sizedInternalFormat, width, height, depth);
 
-    GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, width, height, unpack.alignment);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
 
     for (int i = 0; i < depth; i++)
     {
@@ -2068,7 +2069,8 @@
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
     redefineImage(level, format, width, height, depth);
 
-    GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
 
     for (int i = 0; i < depth; i++)
     {
@@ -2079,8 +2081,8 @@
 
 void TextureD3D_2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels)
 {
-    GLenum internalformat = getInternalFormat(level);
-    GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, type, width, height, unpack.alignment);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
 
     for (int i = 0; i < depth; i++)
     {
@@ -2096,7 +2098,8 @@
 
 void TextureD3D_2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
 {
-    GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
 
     for (int i = 0; i < depth; i++)
     {
@@ -2135,7 +2138,7 @@
             sourceRect.y = y;
             sourceRect.height = height;
 
-            mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0)),
+            mRenderer->copyImage(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
                                  xoffset, yoffset, zoffset, mTexStorage, level);
         }
     }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
index 446149c..f43c767 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
@@ -377,10 +377,10 @@
 
     D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc;
     source->GetDesc(&sourceSRVDesc);
-    GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format);
+    const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3d11_gl::GetInternalFormat(sourceSRVDesc.Format));
 
     GLenum shaderType = GL_NONE;
-    switch (gl::GetComponentType(sourceInternalFormat))
+    switch (sourceFormatInfo.componentType)
     {
       case GL_UNSIGNED_NORMALIZED:
       case GL_SIGNED_NORMALIZED:
@@ -520,7 +520,7 @@
 
     BlitParameters parameters = { 0 };
     parameters.mDestinationFormat = destFormat;
-    parameters.mSignedInteger = gl::GetComponentType(sourceInternalFormat) == GL_INT;
+    parameters.mSignedInteger = gl::GetInternalFormatInfo(sourceInternalFormat).componentType == GL_INT;
     parameters.m3DBlit = sourceArea.depth > 1;
 
     BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters);
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
index 656cd94..1d20fd9 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
@@ -219,34 +219,29 @@
                     return;
                 }
 
-                GLenum internalFormat = attachment->getInternalFormat();
-                GLenum actualFormat = attachment->getActualFormat();
-                GLenum componentType = gl::GetComponentType(internalFormat);
+                const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
+
                 if (clearParams.colorClearType == GL_FLOAT &&
-                    !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || componentType == GL_SIGNED_NORMALIZED))
+                    !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED))
                 {
                     ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-"
-                        "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, internalFormat);
+                        "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment,
+                        attachment->getInternalFormat());
                 }
 
-                GLuint internalRedBits = gl::GetRedBits(internalFormat);
-                GLuint internalGreenBits = gl::GetGreenBits(internalFormat);
-                GLuint internalBlueBits = gl::GetBlueBits(internalFormat);
-                GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat);
-
-                if ((internalRedBits   == 0 || !clearParams.colorMaskRed) &&
-                    (internalGreenBits == 0 || !clearParams.colorMaskGreen) &&
-                    (internalBlueBits  == 0 || !clearParams.colorMaskBlue) &&
-                    (internalAlphaBits == 0 || !clearParams.colorMaskAlpha))
+                if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
+                    (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
+                    (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
+                    (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
                 {
                     // Every channel either does not exist in the render target or is masked out
                     continue;
                 }
                 else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT ||
-                         (internalRedBits   > 0 && !clearParams.colorMaskRed)   ||
-                         (internalGreenBits > 0 && !clearParams.colorMaskGreen) ||
-                         (internalBlueBits  > 0 && !clearParams.colorMaskBlue)  ||
-                         (internalAlphaBits > 0 && !clearParams.colorMaskAlpha))
+                         (formatInfo.redBits   > 0 && !clearParams.colorMaskRed)   ||
+                         (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+                         (formatInfo.blueBits  > 0 && !clearParams.colorMaskBlue) ||
+                         (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
                 {
                     // A scissored or masked clear is required
                     MaskedRenderTarget maskAndRt;
@@ -269,19 +264,16 @@
                         return;
                     }
 
+                    const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
+
                     // Check if the actual format has a channel that the internal format does not and set them to the
                     // default values
-                    GLuint actualRedBits   = gl::GetRedBits(actualFormat);
-                    GLuint actualGreenBits = gl::GetGreenBits(actualFormat);
-                    GLuint actualBlueBits  = gl::GetBlueBits(actualFormat);
-                    GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat);
-
                     const float clearValues[4] =
                     {
-                        ((internalRedBits   == 0 && actualRedBits   > 0) ? 0.0f : clearParams.colorFClearValue.red),
-                        ((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
-                        ((internalBlueBits  == 0 && actualBlueBits  > 0) ? 0.0f : clearParams.colorFClearValue.blue),
-                        ((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
+                        ((formatInfo.redBits == 0 && actualFormatInfo.redBits   > 0) ? 0.0f : clearParams.colorFClearValue.red),
+                        ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
+                        ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits  > 0) ? 0.0f : clearParams.colorFClearValue.blue),
+                        ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
                     };
 
                     deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
@@ -302,9 +294,9 @@
                 return;
             }
 
-            GLenum actualFormat = attachment->getActualFormat();
+            const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
 
-            unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat)) - 1 : 0;
+            unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0;
             bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
 
             if (needScissoredClear || needMaskedStencilClear)
@@ -463,12 +455,12 @@
         if (i < rts.size())
         {
             RenderTarget11 *rt = rts[i].renderTarget;
-            GLint internalFormat = rt->getInternalFormat();
+            const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat());
 
-            blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && gl::GetRedBits(internalFormat)   > 0);
-            blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && gl::GetGreenBits(internalFormat) > 0);
-            blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && gl::GetBlueBits(internalFormat)  > 0);
-            blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && gl::GetAlphaBits(internalFormat) > 0);
+            blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && formatInfo.redBits   > 0);
+            blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && formatInfo.greenBits > 0);
+            blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && formatInfo.blueBits  > 0);
+            blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && formatInfo.alphaBits > 0);
         }
         else
         {
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
index 2165bec..c95f7a4 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
@@ -153,8 +153,9 @@
 void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                        GLint unpackAlignment, GLenum type, const void *input)
 {
-    GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment);
-    GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, type, width, height, unpackAlignment);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+    GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment);
     GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat);
 
     LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, type);
@@ -179,8 +180,9 @@
 void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
                                  const void *input)
 {
-    GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1);
-    GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 1);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+    GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
 
     GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat);
     GLuint outputBlockWidth = d3d11::GetBlockWidth(mDXGIFormat);
@@ -287,13 +289,12 @@
         }
 
         // determine the offset coordinate into the destination buffer
-        GLsizei rowOffset = gl::GetPixelBytes(mActualFormat) * xoffset;
+        GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset;
         void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;
 
-        GLenum format = gl::GetFormat(mInternalFormat);
-        GLenum type = gl::GetType(mInternalFormat);
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
 
-        mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+        mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
 
         unmap();
     }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
index 1ca456c..2e972f2 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -122,7 +122,7 @@
     float texelCenterX = 0.5f / static_cast<float>(destSize.width - 1);
     float texelCenterY = 0.5f / static_cast<float>(destSize.height - 1);
 
-    unsigned int bytesPerPixel = gl::GetPixelBytes(internalFormat);
+    unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes;
     unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
     unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
 
@@ -157,8 +157,8 @@
 
     // The SRV must be in the proper read format, which may be different from the destination format
     // EG: for half float data, we can load full precision floats with implicit conversion
-    GLenum unsizedFormat = gl::GetFormat(destinationFormat);
-    GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType);
+    GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format;
+    GLenum sourceFormat = gl::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat;
 
     DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(sourceFormat);
     ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
@@ -236,8 +236,7 @@
 
 ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const
 {
-    GLenum componentType = gl::GetComponentType(internalFormat);
-
+    GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType;
     if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED)
     {
         componentType = GL_FLOAT;
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
index 466a95a..bf471f2 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
@@ -2602,8 +2602,10 @@
 {
     ASSERT(getRendererExtensions().pixelBufferObject);
 
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+
     // sRGB formats do not work with D3D11 buffer SRVs
-    if (gl::GetColorEncoding(internalFormat) == GL_SRGB)
+    if (formatInfo.colorEncoding == GL_SRGB)
     {
         return false;
     }
@@ -2615,7 +2617,7 @@
     }
 
     // We skip all 3-channel formats since sometimes format support is missing
-    if (gl::GetComponentCount(internalFormat) == 3)
+    if (formatInfo.componentCount == 3)
     {
         return false;
     }
@@ -2955,25 +2957,19 @@
         inputPitch = static_cast<int>(mapping.RowPitch);
     }
 
-    GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(textureDesc.Format);
-    GLenum sourceFormat = gl::GetFormat(sourceInternalFormat);
-    GLenum sourceType = gl::GetType(sourceInternalFormat);
-
-    GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat);
-
-    if (sourceFormat == params.format && sourceType == params.type)
+    const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3d11_gl::GetInternalFormat(textureDesc.Format));
+    if (sourceFormatInfo.format == params.format && sourceFormatInfo.type == params.type)
     {
         unsigned char *dest = static_cast<unsigned char*>(pixelsOut) + params.offset;
         for (int y = 0; y < params.area.height; y++)
         {
-            memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourcePixelSize);
+            memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes);
         }
     }
     else
     {
-        GLenum destInternalFormat = gl::GetSizedInternalFormat(params.format, params.type);
-        GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat);
-
+        const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(params.format, params.type);
+        const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat);
         ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, params.format, params.type);
         if (fastCopyFunc)
         {
@@ -2982,8 +2978,8 @@
             {
                 for (int x = 0; x < params.area.width; x++)
                 {
-                    void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize;
-                    void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize;
+                    void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+                    void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourceFormatInfo.pixelBytes;
 
                     fastCopyFunc(src, dest);
                 }
@@ -2992,7 +2988,6 @@
         else
         {
             ColorReadFunction readFunc = d3d11::GetColorReadFunction(textureDesc.Format);
-            ColorWriteFunction writeFunc = gl::GetColorWriteFunction(params.format, params.type);
 
             unsigned char temp[16]; // Maximum size of any Color<T> type used.
             META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF)  &&
@@ -3003,13 +2998,13 @@
             {
                 for (int x = 0; x < params.area.width; x++)
                 {
-                    void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize;
-                    void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize;
+                    void *dest = static_cast<unsigned char*>(pixelsOut) + params.offset + y * params.outputPitch + x * destFormatInfo.pixelBytes;
+                    void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourceFormatInfo.pixelBytes;
 
                     // readFunc and writeFunc will be using the same type of color, CopyTexImage
                     // will not allow the copy otherwise.
                     readFunc(src, temp);
-                    writeFunc(temp, dest);
+                    destFormatTypeInfo.colorWriteFunction(temp, dest);
                 }
             }
         }
@@ -3108,9 +3103,8 @@
                        drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
                        drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
 
-    bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat()) > 0;
-    bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat()) > 0;
-    bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit);
+    const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat());
+    bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit);
 
     if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() &&
         !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
@@ -3184,7 +3178,7 @@
         }
         else
         {
-            GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat());
+            GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format;
             result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize,
                                         scissor, format, filter);
         }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
index 65e0e63..21d5b97 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -356,7 +356,7 @@
             Blit11 *blitter = mRenderer->getBlitter();
 
             blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL,
-                                 gl::GetFormat(source->getInternalFormat()), GL_LINEAR);
+                                 gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR);
         }
     }
 }
diff --git a/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
index a300c2e..506404b 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
@@ -780,34 +780,33 @@
     return map;
 }
 
-static const SwizzleFormatInfo GetSwizzleFormatInfo(GLenum internalFormat)
+static const SwizzleFormatInfo &GetSwizzleFormatInfo(GLenum internalFormat)
 {
     // Get the maximum sized component
     unsigned int maxBits = 1;
 
-    if (gl::IsFormatCompressed(internalFormat))
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+
+    if (formatInfo.compressed)
     {
-        unsigned int compressedBitsPerBlock = gl::GetPixelBytes(internalFormat) * 8;
-        unsigned int blockSize = gl::GetCompressedBlockWidth(internalFormat) *
-                                 gl::GetCompressedBlockHeight(internalFormat);
+        unsigned int compressedBitsPerBlock = formatInfo.pixelBytes * 8;
+        unsigned int blockSize = formatInfo.compressedBlockWidth * formatInfo.compressedBlockHeight;
         maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits);
     }
     else
     {
-        maxBits = std::max(maxBits, gl::GetAlphaBits(    internalFormat));
-        maxBits = std::max(maxBits, gl::GetRedBits(      internalFormat));
-        maxBits = std::max(maxBits, gl::GetGreenBits(    internalFormat));
-        maxBits = std::max(maxBits, gl::GetBlueBits(     internalFormat));
-        maxBits = std::max(maxBits, gl::GetLuminanceBits(internalFormat));
-        maxBits = std::max(maxBits, gl::GetDepthBits(    internalFormat));
+        maxBits = std::max(maxBits, formatInfo.alphaBits);
+        maxBits = std::max(maxBits, formatInfo.redBits);
+        maxBits = std::max(maxBits, formatInfo.greenBits);
+        maxBits = std::max(maxBits, formatInfo.blueBits);
+        maxBits = std::max(maxBits, formatInfo.luminanceBits);
+        maxBits = std::max(maxBits, formatInfo.depthBits);
     }
 
     maxBits = roundUp(maxBits, 8U);
 
-    GLenum componentType = gl::GetComponentType(internalFormat);
-
     const SwizzleInfoMap &map = GetSwizzleInfoMap();
-    SwizzleInfoMap::const_iterator iter = map.find(SwizzleSizeType(maxBits, componentType));
+    SwizzleInfoMap::const_iterator iter = map.find(SwizzleSizeType(maxBits, formatInfo.componentType));
 
     if (iter != map.end())
     {
@@ -1105,7 +1104,7 @@
 
 DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat)
 {
-    if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4)
+    if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetInternalFormatInfo(internalFormat).componentCount != 4)
     {
         const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat);
         return swizzleInfo.mTexFormat;
@@ -1118,7 +1117,7 @@
 
 DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat)
 {
-    if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4)
+    if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetInternalFormatInfo(internalFormat).componentCount != 4)
     {
         const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat);
         return swizzleInfo.mSRVFormat;
@@ -1131,7 +1130,7 @@
 
 DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat)
 {
-    if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4)
+    if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetInternalFormatInfo(internalFormat).componentCount != 4)
     {
         const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat);
         return swizzleInfo.mRTVFormat;
diff --git a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
index afc5628..2f1d031 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -233,7 +233,8 @@
     UINT formatSupport;
     if (SUCCEEDED(device->CheckFormatSupport(textureFormat, &formatSupport)))
     {
-        if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0)
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
         {
             textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
         }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
index e237c3b..24c26f3 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
@@ -387,7 +387,8 @@
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(zoffset == 0 && depth == 1);
 
-    GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+    GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
 
     LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat);
     ASSERT(loadFunction != NULL);
@@ -418,8 +419,9 @@
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(zoffset == 0 && depth == 1);
 
-    GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1);
-    GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 1);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+    GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
+    GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
 
     ASSERT(xoffset % d3d9::GetBlockWidth(mD3DFormat) == 0);
     ASSERT(yoffset % d3d9::GetBlockHeight(mD3DFormat) == 0);
diff --git a/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
index 0bb7694..cc2b98c 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -57,8 +57,8 @@
 
         bool requiresInitialization = false;
 
-        if (gl::GetDepthBits(internalFormat) > 0 ||
-            gl::GetStencilBits(internalFormat) > 0)
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+        if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
         {
             result = device->CreateDepthStencilSurface(width, height, renderFormat,
                                                        gl_d3d9::GetMultisampleType(supportedSamples),
diff --git a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
index 7b8a1d3..f422743 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
@@ -814,10 +814,11 @@
         // drawing is done.
         // http://code.google.com/p/angleproject/issues/detail?id=169
 
-        DWORD colorMask = gl_d3d9::ConvertColorMask(gl::GetRedBits(internalFormat)   > 0 && blendState.colorMaskRed,
-                                                    gl::GetGreenBits(internalFormat) > 0 && blendState.colorMaskGreen,
-                                                    gl::GetBlueBits(internalFormat)  > 0 && blendState.colorMaskBlue,
-                                                    gl::GetAlphaBits(internalFormat) > 0 && blendState.colorMaskAlpha);
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+        DWORD colorMask = gl_d3d9::ConvertColorMask(formatInfo.redBits   > 0 && blendState.colorMaskRed,
+                                                    formatInfo.greenBits > 0 && blendState.colorMaskGreen,
+                                                    formatInfo.blueBits  > 0 && blendState.colorMaskBlue,
+                                                    formatInfo.alphaBits > 0 && blendState.colorMaskAlpha);
         if (colorMask == 0 && !zeroColorMaskAllowed)
         {
             // Enable green channel, but set blending so nothing will be drawn.
@@ -1745,7 +1746,7 @@
     unsigned int stencilUnmasked = 0x0;
     if (clearParams.clearStencil && frameBuffer->hasStencil())
     {
-        unsigned int stencilSize = gl::GetStencilBits(frameBuffer->getStencilbuffer()->getActualFormat());
+        unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits;
         stencilUnmasked = (0x1 << stencilSize) - 1;
     }
 
@@ -1756,29 +1757,19 @@
     D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0);
     if (clearColor)
     {
-        gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
-        GLenum internalFormat = attachment->getInternalFormat();
-        GLenum actualFormat = attachment->getActualFormat();
+        const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
+        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
+        const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
 
-        GLuint internalRedBits = gl::GetRedBits(internalFormat);
-        GLuint internalGreenBits = gl::GetGreenBits(internalFormat);
-        GLuint internalBlueBits = gl::GetBlueBits(internalFormat);
-        GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat);
+        color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
+                              gl::unorm<8>((formatInfo.redBits   == 0 && actualFormatInfo.redBits   > 0) ? 0.0f : clearParams.colorFClearValue.red),
+                              gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
+                              gl::unorm<8>((formatInfo.blueBits  == 0 && actualFormatInfo.blueBits  > 0) ? 0.0f : clearParams.colorFClearValue.blue));
 
-        GLuint actualRedBits = gl::GetRedBits(actualFormat);
-        GLuint actualGreenBits = gl::GetGreenBits(actualFormat);
-        GLuint actualBlueBits = gl::GetBlueBits(actualFormat);
-        GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat);
-
-        color = D3DCOLOR_ARGB(gl::unorm<8>((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
-                              gl::unorm<8>((internalRedBits   == 0 && actualRedBits   > 0) ? 0.0f : clearParams.colorFClearValue.red),
-                              gl::unorm<8>((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
-                              gl::unorm<8>((internalBlueBits  == 0 && actualBlueBits  > 0) ? 0.0f : clearParams.colorFClearValue.blue));
-
-        if ((internalRedBits   > 0 && !clearParams.colorMaskRed) ||
-            (internalGreenBits > 0 && !clearParams.colorMaskGreen) ||
-            (internalBlueBits  > 0 && !clearParams.colorMaskBlue) ||
-            (internalAlphaBits > 0 && !clearParams.colorMaskAlpha))
+        if ((formatInfo.redBits   > 0 && !clearParams.colorMaskRed) ||
+            (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+            (formatInfo.blueBits  > 0 && !clearParams.colorMaskBlue) ||
+            (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
         {
             needMaskedColorClear = true;
         }
@@ -2772,27 +2763,20 @@
         inputPitch = lock.Pitch;
     }
 
-    GLenum sourceInternalFormat = d3d9_gl::GetInternalFormat(desc.Format);
-    GLenum sourceFormat = gl::GetFormat(sourceInternalFormat);
-    GLenum sourceType = gl::GetType(sourceInternalFormat);
-
-    GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat);
-
-    if (sourceFormat == format && sourceType == type)
+    const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3d9_gl::GetInternalFormat(desc.Format));
+    if (sourceFormatInfo.format == format && sourceFormatInfo.type == type)
     {
         // Direct copy possible
         unsigned char *dest = static_cast<unsigned char*>(pixels);
         for (int y = 0; y < rect.bottom - rect.top; y++)
         {
-            memcpy(dest + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourcePixelSize);
+            memcpy(dest + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes);
         }
     }
     else
     {
-        GLenum destInternalFormat = gl::GetSizedInternalFormat(format, type);
-        GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat);
-        GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat);
-
+        const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type);
+        const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat);
         ColorCopyFunction fastCopyFunc = d3d9::GetFastCopyFunction(desc.Format, format, type);
         if (fastCopyFunc)
         {
@@ -2801,8 +2785,8 @@
             {
                 for (int x = 0; x < rect.right - rect.left; x++)
                 {
-                    void *dest = static_cast<unsigned char*>(pixels) + y * outputPitch + x * destPixelSize;
-                    void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourcePixelSize;
+                    void *dest = static_cast<unsigned char*>(pixels) + y * outputPitch + x * destFormatInfo.pixelBytes;
+                    void *src = static_cast<unsigned char*>(source) + y * inputPitch + x * sourceFormatInfo.pixelBytes;
 
                     fastCopyFunc(src, dest);
                 }
@@ -2811,21 +2795,19 @@
         else
         {
             ColorReadFunction readFunc = d3d9::GetColorReadFunction(desc.Format);
-            ColorWriteFunction writeFunc = gl::GetColorWriteFunction(format, type);
 
             gl::ColorF temp;
-
             for (int y = 0; y < rect.bottom - rect.top; y++)
             {
                 for (int x = 0; x < rect.right - rect.left; x++)
                 {
-                    void *dest = reinterpret_cast<unsigned char*>(pixels) + y * outputPitch + x * destPixelSize;
-                    void *src = source + y * inputPitch + x * sourcePixelSize;
+                    void *dest = reinterpret_cast<unsigned char*>(pixels) + y * outputPitch + x * destFormatInfo.pixelBytes;
+                    void *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
 
                     // readFunc and writeFunc will be using the same type of color, CopyTexImage
                     // will not allow the copy otherwise.
                     readFunc(src, &temp);
-                    writeFunc(&temp, dest);
+                    destFormatTypeInfo.colorWriteFunction(&temp, dest);
                 }
             }
         }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
index b065ee8..8610a45 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -43,8 +43,8 @@
 {
     DWORD d3dusage = 0;
 
-    if (gl::GetDepthBits(internalformat) > 0 ||
-        gl::GetStencilBits(internalformat) > 0)
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+    if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
     {
         d3dusage |= D3DUSAGE_DEPTHSTENCIL;
     }
diff --git a/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
index e605cba..7cb840a 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
@@ -811,7 +811,7 @@
 bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format)
 {
     GLenum internalFormat = d3d9_gl::GetInternalFormat(d3dformat);
-    GLenum convertedFormat = gl::GetFormat(internalFormat);
+    GLenum convertedFormat = gl::GetInternalFormatInfo(internalFormat).format;
     return convertedFormat == format;
 }
 
diff --git a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
index 5e2db1f..358d387 100644
--- a/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -257,7 +257,8 @@
     gl::TextureCaps textureCaps;
 
     D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat);
-    if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0)
+    gl::InternalFormat formatInfo = gl::GetInternalFormatInfo(internalFormat);
+    if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
     {
         textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, renderFormat));
         textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, renderFormat));