Merge all gl::Texture* classes.

The validation for sampler completeness had a lot of duplicated code.
The special cases have been merged into the base class by checking mTarget.

BUG=angle:681

Change-Id: I11d94c1432f8fc70a1edaaf8228bbc43c3c8fff3
Reviewed-on: https://chromium-review.googlesource.com/236932
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tested-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/Texture.cpp b/src/libANGLE/Texture.cpp
index cd86bee..105eaca 100644
--- a/src/libANGLE/Texture.cpp
+++ b/src/libANGLE/Texture.cpp
@@ -4,9 +4,7 @@
 // found in the LICENSE file.
 //
 
-// Texture.cpp: Implements the gl::Texture class and its derived classes
-// Texture2D and TextureCubeMap. Implements GL texture objects and related
-// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
+// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
 
 #include "libANGLE/Texture.h"
 #include "libANGLE/Context.h"
@@ -87,28 +85,132 @@
 
 size_t Texture::getWidth(GLenum target, size_t level) const
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
     return getImageDesc(ImageIdentifier(target, level)).size.width;
 }
 
 size_t Texture::getHeight(GLenum target, size_t level) const
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
     return getImageDesc(ImageIdentifier(target, level)).size.height;
 }
 
 size_t Texture::getDepth(GLenum target, size_t level) const
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
     return getImageDesc(ImageIdentifier(target, level)).size.depth;
 }
 
 GLenum Texture::getInternalFormat(GLenum target, size_t level) const
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
     return getImageDesc(ImageIdentifier(target, level)).internalFormat;
 }
 
+bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
+{
+    GLenum baseTarget = getBaseImageTarget();
+    size_t width = getWidth(baseTarget, 0);
+    size_t height = getHeight(baseTarget, 0);
+    size_t depth = getDepth(baseTarget, 0);
+    if (width == 0 || height == 0 || depth == 0)
+    {
+        return false;
+    }
+
+    if (mTarget == GL_TEXTURE_CUBE_MAP && width != height)
+    {
+        return false;
+    }
+
+    GLenum internalFormat = getInternalFormat(baseTarget, 0);
+    const TextureCaps &textureCaps = data.textureCaps->get(internalFormat);
+    if (!textureCaps.filterable && !IsPointSampled(samplerState))
+    {
+        return false;
+    }
+
+    bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
+    if (!npotSupport)
+    {
+        if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
+            (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
+        {
+            return false;
+        }
+    }
+
+    if (IsMipmapFiltered(samplerState))
+    {
+        if (!npotSupport)
+        {
+            if (!gl::isPow2(width) || !gl::isPow2(height))
+            {
+                return false;
+            }
+        }
+
+        if (!isMipmapComplete())
+        {
+            return false;
+        }
+    }
+    else
+    {
+        if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
+        {
+            return false;
+        }
+    }
+
+    // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
+    // The internalformat specified for the texture arrays is a sized internal depth or
+    // 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.
+    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+    if (formatInfo.depthBits > 0 && data.clientVersion > 2)
+    {
+        if (samplerState.compareMode == GL_NONE)
+        {
+            if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
+                samplerState.magFilter != GL_NEAREST)
+            {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture::isCubeComplete() const
+{
+    ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
+
+    GLenum baseTarget = FirstCubeMapTextureTarget;
+    size_t width = getWidth(baseTarget, 0);
+    size_t height = getWidth(baseTarget, 0);
+    if (width == 0 || width != height)
+    {
+        return false;
+    }
+
+    GLenum internalFormat = getInternalFormat(baseTarget, 0);
+    for (GLenum face = baseTarget + 1; face <= LastCubeMapTextureTarget; face++)
+    {
+        if (getWidth(face, 0) != width ||
+            getHeight(face, 0) != height ||
+            getInternalFormat(face, 0) != internalFormat)
+        {
+            return false;
+        }
+    }
+
+    return true;
+}
+
 unsigned int Texture::getTextureSerial() const
 {
     return mTextureSerial;
@@ -132,7 +234,7 @@
 Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
                         const PixelUnpackState &unpack, const uint8_t *pixels)
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
     if (error.isError())
@@ -150,7 +252,7 @@
 Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
                            const PixelUnpackState &unpack, const uint8_t *pixels)
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
 }
@@ -158,7 +260,7 @@
 Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
                                   const PixelUnpackState &unpack, const uint8_t *pixels)
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
     if (error.isError())
@@ -176,7 +278,7 @@
 Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
                                      const PixelUnpackState &unpack, const uint8_t *pixels)
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
 }
