Commit a9be0dc6 by Geoff Lang

Refactor Texture to track image information for size and format queries.

BUG=angle:681 Change-Id: Ifb3f52d6348e4479181e66f1c39578f49e9dcf76 Reviewed-on: https://chromium-review.googlesource.com/235613Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarBrandon Jones <bajones@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 24d5811b
......@@ -98,17 +98,17 @@ GLuint TextureAttachment::id() const
GLsizei TextureAttachment::getWidth() const
{
return mTexture->getWidth(mIndex);
return mTexture->getWidth(mIndex.type, mIndex.mipIndex);
}
GLsizei TextureAttachment::getHeight() const
{
return mTexture->getHeight(mIndex);
return mTexture->getHeight(mIndex.type, mIndex.mipIndex);
}
GLenum TextureAttachment::getInternalFormat() const
{
return mTexture->getInternalFormat(mIndex);
return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex);
}
GLenum TextureAttachment::type() const
......
......@@ -79,49 +79,28 @@ GLenum Texture::getUsage() const
return mUsage;
}
GLint Texture::getBaseLevelWidth() const
size_t Texture::getWidth(GLenum target, size_t level) const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getWidth() : 0);
}
GLint Texture::getBaseLevelHeight() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getHeight() : 0);
}
GLint Texture::getBaseLevelDepth() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getDepth() : 0);
}
// Note: "base level image" is loosely defined to be any image from the base level,
// where in the base of 2D array textures and cube maps there are several. Don't use
// the base level image for anything except querying texture format and size.
GLenum Texture::getBaseLevelInternalFormat() const
{
const rx::Image *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return getImageDesc(ImageIdentifier(target, level)).size.width;
}
GLsizei Texture::getWidth(const ImageIndex &index) const
size_t Texture::getHeight(GLenum target, size_t level) const
{
rx::Image *image = mTexture->getImage(index);
return image->getWidth();
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return getImageDesc(ImageIdentifier(target, level)).size.height;
}
GLsizei Texture::getHeight(const ImageIndex &index) const
size_t Texture::getDepth(GLenum target, size_t level) const
{
rx::Image *image = mTexture->getImage(index);
return image->getHeight();
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return getImageDesc(ImageIdentifier(target, level)).size.depth;
}
GLenum Texture::getInternalFormat(const ImageIndex &index) const
GLenum Texture::getInternalFormat(GLenum target, size_t level) const
{
rx::Image *image = mTexture->getImage(index);
return image->getInternalFormat();
ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return getImageDesc(ImageIdentifier(target, level)).internalFormat;
}
unsigned int Texture::getTextureSerial() const
......@@ -144,16 +123,6 @@ int Texture::immutableLevelCount()
return mImmutableLevelCount;
}
int Texture::mipLevels() const
{
return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
}
const rx::Image *Texture::getBaseLevelImage() const
{
return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
}
Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
const PixelUnpackState &unpack, const uint8_t *pixels)
{
......@@ -165,6 +134,8 @@ Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, cons
return error;
}
setImageDesc(ImageIdentifier(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
return Error(GL_NO_ERROR);
}
......@@ -187,6 +158,8 @@ Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFo
return error;
}
setImageDesc(ImageIdentifier(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
return Error(GL_NO_ERROR);
}
......@@ -209,6 +182,9 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre
return error;
}
setImageDesc(ImageIdentifier(target, level), ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
return Error(GL_NO_ERROR);
}
......@@ -231,6 +207,8 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
}
mImmutableLevelCount = levels;
clearImageDescs();
setImageDescChain(levels, size, internalFormat);
return Error(GL_NO_ERROR);
}
......@@ -244,46 +222,94 @@ Error Texture::generateMipmaps()
return error;
}
ImageIdentifier baseLevel(mTarget == GL_TEXTURE_CUBE_MAP ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : mTarget, 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);
return Error(GL_NO_ERROR);
}
Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
: Texture(impl, id, GL_TEXTURE_2D)
void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
{
mSurface = NULL;
for (size_t level = 0; level < levels; level++)
{
Extents levelSize(std::max<size_t>(baseSize.width >> level, 1),
std::max<size_t>(baseSize.height >> level, 1),
(mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1));
ImageDesc levelInfo(levelSize, sizedInternalFormat);
if (mTarget == GL_TEXTURE_CUBE_MAP)
{
for (size_t face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
{
setImageDesc(ImageIdentifier(face, level), levelInfo);
}
}
else
{
setImageDesc(ImageIdentifier(mTarget, level), levelInfo);
}
}
}
Texture2D::~Texture2D()
Texture::ImageIdentifier::ImageIdentifier()
: ImageIdentifier(GL_TEXTURE_2D, 0)
{
if (mSurface)
{
mSurface->releaseTexImage(EGL_BACK_BUFFER);
mSurface = NULL;
}
}
GLsizei Texture2D::getWidth(GLint level) const
Texture::ImageIdentifier::ImageIdentifier(GLenum target, size_t level)
: target(target),
level(level)
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, 0)->getWidth();
else
return 0;
}
GLsizei Texture2D::getHeight(GLint level) const
bool Texture::ImageIdentifier::operator<(const ImageIdentifier &other) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, 0)->getHeight();
else
return 0;
return (target != other.target) ? target < other.target : level < other.level;
}
GLenum Texture2D::getInternalFormat(GLint level) const
Texture::ImageDesc::ImageDesc()
: ImageDesc(Extents(0, 0, 0), GL_NONE)
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, 0)->getInternalFormat();
else
return GL_NONE;
}
Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
: size(size),
internalFormat(internalFormat)
{
}
const Texture::ImageDesc &Texture::getImageDesc(const ImageIdentifier& index) const
{
static const Texture::ImageDesc defaultDesc;
ImageDescMap::const_iterator iter = mImageDescs.find(index);
return (iter != mImageDescs.end()) ? iter->second : defaultDesc;
}
void Texture::setImageDesc(const ImageIdentifier& index, const ImageDesc &desc)
{
mImageDescs[index] = desc;
}
void Texture::clearImageDescs()
{
mImageDescs.clear();
}
Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
: Texture(impl, id, GL_TEXTURE_2D)
{
mSurface = NULL;
}
Texture2D::~Texture2D()
{
if (mSurface)
{
mSurface->releaseTexImage(EGL_BACK_BUFFER);
mSurface = NULL;
}
}
Error Texture2D::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
......@@ -373,15 +399,15 @@ void Texture2D::releaseTexImage()
// 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
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
if (width <= 0 || height <= 0)
size_t width = getWidth(GL_TEXTURE_2D, 0);
size_t height = getHeight(GL_TEXTURE_2D, 0);
if (width == 0 || height == 0)
{
return false;
}
if (!data.textureCaps->get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
GLenum internalFormat = getInternalFormat(GL_TEXTURE_2D, 0);
if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
{
return false;
}
......@@ -417,7 +443,7 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &
// 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(getInternalFormat(0));
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
if (formatInfo.depthBits > 0 && data.clientVersion > 2)
{
if (samplerState.compareMode == GL_NONE)
......@@ -433,22 +459,14 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &
return true;
}
bool Texture2D::isCompressed(GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(level)).compressed;
}
bool Texture2D::isDepth(GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool Texture2D::isMipmapComplete() const
{
int levelCount = mipLevels();
size_t width = getWidth(GL_TEXTURE_2D, 0);
size_t height = getHeight(GL_TEXTURE_2D, 0);
for (int level = 0; level < levelCount; level++)
size_t expectedMipLevels = log2(std::max(width, height)) + 1;
for (size_t level = 0; level < expectedMipLevels; level++)
{
if (!isLevelComplete(level))
{
......@@ -459,19 +477,18 @@ bool Texture2D::isMipmapComplete() const
return true;
}
bool Texture2D::isLevelComplete(int level) const
bool Texture2D::isLevelComplete(size_t level) const
{
ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
if (isImmutable())
{
return true;
}
const rx::Image *baseImage = getBaseLevelImage();
GLsizei width = baseImage->getWidth();
GLsizei height = baseImage->getHeight();
if (width <= 0 || height <= 0)
size_t width = getWidth(GL_TEXTURE_2D, 0);
size_t height = getHeight(GL_TEXTURE_2D, 0);
if (width == 0 || height == 0)
{
return false;
}
......@@ -482,20 +499,17 @@ bool Texture2D::isLevelComplete(int level) const
return true;
}
ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
rx::Image *image = mTexture->getImage(level, 0);
if (image->getInternalFormat() != baseImage->getInternalFormat())
if (getInternalFormat(GL_TEXTURE_2D, level) != getInternalFormat(GL_TEXTURE_2D, 0))
{
return false;
}
if (image->getWidth() != std::max(1, width >> level))
if (getWidth(GL_TEXTURE_2D, level) != std::max<size_t>(1, width >> level))
{
return false;
}
if (image->getHeight() != std::max(1, height >> level))
if (getHeight(GL_TEXTURE_2D, level) != std::max<size_t>(1, height >> level))
{
return false;
}
......@@ -512,49 +526,22 @@ TextureCubeMap::~TextureCubeMap()
{
}
GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
else
return 0;
}
GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
else
return 0;
}
GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
{
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
else
return GL_NONE;
}
// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool TextureCubeMap::isCubeComplete() const
{
int baseWidth = getBaseLevelWidth();
int baseHeight = getBaseLevelHeight();
GLenum baseFormat = getBaseLevelInternalFormat();
if (baseWidth <= 0 || baseWidth != baseHeight)
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;
}
for (int faceIndex = 1; faceIndex < 6; faceIndex++)
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++)
{
const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
if (faceBaseImage->getWidth() != baseWidth ||
faceBaseImage->getHeight() != baseHeight ||
faceBaseImage->getInternalFormat() != baseFormat )
if (getWidth(face, 0) != width ||
getHeight(face, 0) != height ||
getInternalFormat(face, 0) != internalFormat)
{
return false;
}
......@@ -563,28 +550,18 @@ bool TextureCubeMap::isCubeComplete() const
return true;
}
bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
}
bool TextureCubeMap::isDepth(GLenum target, GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
}
// Tests for texture sampling completeness
bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{
int size = getBaseLevelWidth();
bool mipmapping = IsMipmapFiltered(samplerState);
if (!data.textureCaps->get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(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)
......@@ -645,11 +622,13 @@ bool TextureCubeMap::isMipmapComplete() const
return false;
}
int levelCount = mipLevels();
size_t width = getWidth(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0);
size_t height = getHeight(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0);
for (int face = 0; face < 6; face++)
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 (int level = 1; level < levelCount; level++)
for (size_t level = 1; level < expectedMipLevels; level++)
{
if (!isFaceLevelComplete(face, level))
{
......@@ -661,18 +640,17 @@ bool TextureCubeMap::isMipmapComplete() const
return true;
}
bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
bool TextureCubeMap::isFaceLevelComplete(GLenum target, size_t level) const
{
ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && IsCubemapTextureTarget(target));
if (isImmutable())
{
return true;
}
int baseSize = getBaseLevelWidth();
if (baseSize <= 0)
size_t baseSize = getWidth(target, 0);
if (baseSize == 0)
{
return false;
}
......@@ -686,14 +664,12 @@ bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
}
// Check that non-zero levels are consistent with the base level.
const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
if (getInternalFormat(target, level) != getInternalFormat(target, 0))
{
return false;
}
if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
if (getWidth(target, level) != std::max<size_t>(1, baseSize >> level))
{
return false;
}
......@@ -711,48 +687,18 @@ Texture3D::~Texture3D()
{
}
GLsizei Texture3D::getWidth(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
}
GLsizei Texture3D::getHeight(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
}
GLsizei Texture3D::getDepth(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
}
GLenum Texture3D::getInternalFormat(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
}
bool Texture3D::isCompressed(GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(level)).compressed;
}
bool Texture3D::isDepth(GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
if (width <= 0 || height <= 0 || depth <= 0)
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)
{
return false;
}
if (!data.textureCaps->get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
GLenum internalFormat = getInternalFormat(GL_TEXTURE_3D, 0);
if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
{
return false;
}
......@@ -767,9 +713,12 @@ bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &
bool Texture3D::isMipmapComplete() const
{
int levelCount = mipLevels();
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);
for (int level = 0; level < levelCount; level++)
size_t expectedMipLevels = log2(std::max(std::max(width, height), depth)) + 1;
for (size_t level = 0; level < expectedMipLevels; level++)
{
if (!isLevelComplete(level))
{
......@@ -780,20 +729,19 @@ bool Texture3D::isMipmapComplete() const
return true;
}
bool Texture3D::isLevelComplete(int level) const
bool Texture3D::isLevelComplete(size_t level) const
{
ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
if (isImmutable())
{
return true;
}
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getBaseLevelDepth();
if (width <= 0 || height <= 0 || depth <= 0)
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;
}
......@@ -803,24 +751,22 @@ bool Texture3D::isLevelComplete(int level) const
return true;
}
rx::Image *levelImage = mTexture->getImage(level, 0);
if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
if (getInternalFormat(GL_TEXTURE_3D, level) != getInternalFormat(GL_TEXTURE_3D, 0))
{
return false;
}
if (levelImage->getWidth() != std::max(1, width >> level))
if (getWidth(GL_TEXTURE_3D, level) != std::max<size_t>(1, width >> level))
{
return false;
}
if (levelImage->getHeight() != std::max(1, height >> level))
if (getHeight(GL_TEXTURE_3D, level) != std::max<size_t>(1, height >> level))
{
return false;
}
if (levelImage->getDepth() != std::max(1, depth >> level))
if (getDepth(GL_TEXTURE_3D, level) != std::max<size_t>(1, depth >> level))
{
return false;
}
......@@ -837,48 +783,18 @@ Texture2DArray::~Texture2DArray()
{
}
GLsizei Texture2DArray::getWidth(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0;
}
GLsizei Texture2DArray::getHeight(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0;
}
GLsizei Texture2DArray::getLayers(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
}
GLenum Texture2DArray::getInternalFormat(GLint level) const
{
return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
}
bool Texture2DArray::isCompressed(GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(level)).compressed;
}
bool Texture2DArray::isDepth(GLint level) const
{
return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei depth = getLayers(0);
if (width <= 0 || height <= 0 || depth <= 0)
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;
}
if (!data.textureCaps->get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
GLenum internalFormat = getInternalFormat(GL_TEXTURE_2D_ARRAY, 0);
if (!data.textureCaps->get(internalFormat).filterable && !IsPointSampled(samplerState))
{
return false;
}
......@@ -893,9 +809,11 @@ bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const D
bool Texture2DArray::isMipmapComplete() const
{
int levelCount = mipLevels();
size_t width = getWidth(GL_TEXTURE_2D_ARRAY, 0);
size_t height = getHeight(GL_TEXTURE_2D_ARRAY, 0);
for (int level = 1; level < levelCount; level++)
size_t expectedMipLevels = log2(std::max(width, height)) + 1;
for (size_t level = 1; level < expectedMipLevels; level++)
{
if (!isLevelComplete(level))
{
......@@ -906,20 +824,19 @@ bool Texture2DArray::isMipmapComplete() const
return true;
}
bool Texture2DArray::isLevelComplete(int level) const
bool Texture2DArray::isLevelComplete(size_t level) const
{
ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
if (isImmutable())
{
return true;
}
GLsizei width = getBaseLevelWidth();
GLsizei height = getBaseLevelHeight();
GLsizei layers = getLayers(0);
if (width <= 0 || height <= 0 || layers <= 0)
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;
}
......@@ -929,22 +846,22 @@ bool Texture2DArray::isLevelComplete(int level) const
return true;
}
if (getInternalFormat(level) != getInternalFormat(0))
if (getInternalFormat(GL_TEXTURE_2D_ARRAY, level) != getInternalFormat(GL_TEXTURE_2D_ARRAY, 0))
{
return false;
}
if (getWidth(level) != std::max(1, width >> level))
if (getWidth(GL_TEXTURE_2D_ARRAY, level) != std::max<size_t>(1, width >> level))
{
return false;
}
if (getHeight(level) != std::max(1, height >> level))
if (getHeight(GL_TEXTURE_2D_ARRAY, level) != std::max<size_t>(1, height >> level))
{
return false;
}
if (getLayers(level) != layers)
if (getDepth(GL_TEXTURE_2D_ARRAY, level) != layers)
{
return false;
}
......
......@@ -21,6 +21,7 @@
#include "angle_gl.h"
#include <vector>
#include <map>
namespace egl
{
......@@ -57,14 +58,10 @@ class Texture : public RefCountObject
void setUsage(GLenum usage);
GLenum getUsage() const;
GLint getBaseLevelWidth() const;
GLint getBaseLevelHeight() const;
GLint getBaseLevelDepth() const;
GLenum getBaseLevelInternalFormat() const;
GLsizei getWidth(const ImageIndex &index) const;
GLsizei getHeight(const ImageIndex &index) const;
GLenum getInternalFormat(const ImageIndex &index) const;
size_t getWidth(GLenum target, size_t level) const;
size_t getHeight(GLenum target, size_t level) const;
size_t getDepth(GLenum target, size_t level) const;
GLenum getInternalFormat(GLenum target, size_t level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const = 0;
......@@ -100,8 +97,6 @@ class Texture : public RefCountObject
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
protected:
int mipLevels() const;
const rx::Image *getBaseLevelImage() const;
static unsigned int issueTextureSerial();
rx::TextureImpl *mTexture;
......@@ -113,11 +108,39 @@ class Texture : public RefCountObject
GLenum mTarget;
struct ImageIdentifier
{
GLenum target;
size_t level;
ImageIdentifier();
ImageIdentifier(GLenum target, size_t level);
bool operator<(const ImageIdentifier &other) const;
};
struct ImageDesc
{
Extents size;
GLenum internalFormat;
ImageDesc();
ImageDesc(const Extents &size, GLenum internalFormat);
};
const unsigned int mTextureSerial;
static unsigned int mCurrentTextureSerial;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
const ImageDesc &getImageDesc(const ImageIdentifier& index) const;
void setImageDesc(const ImageIdentifier& index, const ImageDesc &desc);
void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat);
void clearImageDescs();
typedef std::map<ImageIdentifier, ImageDesc> ImageDescMap;
ImageDescMap mImageDescs;
};
class Texture2D : public Texture
......@@ -127,12 +150,6 @@ class Texture2D : public Texture
virtual ~Texture2D();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
const PixelUnpackState &unpack, const uint8_t *pixels) override;
......@@ -154,7 +171,7 @@ class Texture2D : public Texture
DISALLOW_COPY_AND_ASSIGN(Texture2D);
bool isMipmapComplete() const;
bool isLevelComplete(int level) const;
bool isLevelComplete(size_t level) const;
egl::Surface *mSurface;
};
......@@ -166,12 +183,6 @@ class TextureCubeMap : public Texture
virtual ~TextureCubeMap();
GLsizei getWidth(GLenum target, GLint level) const;
GLsizei getHeight(GLenum target, GLint level) const;
GLenum getInternalFormat(GLenum target, GLint level) const;
bool isCompressed(GLenum target, GLint level) const;
bool isDepth(GLenum target, GLint level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
bool isCubeComplete() const;
......@@ -183,7 +194,7 @@ class TextureCubeMap : public Texture
DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
bool isMipmapComplete() const;
bool isFaceLevelComplete(int faceIndex, int level) const;
bool isFaceLevelComplete(GLenum target, size_t level) const;
};
class Texture3D : public Texture
......@@ -193,20 +204,13 @@ class Texture3D : public Texture
virtual ~Texture3D();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLsizei getDepth(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
private:
DISALLOW_COPY_AND_ASSIGN(Texture3D);
bool isMipmapComplete() const;
bool isLevelComplete(int level) const;
bool isLevelComplete(size_t level) const;
};
class Texture2DArray : public Texture
......@@ -216,20 +220,13 @@ class Texture2DArray : public Texture
virtual ~Texture2DArray();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLsizei getLayers(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
private:
DISALLOW_COPY_AND_ASSIGN(Texture2DArray);
bool isMipmapComplete() const;
bool isLevelComplete(int level) const;
bool isLevelComplete(size_t level) const;
};
}
......
......@@ -1230,28 +1230,11 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL;
GLenum textureInternalFormat = GL_NONE;
GLint textureLevelWidth = 0;
GLint textureLevelHeight = 0;
GLint textureLevelDepth = 0;
GLuint maxDimension = 0;
switch (target)
{
case GL_TEXTURE_2D:
{
gl::Texture2D *texture2d = context->getTexture2D();
if (texture2d)
{
textureInternalFormat = texture2d->getInternalFormat(level);
textureLevelWidth = texture2d->getWidth(level);
textureLevelHeight = texture2d->getHeight(level);
textureLevelDepth = 1;
texture = texture2d;
maxDimension = caps.max2DTextureSize;
}
}
maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
......@@ -1260,48 +1243,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{
gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
if (textureCube)
{
textureInternalFormat = textureCube->getInternalFormat(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
maxDimension = caps.maxCubeMapTextureSize;
}
}
maxDimension = caps.maxCubeMapTextureSize;
break;
case GL_TEXTURE_2D_ARRAY:
{
gl::Texture2DArray *texture2dArray = context->getTexture2DArray();
if (texture2dArray)
{
textureInternalFormat = texture2dArray->getInternalFormat(level);
textureLevelWidth = texture2dArray->getWidth(level);
textureLevelHeight = texture2dArray->getHeight(level);
textureLevelDepth = texture2dArray->getLayers(level);
texture = texture2dArray;
maxDimension = caps.max2DTextureSize;
}
}
maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_3D:
{
gl::Texture3D *texture3d = context->getTexture3D();
if (texture3d)
{
textureInternalFormat = texture3d->getInternalFormat(level);
textureLevelWidth = texture3d->getWidth(level);
textureLevelHeight = texture3d->getHeight(level);
textureLevelDepth = texture3d->getDepth(level);
texture = texture3d;
maxDimension = caps.max3DTextureSize;
}
}
maxDimension = caps.max3DTextureSize;
break;
default:
......@@ -1309,6 +1259,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false;
}
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
......@@ -1329,21 +1280,17 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false;
}
if (formatInfo.compressed)
if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
{
if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) ||
((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (isSubImage)
{
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset >= textureLevelDepth)
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
......@@ -1371,7 +1318,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
}
}
*textureFormatOut = textureInternalFormat;
*textureFormatOut = texture->getInternalFormat(target, level);
return true;
}
......@@ -1786,12 +1733,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
if (tex2d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1812,12 +1753,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
if (texcube->isCompressed(textarget, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1825,6 +1760,13 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level));
if (internalFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
return true;
......
......@@ -21,218 +21,118 @@
namespace gl
{
static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height,
GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
gl::Texture2D *texture)
bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type, const GLvoid *pixels)
{
if (!texture)
if (!ValidTexture2DDestinationTarget(context, target))
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (compressed != texture->isCompressed(level))
if (!ValidImageSize(context, target, level, width, height, 1))
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (format != GL_NONE)
{
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (compressed)
{
if ((width % 4 != 0 && width != texture->getWidth(level)) ||
(height % 4 != 0 && height != texture->getHeight(level)))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (xoffset + width > texture->getWidth(level) ||
yoffset + height > texture->getHeight(level))
if (level < 0 || xoffset < 0 ||
std::numeric_limits<GLsizei>::max() - xoffset < width ||
std::numeric_limits<GLsizei>::max() - yoffset < height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
return true;
}
static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height,
GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
gl::TextureCubeMap *texture)
{
if (!texture)
if (!isSubImage && !isCompressed && internalformat != format)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (compressed != texture->isCompressed(target, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
const gl::Caps &caps = context->getCaps();
if (format != GL_NONE)
if (target == GL_TEXTURE_2D)
{
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
if (compressed)
else if (IsCubemapTextureTarget(target))
{
if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
(height % 4 != 0 && height != texture->getHeight(target, 0)))
if (!isSubImage && width != height)
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
if (xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
return true;
}
bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type, const GLvoid *pixels)
{
if (!ValidTexture2DDestinationTarget(context, target))
else
{
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (!ValidImageSize(context, target, level, width, height, 1))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (level < 0 || xoffset < 0 ||
std::numeric_limits<GLsizei>::max() - xoffset < width ||
std::numeric_limits<GLsizei>::max() - yoffset < height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (!isSubImage && !isCompressed && internalformat != format)
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL;
GLenum textureInternalFormat = GL_NONE;
switch (target)
if (isSubImage)
{
case GL_TEXTURE_2D:
if (format != GL_NONE)
{
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2D *tex2d = context->getTexture2D();
if (tex2d)
{
textureInternalFormat = tex2d->getInternalFormat(level);
texture = tex2d;
}
if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
level, format, type, tex2d))
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
texture = tex2d;
}
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
{
if (!isSubImage && width != height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::TextureCubeMap *texCube = context->getTextureCubeMap();
if (texCube)
{
textureInternalFormat = texCube->getInternalFormat(target, level);
texture = texCube;
}
if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
target, level, format, type, texCube))
{
return false;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (!texture)
else
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
if (texture->isImmutable())
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (!isSubImage && texture->isImmutable())
// Verify zero border
if (border != 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
// Verify zero border
if (border != 0)
GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
if (isCompressed != actualFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_VALUE));
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
if (isCompressed)
{
if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
......
......@@ -16,6 +16,7 @@
#include "libANGLE/FramebufferAttachment.h"
#include "common/mathutil.h"
#include "common/utilities.h"
namespace gl
{
......@@ -310,33 +311,14 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL;
bool textureCompressed = false;
GLenum textureInternalFormat = GL_NONE;
GLint textureLevelWidth = 0;
GLint textureLevelHeight = 0;
GLint textureLevelDepth = 0;
switch (target)
{
case GL_TEXTURE_2D:
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2D *texture2d = context->getTexture2D();
if (texture2d)
{
textureCompressed = texture2d->isCompressed(level);
textureInternalFormat = texture2d->getInternalFormat(level);
textureLevelWidth = texture2d->getWidth(level);
textureLevelHeight = texture2d->getHeight(level);
textureLevelDepth = 1;
texture = texture2d;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
......@@ -346,83 +328,45 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (!isSubImage && width != height)
{
if (!isSubImage && width != height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
if (textureCube)
{
textureCompressed = textureCube->isCompressed(target, level);
textureInternalFormat = textureCube->getInternalFormat(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
case GL_TEXTURE_3D:
if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
{
if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture3D *texture3d = context->getTexture3D();
if (texture3d)
{
textureCompressed = texture3d->isCompressed(level);
textureInternalFormat = texture3d->getInternalFormat(level);
textureLevelWidth = texture3d->getWidth(level);
textureLevelHeight = texture3d->getHeight(level);
textureLevelDepth = texture3d->getDepth(level);
texture = texture3d;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
case GL_TEXTURE_2D_ARRAY:
{
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2DArray *texture2darray = context->getTexture2DArray();
if (texture2darray)
{
textureCompressed = texture2darray->isCompressed(level);
textureInternalFormat = texture2darray->getInternalFormat(level);
textureLevelWidth = texture2darray->getWidth(level);
textureLevelHeight = texture2darray->getHeight(level);
textureLevelDepth = texture2darray->getLayers(level);
texture = texture2darray;
}
}
break;
case GL_TEXTURE_2D_ARRAY:
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
......@@ -436,7 +380,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
}
// Validate texture formats
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
if (isCompressed)
{
......@@ -475,22 +419,12 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
// Validate sub image parameters
if (isSubImage)
{
if (isCompressed != textureCompressed)
if (isCompressed != actualFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (isCompressed)
{
if ((width % 4 != 0 && width != textureLevelWidth) ||
(height % 4 != 0 && height != textureLevelHeight))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (width == 0 || height == 0 || depth == 0)
{
return false;
......@@ -510,9 +444,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset + depth > textureLevelDepth)
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
......@@ -1067,13 +1001,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
if (texArray->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1090,13 +1017,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
if (tex3d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1104,6 +1024,13 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
if (internalFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
return true;
......
......@@ -1453,7 +1453,8 @@ void GL_APIENTRY GenerateMipmap(GLenum target)
return;
}
GLenum internalFormat = texture->getBaseLevelInternalFormat();
GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
GLenum internalFormat = texture->getInternalFormat(baseTarget, 0);
const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
......@@ -1484,7 +1485,7 @@ void GL_APIENTRY GenerateMipmap(GLenum target)
}
// Non-power of 2 ES2 check
if (!context->getExtensions().textureNPOT && (!isPow2(texture->getBaseLevelWidth()) || !isPow2(texture->getBaseLevelHeight())))
if (!context->getExtensions().textureNPOT && (!isPow2(texture->getWidth(baseTarget, 0)) || !isPow2(texture->getHeight(baseTarget, 0))))
{
ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
context->recordError(Error(GL_INVALID_OPERATION));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment