Bug 1325741 - Handle uploads from RED/FLOAT to R16F, and others. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 23 Dec 2016 19:09:33 -0800
changeset 453626 444b9c77e5afab9b15833795a0650be6157d1d68
parent 453625 c77195ad565b28a619c565c591b58c0f8d13a442
child 540514 afc0b5dbb4b6084e934f45a9f0132b27575d5e8b
push id39721
push userbmo:jgilbert@mozilla.com
push dateSat, 24 Dec 2016 03:17:59 +0000
reviewersdaoshengmu
bugs1325741
milestone53.0a1
Bug 1325741 - Handle uploads from RED/FLOAT to R16F, and others. - r=daoshengmu MozReview-Commit-ID: 1ef1essxTNV
gfx/angle/src/libANGLE/formatutils.cpp
gfx/angle/src/libANGLE/formatutils.h
gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h
gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp
gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
gfx/angle/src/libANGLE/validationES.cpp
gfx/angle/src/libANGLE/validationES2.cpp
gfx/angle/src/libANGLE/validationES3.cpp
--- a/gfx/angle/src/libANGLE/formatutils.cpp
+++ b/gfx/angle/src/libANGLE/formatutils.cpp
@@ -713,91 +713,81 @@ const InternalFormat &GetInternalFormatI
     }
     else
     {
         static const InternalFormat defaultInternalFormat;
         return defaultInternalFormat;
     }
 }
 
-GLuint InternalFormat::computePixelBytes(GLenum formatType) const
-{
-    const auto &typeInfo = GetTypeInfo(formatType);
-    GLuint components    = typeInfo.specialInterpretation ? 1u : componentCount;
-    return components * typeInfo.bytes;
-}
-
-ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLenum formatType,
-                                                          GLsizei width,
-                                                          GLint alignment,
-                                                          GLint rowLength) const
+ErrorOrResult<GLuint> InternalFormat::computeRowPitch(GLsizei width,
+                                                      GLint alignment,
+                                                      GLint rowLength) const
 {
     // Compressed images do not use pack/unpack parameters.
     if (compressed)
     {
         ASSERT(rowLength == 0);
-        return computeCompressedImageSize(formatType, Extents(width, 1, 1));
+        return computeCompressedImageSize(Extents(width, 1, 1));
     }
 
     CheckedNumeric<GLuint> checkedWidth(rowLength > 0 ? rowLength : width);
-    CheckedNumeric<GLuint> checkedRowBytes = checkedWidth * computePixelBytes(formatType);
+    CheckedNumeric<GLuint> checkedRowBytes = checkedWidth * pixelBytes;
 
     ASSERT(alignment > 0 && isPow2(alignment));
     CheckedNumeric<GLuint> checkedAlignment(alignment);
     auto aligned = rx::roundUp(checkedRowBytes, checkedAlignment);
     ANGLE_TRY_CHECKED_MATH(aligned);
     return aligned.ValueOrDie();
 }
 
 ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLsizei height,
                                                         GLint imageHeight,
-                                                        GLuint rowPitch) const
+                                                        GLuint rowPitch)
 {
     GLuint rows =
         (imageHeight > 0 ? static_cast<GLuint>(imageHeight) : static_cast<GLuint>(height));
     CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
 
     auto depthPitch = checkedRowPitch * rows;
     ANGLE_TRY_CHECKED_MATH(depthPitch);
     return depthPitch.ValueOrDie();
 }
 
-ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLenum formatType,
-                                                            GLsizei width,
-                                                            GLsizei height,
-                                                            GLint alignment,
-                                                            GLint rowLength,
-                                                            GLint imageHeight) const
+ErrorOrResult<GLuint> InternalFormat::computeDepthPitch(GLsizei width,
+                                                        GLsizei height,
+                                                        GLint alignment,
+                                                        GLint rowLength,
+                                                        GLint imageHeight) const
 {
     GLuint rowPitch = 0;
-    ANGLE_TRY_RESULT(computeRowPitch(formatType, width, alignment, rowLength), rowPitch);
+    ANGLE_TRY_RESULT(computeRowPitch(width, alignment, rowLength), rowPitch);
     return computeDepthPitch(height, imageHeight, rowPitch);
 }
 
-ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(GLenum formatType,
-                                                                     const Extents &size) const
+ErrorOrResult<GLuint> InternalFormat::computeCompressedImageSize(const Extents &size) const
 {
     CheckedNumeric<GLuint> checkedWidth(size.width);
     CheckedNumeric<GLuint> checkedHeight(size.height);
     CheckedNumeric<GLuint> checkedDepth(size.depth);
     CheckedNumeric<GLuint> checkedBlockWidth(compressedBlockWidth);
     CheckedNumeric<GLuint> checkedBlockHeight(compressedBlockHeight);
 
     ASSERT(compressed);
     auto numBlocksWide = (checkedWidth + checkedBlockWidth - 1u) / checkedBlockWidth;
     auto numBlocksHigh = (checkedHeight + checkedBlockHeight - 1u) / checkedBlockHeight;
     auto bytes         = numBlocksWide * numBlocksHigh * pixelBytes * checkedDepth;
     ANGLE_TRY_CHECKED_MATH(bytes);
     return bytes.ValueOrDie();
 }
 
 ErrorOrResult<GLuint> InternalFormat::computeSkipBytes(GLuint rowPitch,
-                                                           GLuint depthPitch,
-                                                           const PixelStoreStateBase &state,
-                                                           bool is3D) const
+                                                       GLuint depthPitch,
+                                                       const PixelStoreStateBase &state,
+                                                       bool is3D) const
 {
     CheckedNumeric<GLuint> checkedRowPitch(rowPitch);
     CheckedNumeric<GLuint> checkedDepthPitch(depthPitch);
     CheckedNumeric<GLuint> checkedSkipImages(static_cast<GLuint>(state.skipImages));
     CheckedNumeric<GLuint> checkedSkipRows(static_cast<GLuint>(state.skipRows));
     CheckedNumeric<GLuint> checkedSkipPixels(static_cast<GLuint>(state.skipPixels));
     CheckedNumeric<GLuint> checkedPixelBytes(pixelBytes);
     auto checkedSkipImagesBytes = checkedSkipImages * checkedDepthPitch;
@@ -806,54 +796,53 @@ ErrorOrResult<GLuint> InternalFormat::co
         checkedSkipImagesBytes = 0;
     }
     auto skipBytes = checkedSkipImagesBytes + checkedSkipRows * checkedRowPitch +
                      checkedSkipPixels * checkedPixelBytes;
     ANGLE_TRY_CHECKED_MATH(skipBytes);
     return skipBytes.ValueOrDie();
 }
 
-ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(
-    GLenum formatType,
-    const Extents &size,
-    const PixelStoreStateBase &state,
-    bool is3D) const
+ErrorOrResult<GLuint> InternalFormat::computePackUnpackEndByte(const Extents &size,
+                                                               const PixelStoreStateBase &state,
+                                                               bool is3D) const
 {
     GLuint rowPitch = 0;
-    ANGLE_TRY_RESULT(computeRowPitch(formatType, size.width, state.alignment, state.rowLength),
+    ANGLE_TRY_RESULT(computeRowPitch(size.width, state.alignment, state.rowLength),
                      rowPitch);
 
     GLuint depthPitch = 0;
     if (is3D)
     {
         ANGLE_TRY_RESULT(computeDepthPitch(size.height, state.imageHeight, rowPitch), depthPitch);
     }
 
     CheckedNumeric<GLuint> checkedCopyBytes = 0;
     if (compressed)
     {
-        ANGLE_TRY_RESULT(computeCompressedImageSize(formatType, size), checkedCopyBytes);
+        ANGLE_TRY_RESULT(computeCompressedImageSize(size), checkedCopyBytes);
     }
     else if (size.height != 0 && (!is3D || size.depth != 0))
     {
-        CheckedNumeric<GLuint> bytes = computePixelBytes(formatType);
+        CheckedNumeric<GLuint> bytes = pixelBytes;
         checkedCopyBytes += size.width * bytes;
 
         CheckedNumeric<GLuint> heightMinusOne = size.height - 1;
         checkedCopyBytes += heightMinusOne * rowPitch;
 
         if (is3D)
         {
             CheckedNumeric<GLuint> depthMinusOne = size.depth - 1;
             checkedCopyBytes += depthMinusOne * depthPitch;
         }
     }
 
     CheckedNumeric<GLuint> checkedSkipBytes = 0;
-    ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D), checkedSkipBytes);
+    ANGLE_TRY_RESULT(computeSkipBytes(rowPitch, depthPitch, state, is3D),
+                     checkedSkipBytes);
 
     CheckedNumeric<GLuint> endByte = checkedCopyBytes + checkedSkipBytes;
 
     ANGLE_TRY_CHECKED_MATH(endByte);
     return endByte.ValueOrDie();
 }
 
 GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