@@ -184,7 +286,7 @@
 Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
                          const Framebuffer *source)
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
     if (error.isError())
@@ -203,7 +305,7 @@
 Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
                             const Framebuffer *source)
 {
-    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
+    ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
 
     return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
 }
@@ -238,7 +340,7 @@
 
     releaseTexImage();
 
-    ImageIdentifier baseLevel(mTarget == GL_TEXTURE_CUBE_MAP ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : mTarget, 0);
+    ImageIdentifier baseLevel(getBaseImageTarget(), 0);
     const ImageDesc &baseImageInfo = getImageDesc(baseLevel);
     size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
     setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
@@ -257,7 +359,7 @@
 
         if (mTarget == GL_TEXTURE_CUBE_MAP)
         {
-            for (size_t face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
+            for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
             {
                 setImageDesc(ImageIdentifier(face, level), levelInfo);
             }
@@ -329,97 +431,56 @@
     }
 }
 
-Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
-    : Texture(impl, id, GL_TEXTURE_2D)
+GLenum Texture::getBaseImageTarget() const
 {
+    return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
 }
 
-Texture2D::~Texture2D()
+size_t Texture::getExpectedMipLevels() const
 {
+    GLenum baseTarget = getBaseImageTarget();
+    size_t width = getWidth(baseTarget, 0);
+    size_t height = getHeight(baseTarget, 0);
+    if (mTarget == GL_TEXTURE_3D)
+    {
+        size_t depth = getDepth(baseTarget, 0);
+        return log2(std::max(std::max(width, height), depth)) + 1;
+    }
+    else
+    {
+        return log2(std::max(width, height)) + 1;
+    }
 }
 
-// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
-bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
+bool Texture::isMipmapComplete() const
 {
-    size_t width = getWidth(GL_TEXTURE_2D, 0);
-    size_t height = getHeight(GL_TEXTURE_2D, 0);
-    if (width == 0 || height == 0)
-    {
-        return false;
-    }
-
-    GLenum internalFormat = getInternalFormat(GL_TEXTURE_2D, 0);
-    if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
-    {
-        return false;
-    }
-
-    bool npotSupport = data.extensions->textureNPOT;
-    if (!npotSupport)
-    {
-        if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
-            (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
-        {
-            return false;
-        }
-    }
-
-    if (IsMipmapFiltered(samplerState))
-    {
-        if (!npotSupport)
-        {
-            if (!gl::isPow2(width) || !gl::isPow2(height))
-            {
-                return false;
-            }
-        }
-
-        if (!isMipmapComplete())
-        {
-            return false;
-        }
-    }
-
-    // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
-    // The internalformat specified for the texture arrays is a sized internal depth or
-    // 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.
-    const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
-    if (formatInfo.depthBits > 0 && data.clientVersion > 2)
-    {
-        if (samplerState.compareMode == GL_NONE)
-        {
-            if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
-                samplerState.magFilter != GL_NEAREST)
-            {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture2D::isMipmapComplete() const
-{
-    size_t width = getWidth(GL_TEXTURE_2D, 0);
-    size_t height = getHeight(GL_TEXTURE_2D, 0);
-
-    size_t expectedMipLevels = log2(std::max(width, height)) + 1;
+    size_t expectedMipLevels = getExpectedMipLevels();
     for (size_t level = 0; level < expectedMipLevels; level++)
     {
-        if (!isLevelComplete(level))
+        if (mTarget == GL_TEXTURE_CUBE_MAP)
         {
-            return false;
+            for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+            {
+                if (!isLevelComplete(face, level))
+                {
+                    return false;
+                }
+            }
+        }
+        else
+        {
+            if (!isLevelComplete(mTarget, level))
+            {
+                return false;
+            }
         }
     }
 
     return true;
 }
 
-bool Texture2D::isLevelComplete(size_t level) const
+
+bool Texture::isLevelComplete(GLenum target, size_t level) const
 {
     ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
 
@@ -428,9 +489,10 @@
         return true;
     }
 
-    size_t width = getWidth(GL_TEXTURE_2D, 0);
-    size_t height = getHeight(GL_TEXTURE_2D, 0);
-    if (width == 0 || height == 0)
+    size_t width = getWidth(target, 0);
+    size_t height = getHeight(target, 0);
+    size_t depth = getHeight(target, 0);
+    if (width == 0 || height == 0 || depth == 0)
     {
         return false;
     }
@@ -441,323 +503,31 @@
         return true;
     }
 
-    if (getInternalFormat(GL_TEXTURE_2D, level) != getInternalFormat(GL_TEXTURE_2D, 0))
-    {
-        return false;
-    }
-
-    if (getWidth(GL_TEXTURE_2D, level) != std::max<size_t>(1, width >> level))
-    {
-        return false;
-    }
-
-    if (getHeight(GL_TEXTURE_2D, level) != std::max<size_t>(1, height >> level))
-    {
-        return false;
-    }
-
-    return true;
-}
-
-TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
-    : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
-{
-}
-
-TextureCubeMap::~TextureCubeMap()
-{
-}
-
-// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool TextureCubeMap::isCubeComplete() const
-{
-    size_t width = getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-    size_t height = getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-    if (width == 0 || width != height)
-    {
-        return false;
-    }
-
-    GLenum internalFormat = getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-    for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X + 1; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
-    {
-        if (getWidth(face, 0)          != width  ||
-            getHeight(face, 0)         != height ||
-            getInternalFormat(face, 0) != internalFormat)
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-// Tests for texture sampling completeness
-bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
-{
-    bool mipmapping = IsMipmapFiltered(samplerState);
-
-    GLenum internalFormat = getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-    if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
-    {
-        return false;
-    }
-
-    size_t size = getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
-    if (!gl::isPow2(size) && !data.extensions->textureNPOT)
-    {
-        if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
-        {
-            return false;
-        }
-    }
-
-    if (!mipmapping)
-    {
-        if (!isCubeComplete())
-        {
-            return false;
-        }
-    }
-    else
-    {
-        if (!isMipmapComplete())   // Also tests for isCubeComplete()
-        {
-            return false;
-        }
-    }
-
-    return true;
-}
-
-int TextureCubeMap::targetToLayerIndex(GLenum target)
-{
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
-
-    return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-}
-
-GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
-{
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
-    META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
-
-    return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
-}
-
-bool TextureCubeMap::isMipmapComplete() const
-{
-    if (isImmutable())
-    {
-        return true;
-    }
-
-    if (!isCubeComplete())
-    {
-        return false;
-    }
-
-    size_t width = getWidth(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0);
-    size_t height = getHeight(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0);
-
-    size_t expectedMipLevels = log2(std::max(width, height)) + 1;
-    for (GLenum face = GL_TEXTURE_CUBE_MAP_NEGATIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
-    {
-        for (size_t level = 1; level < expectedMipLevels; level++)
-        {
-            if (!isFaceLevelComplete(face, level))
-            {
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-bool TextureCubeMap::isFaceLevelComplete(GLenum target, size_t level) const
-{
-    ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && IsCubemapTextureTarget(target));
-
-    if (isImmutable())
-    {
-        return true;
-    }
-
-    size_t baseSize = getWidth(target, 0);
-    if (baseSize == 0)
-    {
-        return false;
-    }
-
-    // "isCubeComplete" checks for base level completeness and we must call that
-    // to determine if any face at level 0 is complete. We omit that check here
-    // to avoid re-checking cube-completeness for every face at level 0.
-    if (level == 0)
-    {
-        return true;
-    }
-
-    // Check that non-zero levels are consistent with the base level.
     if (getInternalFormat(target, level) != getInternalFormat(target, 0))
     {
         return false;
     }
 
-    if (getWidth(target, level) != std::max<size_t>(1, baseSize >> level))
+    if (getWidth(target, level) != std::max<size_t>(1, width >> level))
     {
         return false;
     }
 
-    return true;
-}
-
-
-Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
-    : Texture(impl, id, GL_TEXTURE_3D)
-{
-}
-
-Texture3D::~Texture3D()
-{
-}
-
-bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
-{
-    size_t width = getWidth(GL_TEXTURE_3D, 0);
-    size_t height = getHeight(GL_TEXTURE_3D, 0);
-    size_t depth = getDepth(GL_TEXTURE_3D, 0);
-    if (width == 0 || height == 0 || depth == 0)
+    if (getHeight(target, level) != std::max<size_t>(1, height >> level))
     {
         return false;
     }
 
-    GLenum internalFormat = getInternalFormat(GL_TEXTURE_3D, 0);
-    if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
+    if (mTarget == GL_TEXTURE_3D)
     {
-        return false;
-    }
-
-    if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool Texture3D::isMipmapComplete() const
-{
-    size_t width = getWidth(GL_TEXTURE_2D_ARRAY, 0);
-    size_t height = getHeight(GL_TEXTURE_2D_ARRAY, 0);
-    size_t depth = getDepth(GL_TEXTURE_3D, 0);
-
-    size_t expectedMipLevels = log2(std::max(std::max(width, height), depth)) + 1;
-    for (size_t level = 0; level < expectedMipLevels; level++)
-    {
-        if (!isLevelComplete(level))
+        if (getDepth(target, level) != std::max<size_t>(1, depth >> level))
         {
             return false;
         }
     }
-
-    return true;
-}
-
-bool Texture3D::isLevelComplete(size_t level) const
-{
-    ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-
-    if (isImmutable())
+    else if (mTarget == GL_TEXTURE_2D_ARRAY)
     {
-        return true;
-    }
-
-    size_t width = getWidth(GL_TEXTURE_3D, level);
-    size_t height = getHeight(GL_TEXTURE_3D, level);
-    size_t depth = getDepth(GL_TEXTURE_3D, level);
-    if (width == 0 || height == 0 || depth == 0)
-    {
-        return false;
-    }
-
-    if (level == 0)
-    {
-        return true;
-    }
-
-    if (getInternalFormat(GL_TEXTURE_3D, level) != getInternalFormat(GL_TEXTURE_3D, 0))
-    {
-        return false;
-    }
-
-    if (getWidth(GL_TEXTURE_3D, level) != std::max<size_t>(1, width >> level))
-    {
-        return false;
-    }
-
-    if (getHeight(GL_TEXTURE_3D, level) != std::max<size_t>(1, height >> level))
-    {
-        return false;
-    }
-
-    if (getDepth(GL_TEXTURE_3D, level) != std::max<size_t>(1, depth >> level))
-    {
-        return false;
-    }
-
-    return true;
-}
-
-Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
-    : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
-{
-}
-
-Texture2DArray::~Texture2DArray()
-{
-}
-
-bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
-{
-    size_t width = getWidth(GL_TEXTURE_2D_ARRAY, 0);
-    size_t height = getHeight(GL_TEXTURE_2D_ARRAY, 0);
-    size_t depth = getDepth(GL_TEXTURE_2D_ARRAY, 0);
-    if (width == 0 || height == 0 || depth == 0)
-    {
-        return false;
-    }
-
-    GLenum internalFormat = getInternalFormat(GL_TEXTURE_2D_ARRAY, 0);
-    if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
-    {
-        return false;
-    }
-
-    if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
-    {
-        return false;
-    }
-
-    return true;
-}
-
-bool Texture2DArray::isMipmapComplete() const
-{
-    size_t width = getWidth(GL_TEXTURE_2D_ARRAY, 0);
-    size_t height = getHeight(GL_TEXTURE_2D_ARRAY, 0);
-
-    size_t expectedMipLevels = log2(std::max(width, height)) + 1;
-    for (size_t level = 1; level < expectedMipLevels; level++)
-    {
-        if (!isLevelComplete(level))
+        if (getDepth(target, level) != depth)
         {
             return false;
         }
@@ -766,49 +536,4 @@
     return true;
 }
 
-bool Texture2DArray::isLevelComplete(size_t level) const
-{
-    ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-
-    if (isImmutable())
-    {
-        return true;
-    }
-
-    size_t width = getWidth(GL_TEXTURE_2D_ARRAY, level);
-    size_t height = getHeight(GL_TEXTURE_2D_ARRAY, level);
-    size_t layers = getDepth(GL_TEXTURE_2D_ARRAY, 0);
-    if (width == 0 || height == 0 || layers == 0)
-    {
-        return false;
-    }
-
-    if (level == 0)
-    {
-        return true;
-    }
-
-    if (getInternalFormat(GL_TEXTURE_2D_ARRAY, level) != getInternalFormat(GL_TEXTURE_2D_ARRAY, 0))
-    {
-        return false;
-    }
-
-    if (getWidth(GL_TEXTURE_2D_ARRAY, level) != std::max<size_t>(1, width >> level))
-    {
-        return false;
-    }
-
-    if (getHeight(GL_TEXTURE_2D_ARRAY, level) != std::max<size_t>(1, height >> level))
-    {
-        return false;
-    }
-
-    if (getDepth(GL_TEXTURE_2D_ARRAY, level) != layers)
-    {
-        return false;
-    }
-
-    return true;
-}
-
 }