--- a/gfx/angle/src/libANGLE/formatutils.h
+++ b/gfx/angle/src/libANGLE/formatutils.h
@@ -43,44 +43,38 @@ struct Type
     bool specialInterpretation;
 };
 const Type &GetTypeInfo(GLenum type);
 
 struct InternalFormat
 {
     InternalFormat();
 
-    GLuint computePixelBytes(GLenum formatType) const;
-
-    ErrorOrResult<GLuint> computeRowPitch(GLenum formatType,
-                                          GLsizei width,
+    ErrorOrResult<GLuint> computeRowPitch(GLsizei width,
                                           GLint alignment,
                                           GLint rowLength) const;
-    ErrorOrResult<GLuint> computeDepthPitch(GLsizei height,
-                                            GLint imageHeight,
-                                            GLuint rowPitch) const;
-    ErrorOrResult<GLuint> computeDepthPitch(GLenum formatType,
-                                            GLsizei width,
+    static ErrorOrResult<GLuint> computeDepthPitch(GLsizei height,
+                                                   GLint imageHeight,
+                                                   GLuint rowPitch);
+    ErrorOrResult<GLuint> computeDepthPitch(GLsizei width,
                                             GLsizei height,
                                             GLint alignment,
                                             GLint rowLength,
                                             GLint imageHeight) const;
 
-    ErrorOrResult<GLuint> computeCompressedImageSize(GLenum formatType,
-                                                     const Extents &size) const;
+    ErrorOrResult<GLuint> computeCompressedImageSize(const Extents &size) const;
 
     ErrorOrResult<GLuint> computeSkipBytes(GLuint rowPitch,
                                            GLuint depthPitch,
                                            const PixelStoreStateBase &state,
                                            bool is3D) const;
 
-    ErrorOrResult<GLuint> computePackUnpackEndByte(GLenum formatType,
-                                                       const Extents &size,
-                                                       const PixelStoreStateBase &state,
-                                                       bool is3D) const;
+    ErrorOrResult<GLuint> computePackUnpackEndByte(const Extents &size,
+                                                   const PixelStoreStateBase &state,
+                                                   bool is3D) const;
 
     bool isLUMA() const;
     GLenum getReadPixelsFormat() const;
     GLenum getReadPixelsType() const;
 
     bool operator==(const InternalFormat &other) const;
     bool operator!=(const InternalFormat &other) const;
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -235,25 +235,23 @@ GLenum FramebufferD3D::getImplementation
 gl::Error FramebufferD3D::readPixels(ContextImpl *context,
                                      const gl::Rectangle &area,
                                      GLenum format,
                                      GLenum type,
                                      GLvoid *pixels) const
 {
     const gl::PixelPackState &packState = context->getGLState().getPackState();
 
-    GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
-    const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
 
     GLuint outputPitch = 0;
-    ANGLE_TRY_RESULT(
-        sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength),
-        outputPitch);
+    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, packState.alignment, packState.rowLength),
+                     outputPitch);
     GLuint outputSkipBytes = 0;
-    ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false),
+    ANGLE_TRY_RESULT(formatInfo.computeSkipBytes(outputPitch, 0, packState, false),
                      outputSkipBytes);
 
     return readPixelsImpl(area, format, type, outputPitch, packState,
                           reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes);
 }
 
 gl::Error FramebufferD3D::blit(ContextImpl *context,
                                const gl::Rectangle &sourceArea,
--- a/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
@@ -5,16 +5,17 @@
 //
 
 // Image.h: Implements the rx::Image class, an abstract base class for the
 // renderer-specific classes which will define the interface to the underlying
 // surfaces or resources.
 
 #include "libANGLE/renderer/d3d/ImageD3D.h"
 
+#include "libANGLE/formatutils.h"
 #include "libANGLE/Framebuffer.h"
 #include "libANGLE/FramebufferAttachment.h"
 #include "libANGLE/renderer/d3d/FramebufferD3D.h"
 #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
 
 namespace rx
 {
 
@@ -24,9 +25,18 @@ ImageD3D::ImageD3D()
       mDepth(0),
       mInternalFormat(GL_NONE),
       mRenderable(false),
       mTarget(GL_NONE),
       mDirty(false)
 {
 }
 
+GLenum
+ImageD3D::getSizedInputFormat(GLenum inputType) const
+{
+    const auto &internalFormat = gl::GetInternalFormatInfo(mInternalFormat);
+    const auto &unsizedInternalFormat = internalFormat.format;
+    const auto &sizedInputFormat = gl::GetSizedInternalFormat(unsizedInternalFormat, inputType);
+    return sizedInputFormat;
+}
+
 }  // namespace rx
--- a/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -46,16 +46,18 @@ class ImageD3D : angle::NonCopyable
     bool isRenderableFormat() const { return mRenderable; }
 
     void markDirty() { mDirty = true; }
     void markClean() { mDirty = false; }
     virtual bool isDirty() const = 0;
 
     virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
 
+    GLenum getSizedInputFormat(GLenum inputType) const;
+
     virtual gl::Error loadData(const gl::Box &area,
                                const gl::PixelUnpackState &unpack,
                                GLenum type,
                                const void *input,
                                bool applySkipImages) = 0;
     virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
 
     virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
--- a/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -2361,25 +2361,25 @@ gl::Error TextureD3D_2DArray::setImage(G
                                        const gl::Extents &size,
                                        GLenum format,
                                        GLenum type,
                                        const gl::PixelUnpackState &unpack,
                                        const uint8_t *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
+    GLint level = static_cast<GLint>(imageLevel);
     GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
-
-    GLint level = static_cast<GLint>(imageLevel);
     redefineImage(level, sizedInternalFormat, size);
 
-    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
-    GLsizei inputDepthPitch              = 0;
-    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment,
-                                                  unpack.rowLength, unpack.imageHeight),
+    const auto sizedInputFormat = gl::GetSizedInternalFormat(format, type);
+    const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
+    GLsizei inputDepthPitch               = 0;
+    ANGLE_TRY_RESULT(inputFormat.computeDepthPitch(size.width, size.height, unpack.alignment,
+                                                   unpack.rowLength, unpack.imageHeight),
                      inputDepthPitch);
 
     for (int i = 0; i < size.depth; i++)
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
         ANGLE_TRY(setImageImpl(index, type, unpack, pixels, layerOffset));
     }
@@ -2391,21 +2391,22 @@ gl::Error TextureD3D_2DArray::setSubImag
                                           size_t imageLevel,
                                           const gl::Box &area,
                                           GLenum format,
                                           GLenum type,
                                           const gl::PixelUnpackState &unpack,
                                           const uint8_t *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
-    GLint level                          = static_cast<GLint>(imageLevel);
-    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
-    GLsizei inputDepthPitch              = 0;
-    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment,
-                                                  unpack.rowLength, unpack.imageHeight),
+    GLint level                           = static_cast<GLint>(imageLevel);
+    const auto sizedInputFormat = gl::GetSizedInternalFormat(format, type);
+    const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
+    GLsizei inputDepthPitch               = 0;
+    ANGLE_TRY_RESULT(inputFormat.computeDepthPitch(area.width, area.height, unpack.alignment,
+                                                   unpack.rowLength, unpack.imageHeight),
                      inputDepthPitch);
 
     for (int i = 0; i < area.depth; i++)
     {
         int layer = area.z + i;
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
@@ -2430,17 +2431,17 @@ gl::Error TextureD3D_2DArray::setCompres
 
     GLint level = static_cast<GLint>(imageLevel);
     // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
     redefineImage(level, internalFormat, size);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
     GLsizei inputDepthPitch              = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0, 0),
+        formatInfo.computeDepthPitch(size.width, size.height, 1, 0, 0),
         inputDepthPitch);
 
     for (int i = 0; i < size.depth; i++)
     {
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
         ANGLE_TRY(setCompressedImageImpl(index, unpack, pixels, layerOffset));
@@ -2452,17 +2453,17 @@ gl::Error TextureD3D_2DArray::setCompres
 gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
                                                     const gl::PixelUnpackState &unpack, size_t imageSize, const uint8_t *pixels)
 {
     ASSERT(target == GL_TEXTURE_2D_ARRAY);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
     GLsizei inputDepthPitch              = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0, 0),
+        formatInfo.computeDepthPitch(area.width, area.height, 1, 0, 0),
         inputDepthPitch);
 
     for (int i = 0; i < area.depth; i++)
     {
         int layer = area.z + i;
         const ptrdiff_t layerOffset = (inputDepthPitch * i);
 
         gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -224,39 +224,40 @@ DXGI_FORMAT Image11::getDXGIFormat() con
     return mDXGIFormat;
 }
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as
 // format/type at input
 // into the target pixel rectangle.
 gl::Error Image11::loadData(const gl::Box &area,
                             const gl::PixelUnpackState &unpack,
-                            GLenum type,
+                            GLenum inputType,
                             const void *input,
                             bool applySkipImages)
 {
-    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
+    const auto sizedInputFormat = getSizedInputFormat(inputType);
+    const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
     GLuint inputRowPitch                 = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+        inputFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
         inputRowPitch);
     GLuint inputDepthPitch = 0;
-    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch),
+    ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, inputRowPitch),
                      inputDepthPitch);
     GLuint inputSkipBytes = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
+        inputFormat.computeSkipBytes(inputRowPitch, inputDepthPitch, unpack, applySkipImages),
         inputSkipBytes);
 
     const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
     GLuint outputPixelSize                      = dxgiFormatInfo.pixelBytes;
 
     const d3d11::Format &d3dFormatInfo =
         d3d11::Format::Get(mInternalFormat, mRenderer->getRenderer11DeviceCaps());
-    LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(type).loadFunction;
+    LoadImageFunction loadFunction = d3dFormatInfo.getLoadFunctions()(inputType).loadFunction;
 
     D3D11_MAPPED_SUBRESOURCE mappedImage;
     ANGLE_TRY(map(D3D11_MAP_WRITE, &mappedImage));
 
     uint8_t *offsetMappedData = (reinterpret_cast<uint8_t *>(mappedImage.pData) +
                                  (area.y * mappedImage.RowPitch + area.x * outputPixelSize +
                                   area.z * mappedImage.DepthPitch));
     loadFunction(area.width, area.height, area.depth,
@@ -267,19 +268,19 @@ gl::Error Image11::loadData(const gl::Bo
 
     return gl::NoError();
 }
 
 gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
 {
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch                = 0;
-    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch);
+    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, 1, 0), inputRowPitch);
     GLsizei inputDepthPitch = 0;
-    ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch);
+    ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, 0, inputRowPitch), inputDepthPitch);
 
     const d3d11::DXGIFormatSize &dxgiFormatInfo = d3d11::GetDXGIFormatSizeInfo(mDXGIFormat);
     GLuint outputPixelSize                      = dxgiFormatInfo.pixelBytes;
     GLuint outputBlockWidth                     = dxgiFormatInfo.blockWidth;
     GLuint outputBlockHeight                    = dxgiFormatInfo.blockHeight;
 
     ASSERT(area.x % outputBlockWidth == 0);
     ASSERT(area.y % outputBlockHeight == 0);
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -583,74 +583,74 @@ gl::Error TextureStorage11::copyToStorag
     dest11->markDirty();
 
     return gl::NoError();
 }
 
 gl::Error TextureStorage11::setData(const gl::ImageIndex &index,
                                     ImageD3D *image,
                                     const gl::Box *destBox,
-                                    GLenum type,
+                                    GLenum inputType,
                                     const gl::PixelUnpackState &unpack,
                                     const uint8_t *pixelData)
 {
     ASSERT(!image->isDirty());
 
     markLevelDirty(index.mipIndex);
 
     ID3D11Resource *resource = nullptr;
     ANGLE_TRY(getResource(&resource));
     ASSERT(resource);
 
     UINT destSubresource = getSubresourceIndex(index);
 
-    const gl::InternalFormat &internalFormatInfo =
-        gl::GetInternalFormatInfo(image->getInternalFormat());
+    const auto sizedInputFormat = image->getSizedInputFormat(inputType);
+    const gl::InternalFormat &inputFormat = gl::GetInternalFormatInfo(sizedInputFormat);
 
     gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex),
                      getLevelDepth(index.mipIndex));
     bool fullUpdate = (destBox == nullptr || *destBox == levelBox);
-    ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
+    ASSERT(inputFormat.depthBits == 0 || fullUpdate);
 
     // TODO(jmadill): Handle compressed formats
     // Compressed formats have different load syntax, so we'll have to handle them with slightly
     // different logic. Will implemnent this in a follow-up patch, and ensure we do not use SetData
     // with compressed formats in the calling logic.
-    ASSERT(!internalFormatInfo.compressed);
+    ASSERT(!inputFormat.compressed);
 
     const int width    = destBox ? destBox->width : static_cast<int>(image->getWidth());
     const int height   = destBox ? destBox->height : static_cast<int>(image->getHeight());
     const int depth    = destBox ? destBox->depth : static_cast<int>(image->getDepth());
     GLuint srcRowPitch = 0;
     ANGLE_TRY_RESULT(
-        internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength),
+        inputFormat.computeRowPitch(width, unpack.alignment, unpack.rowLength),
         srcRowPitch);
     GLuint srcDepthPitch = 0;
-    ANGLE_TRY_RESULT(internalFormatInfo.computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
+    ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(height, unpack.imageHeight, srcRowPitch),
                      srcDepthPitch);
     GLuint srcSkipBytes = 0;
     ANGLE_TRY_RESULT(
-        internalFormatInfo.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
+        inputFormat.computeSkipBytes(srcRowPitch, srcDepthPitch, unpack, index.is3D()),
         srcSkipBytes);
 
     const d3d11::Format &d3d11Format =
         d3d11::Format::Get(image->getInternalFormat(), mRenderer->getRenderer11DeviceCaps());
     const d3d11::DXGIFormatSize &dxgiFormatInfo =
         d3d11::GetDXGIFormatSizeInfo(d3d11Format.texFormat);
 
     const size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
 
     UINT bufferRowPitch   = static_cast<unsigned int>(outputPixelSize) * width;
     UINT bufferDepthPitch = bufferRowPitch * height;
 
     const size_t neededSize        = bufferDepthPitch * depth;
     MemoryBuffer *conversionBuffer = nullptr;
     const uint8_t *data            = nullptr;
 
-    LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(type);
+    LoadImageFunctionInfo loadFunctionInfo = d3d11Format.getLoadFunctions()(inputType);
     if (loadFunctionInfo.requiresConversion)
     {
         ANGLE_TRY(mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer));
         loadFunctionInfo.loadFunction(width, height, depth, pixelData + srcSkipBytes, srcRowPitch,
                                       srcDepthPitch, conversionBuffer->data(), bufferRowPitch,
                                       bufferDepthPitch);
         data = conversionBuffer->data();
     }
--- a/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -470,27 +470,27 @@ gl::Error Image9::copyToSurface(IDirect3
 
     return gl::Error(GL_NO_ERROR);
 }
 
 // Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
 // into the target pixel rectangle.
 gl::Error Image9::loadData(const gl::Box &area,
                            const gl::PixelUnpackState &unpack,
-                           GLenum type,
+                           GLenum inputType,
                            const void *input,
                            bool applySkipImages)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(area.z == 0 && area.depth == 1);
-
+    ASSERT(getSizedInputFormat(inputType) == mInternalFormat);
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLuint inputRowPitch                 = 0;
     ANGLE_TRY_RESULT(
-        formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+        formatInfo.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
         inputRowPitch);
     ASSERT(!applySkipImages);
     ASSERT(unpack.skipPixels == 0);
     ASSERT(unpack.skipRows == 0);
 
     const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
     ASSERT(d3dFormatInfo.loadFunction != NULL);
 
@@ -518,17 +518,17 @@ gl::Error Image9::loadData(const gl::Box
 
 gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
 {
     // 3D textures are not supported by the D3D9 backend.
     ASSERT(area.z == 0 && area.depth == 1);
 
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
     GLsizei inputRowPitch                = 0;
-    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0), inputRowPitch);
+    ANGLE_TRY_RESULT(formatInfo.computeRowPitch(area.width, 1, 0), inputRowPitch);
     GLsizei inputDepthPitch = 0;
     ANGLE_TRY_RESULT(formatInfo.computeDepthPitch(area.height, 0, inputDepthPitch),
                      inputDepthPitch);
 
     const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
 
     ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
     ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
--- a/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
+++ b/gfx/angle/src/libANGLE/renderer/gl/FramebufferGL.cpp
@@ -489,17 +489,17 @@ gl::Error FramebufferGL::readPixelsRowBy
                                                       const gl::PixelPackState &pack,
                                                       GLvoid *pixels) const
 {
     intptr_t offset = reinterpret_cast<intptr_t>(pixels);
 
     const gl::InternalFormat &glFormat =
         gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
     GLuint rowBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, pack.alignment, pack.rowLength),
                      rowBytes);
     GLuint skipBytes = 0;
     ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
 
     gl::PixelPackState directPack;
     directPack.pixelBuffer = pack.pixelBuffer;
     directPack.alignment   = 1;
     mStateManager->setPixelPackState(directPack);
@@ -520,17 +520,17 @@ gl::Error FramebufferGL::readPixelsPaddi
                                                      GLenum format,
                                                      GLenum type,
                                                      const gl::PixelPackState &pack,
                                                      GLvoid *pixels) const
 {
     const gl::InternalFormat &glFormat =
         gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
     GLuint rowBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, pack.alignment, pack.rowLength),
                      rowBytes);
     GLuint skipBytes = 0;
     ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
 
     // Get all by the last row
     if (area.height > 1)
     {
         mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
--- a/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp
+++ b/gfx/angle/src/libANGLE/renderer/gl/TextureGL.cpp
@@ -320,21 +320,21 @@ gl::Error TextureGL::setSubImageRowByRow
     gl::PixelUnpackState directUnpack;
     directUnpack.pixelBuffer = unpack.pixelBuffer;
     directUnpack.alignment   = 1;
     mStateManager->setPixelUnpackState(directUnpack);
     directUnpack.pixelBuffer.set(nullptr);
 
     const gl::InternalFormat &glFormat =
         gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
-    GLuint rowBytes                      = 0;
-    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+    GLuint rowBytes = 0;
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
                      rowBytes);
     GLuint imageBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
+    ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
                      imageBytes);
     bool useTexImage3D = UseTexImage3D(mState.mTarget);
     GLuint skipBytes   = 0;
     ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
                      skipBytes);
 
     const uint8_t *pixelsWithSkip = pixels + skipBytes;
     if (useTexImage3D)
@@ -372,20 +372,20 @@ gl::Error TextureGL::setSubImagePaddingW
                                                   GLenum format,
                                                   GLenum type,
                                                   const gl::PixelUnpackState &unpack,
                                                   const uint8_t *pixels)
 {
     const gl::InternalFormat &glFormat =
         gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
     GLuint rowBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength),
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(area.width, unpack.alignment, unpack.rowLength),
                      rowBytes);
     GLuint imageBytes = 0;
-    ANGLE_TRY_RESULT(glFormat.computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
+    ANGLE_TRY_RESULT(gl::InternalFormat::computeDepthPitch(area.height, unpack.imageHeight, rowBytes),
                      imageBytes);
     bool useTexImage3D = UseTexImage3D(mState.mTarget);
     GLuint skipBytes   = 0;
     ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, imageBytes, unpack, useTexImage3D),
                      skipBytes);
 
     gl::PixelUnpackState directUnpack;
     directUnpack.pixelBuffer = unpack.pixelBuffer;
@@ -634,18 +634,17 @@ gl::Error TextureGL::setStorage(GLenum t
                                       std::max(size.height >> level, 1),
                                       1);
 
                 if (mState.mTarget == GL_TEXTURE_2D)
                 {
                     if (internalFormatInfo.compressed)
                     {
                         GLuint dataSize = 0;
-                        ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
-                                             GL_UNSIGNED_BYTE, levelSize),
+                        ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(levelSize),
                                          dataSize);
                         mFunctions->compressedTexImage2D(target, static_cast<GLint>(level),
                                                          texStorageFormat.internalFormat,
                                                          levelSize.width, levelSize.height, 0,
                                                          static_cast<GLsizei>(dataSize), nullptr);
                     }
                     else
                     {
@@ -658,17 +657,17 @@ gl::Error TextureGL::setStorage(GLenum t
                 else if (mState.mTarget == GL_TEXTURE_CUBE_MAP)
                 {
                     for (GLenum face = gl::FirstCubeMapTextureTarget; face <= gl::LastCubeMapTextureTarget; face++)
                     {
                         if (internalFormatInfo.compressed)
                         {
                             GLuint dataSize = 0;
                             ANGLE_TRY_RESULT(internalFormatInfo.computeCompressedImageSize(
-                                                 GL_UNSIGNED_BYTE, levelSize),
+                                                 levelSize),
                                              dataSize);
                             mFunctions->compressedTexImage2D(
                                 face, static_cast<GLint>(level), texStorageFormat.internalFormat,
                                 levelSize.width, levelSize.height, 0,
                                 static_cast<GLsizei>(dataSize), nullptr);
                         }
                         else
                         {
@@ -709,17 +708,17 @@ gl::Error TextureGL::setStorage(GLenum t
                 gl::Extents levelSize(
                     std::max(size.width >> i, 1), std::max(size.height >> i, 1),
                     mState.mTarget == GL_TEXTURE_3D ? std::max(size.depth >> i, 1) : size.depth);
 
                 if (internalFormatInfo.compressed)
                 {
                     GLuint dataSize = 0;
                     ANGLE_TRY_RESULT(
-                        internalFormatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, levelSize),
+                        internalFormatInfo.computeCompressedImageSize(levelSize),
                         dataSize);
                     mFunctions->compressedTexImage3D(target, i, texStorageFormat.internalFormat,
                                                      levelSize.width, levelSize.height,
                                                      levelSize.depth, 0,
                                                      static_cast<GLsizei>(dataSize), nullptr);
                 }
                 else
                 {
--- a/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
+++ b/gfx/angle/src/libANGLE/renderer/gl/renderergl_utils.cpp
@@ -1018,20 +1018,20 @@ gl::ErrorOrResult<bool> ShouldApplyLastR
     // last byte read or written. If it is past the end of the buffer, we will need to use the
     // workaround otherwise the driver will generate INVALID_OPERATION and not do the operation.
     CheckedNumeric<size_t> checkedEndByte;
     CheckedNumeric<size_t> pixelBytes;
     size_t rowPitch;
 
     const gl::InternalFormat &glFormat =
         gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
-    ANGLE_TRY_RESULT(glFormat.computePackUnpackEndByte(type, size, state, is3D), checkedEndByte);
-    ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, size.width, state.alignment, state.rowLength),
+    ANGLE_TRY_RESULT(glFormat.computePackUnpackEndByte(size, state, is3D), checkedEndByte);
+    ANGLE_TRY_RESULT(glFormat.computeRowPitch(size.width, state.alignment, state.rowLength),
                      rowPitch);
-    pixelBytes = glFormat.computePixelBytes(type);
+    pixelBytes = glFormat.pixelBytes;
 
     checkedEndByte += reinterpret_cast<intptr_t>(pixels);
 
     // At this point checkedEndByte is the actual last byte read.
     // The driver adds an extra row padding (if any), mimic it.
     ANGLE_TRY_CHECKED_MATH(pixelBytes);
     if (pixelBytes.ValueOrDie() * size.width < rowPitch)
     {
--- a/gfx/angle/src/libANGLE/validationES.cpp
+++ b/gfx/angle/src/libANGLE/validationES.cpp
@@ -247,17 +247,17 @@ bool ValidateReadPixelsBase(ValidationCo
 
     // ..  the data would be packed to the buffer object such that the memory writes required
     // would exceed the data store size.
     GLenum sizedInternalFormat       = GetSizedInternalFormat(format, type);
     const InternalFormat &formatInfo = GetInternalFormatInfo(sizedInternalFormat);
     const gl::Extents size(width, height, 1);
     const auto &pack = context->getGLState().getPackState();
 
-    auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, pack, false);
+    auto endByteOrErr = formatInfo.computePackUnpackEndByte(size, pack, false);
     if (endByteOrErr.isError())
     {
         context->handleError(endByteOrErr.getError());
         return false;
     }
 
     size_t endByte = endByteOrErr.getResult();
     if (bufSize >= 0)
@@ -1533,17 +1533,17 @@ bool ValidImageDataSize(ValidationContex
     // ...the data would be unpacked from the buffer object such that the memory reads required
     // would exceed the data store size.
     GLenum sizedFormat                   = GetSizedInternalFormat(internalFormat, type);
     const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
     const gl::Extents size(width, height, depth);
     const auto &unpack = context->getGLState().getUnpackState();
 
     bool targetIs3D   = textureTarget == GL_TEXTURE_3D || textureTarget == GL_TEXTURE_2D_ARRAY;
-    auto endByteOrErr = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
+    auto endByteOrErr = formatInfo.computePackUnpackEndByte(size, unpack, targetIs3D);
     if (endByteOrErr.isError())
     {
         context->handleError(endByteOrErr.getError());
         return false;
     }
 
     GLuint endByte = endByteOrErr.getResult();
 
--- a/gfx/angle/src/libANGLE/validationES2.cpp
+++ b/gfx/angle/src/libANGLE/validationES2.cpp
@@ -2111,17 +2111,17 @@ bool ValidateCompressedTexImage2D(Contex
                                              data))
         {
             return false;
         }
     }
 
     const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
     auto blockSizeOrErr =
-        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
+        formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
     if (blockSizeOrErr.isError())
     {
         context->handleError(blockSizeOrErr.getError());
         return false;
     }
 
     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
     {
@@ -2159,17 +2159,17 @@ bool ValidateCompressedTexSubImage2D(Con
                                              data))
         {
             return false;
         }
     }
 
     const InternalFormat &formatInfo = GetInternalFormatInfo(format);
     auto blockSizeOrErr =
-        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, 1));
+        formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
     if (blockSizeOrErr.isError())
     {
         context->handleError(blockSizeOrErr.getError());
         return false;
     }
 
     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
     {
--- a/gfx/angle/src/libANGLE/validationES3.cpp
+++ b/gfx/angle/src/libANGLE/validationES3.cpp
@@ -1186,17 +1186,17 @@ bool ValidateCompressedTexImage3D(Contex
     const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
     if (!formatInfo.compressed)
     {
         context->handleError(Error(GL_INVALID_ENUM, "Not a valid compressed texture format"));
         return false;
     }
 
     auto blockSizeOrErr =
-        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
+        formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
     if (blockSizeOrErr.isError())
     {
         context->handleError(Error(GL_INVALID_VALUE));
         return false;
     }
     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
     {
         context->handleError(Error(GL_INVALID_VALUE));
@@ -1595,17 +1595,17 @@ bool ValidateCompressedTexSubImage3D(Con
     if (context->getClientMajorVersion() < 3)
     {
         context->handleError(Error(GL_INVALID_OPERATION));
         return false;
     }
 
     const InternalFormat &formatInfo = GetInternalFormatInfo(format);
     auto blockSizeOrErr =
-        formatInfo.computeCompressedImageSize(GL_UNSIGNED_BYTE, gl::Extents(width, height, depth));
+        formatInfo.computeCompressedImageSize(gl::Extents(width, height, depth));
     if (blockSizeOrErr.isError())
     {
         context->handleError(blockSizeOrErr.getError());
         return false;
     }
     if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
     {
         context->handleError(Error(GL_INVALID_VALUE));