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 ...@@ -98,17 +98,17 @@ GLuint TextureAttachment::id() const
GLsizei TextureAttachment::getWidth() const GLsizei TextureAttachment::getWidth() const
{ {
return mTexture->getWidth(mIndex); return mTexture->getWidth(mIndex.type, mIndex.mipIndex);
} }
GLsizei TextureAttachment::getHeight() const GLsizei TextureAttachment::getHeight() const
{ {
return mTexture->getHeight(mIndex); return mTexture->getHeight(mIndex.type, mIndex.mipIndex);
} }
GLenum TextureAttachment::getInternalFormat() const GLenum TextureAttachment::getInternalFormat() const
{ {
return mTexture->getInternalFormat(mIndex); return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex);
} }
GLenum TextureAttachment::type() const GLenum TextureAttachment::type() const
......
...@@ -79,49 +79,28 @@ GLenum Texture::getUsage() const ...@@ -79,49 +79,28 @@ GLenum Texture::getUsage() const
return mUsage; return mUsage;
} }
GLint Texture::getBaseLevelWidth() const size_t Texture::getWidth(GLenum target, size_t level) const
{ {
const rx::Image *baseImage = getBaseLevelImage(); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return (baseImage ? baseImage->getWidth() : 0); return getImageDesc(ImageIdentifier(target, level)).size.width;
}
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);
} }
GLsizei Texture::getWidth(const ImageIndex &index) const size_t Texture::getHeight(GLenum target, size_t level) const
{ {
rx::Image *image = mTexture->getImage(index); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return image->getWidth(); 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); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return image->getHeight(); 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); ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubemapTextureTarget(target)));
return image->getInternalFormat(); return getImageDesc(ImageIdentifier(target, level)).internalFormat;
} }
unsigned int Texture::getTextureSerial() const unsigned int Texture::getTextureSerial() const
...@@ -144,16 +123,6 @@ int Texture::immutableLevelCount() ...@@ -144,16 +123,6 @@ int Texture::immutableLevelCount()
return mImmutableLevelCount; 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, Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
const PixelUnpackState &unpack, const uint8_t *pixels) const PixelUnpackState &unpack, const uint8_t *pixels)
{ {
...@@ -165,6 +134,8 @@ Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, cons ...@@ -165,6 +134,8 @@ Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, cons
return error; return error;
} }
setImageDesc(ImageIdentifier(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
...@@ -187,6 +158,8 @@ Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFo ...@@ -187,6 +158,8 @@ Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFo
return error; return error;
} }
setImageDesc(ImageIdentifier(target, level), ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
...@@ -209,6 +182,9 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre ...@@ -209,6 +182,9 @@ Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceAre
return error; return error;
} }
setImageDesc(ImageIdentifier(target, level), ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
...@@ -231,6 +207,8 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c ...@@ -231,6 +207,8 @@ Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, c
} }
mImmutableLevelCount = levels; mImmutableLevelCount = levels;
clearImageDescs();
setImageDescChain(levels, size, internalFormat);
return Error(GL_NO_ERROR); return Error(GL_NO_ERROR);
} }
...@@ -244,46 +222,94 @@ Error Texture::generateMipmaps() ...@@ -244,46 +222,94 @@ Error Texture::generateMipmaps()
return error; 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); return Error(GL_NO_ERROR);
} }
Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id) void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
: Texture(impl, id, GL_TEXTURE_2D)
{ {
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 (target != other.target) ? target < other.target : level < other.level;
return mTexture->getImage(level, 0)->getHeight();
else
return 0;
} }
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 Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
return GL_NONE; : 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, Error Texture2D::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
...@@ -373,15 +399,15 @@ void Texture2D::releaseTexImage() ...@@ -373,15 +399,15 @@ void Texture2D::releaseTexImage()
// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. // 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 Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{ {
GLsizei width = getBaseLevelWidth(); size_t width = getWidth(GL_TEXTURE_2D, 0);
GLsizei height = getBaseLevelHeight(); size_t height = getHeight(GL_TEXTURE_2D, 0);
if (width == 0 || height == 0)
if (width <= 0 || height <= 0)
{ {
return false; 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; return false;
} }
...@@ -417,7 +443,7 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data & ...@@ -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_- // 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- // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
// fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST. // 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 (formatInfo.depthBits > 0 && data.clientVersion > 2)
{ {
if (samplerState.compareMode == GL_NONE) if (samplerState.compareMode == GL_NONE)
...@@ -433,22 +459,14 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data & ...@@ -433,22 +459,14 @@ bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const Data &
return true; 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. // Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool Texture2D::isMipmapComplete() const 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)) if (!isLevelComplete(level))
{ {
...@@ -459,19 +477,18 @@ bool Texture2D::isMipmapComplete() const ...@@ -459,19 +477,18 @@ bool Texture2D::isMipmapComplete() const
return true; return true;
} }
bool Texture2D::isLevelComplete(int level) const bool Texture2D::isLevelComplete(size_t level) const
{ {
ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
if (isImmutable()) if (isImmutable())
{ {
return true; return true;
} }
const rx::Image *baseImage = getBaseLevelImage(); size_t width = getWidth(GL_TEXTURE_2D, 0);
size_t height = getHeight(GL_TEXTURE_2D, 0);
GLsizei width = baseImage->getWidth(); if (width == 0 || height == 0)
GLsizei height = baseImage->getHeight();
if (width <= 0 || height <= 0)
{ {
return false; return false;
} }
...@@ -482,20 +499,17 @@ bool Texture2D::isLevelComplete(int level) const ...@@ -482,20 +499,17 @@ bool Texture2D::isLevelComplete(int level) const
return true; return true;
} }
ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); if (getInternalFormat(GL_TEXTURE_2D, level) != getInternalFormat(GL_TEXTURE_2D, 0))
rx::Image *image = mTexture->getImage(level, 0);
if (image->getInternalFormat() != baseImage->getInternalFormat())
{ {
return false; 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; 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; return false;
} }
...@@ -512,49 +526,22 @@ TextureCubeMap::~TextureCubeMap() ...@@ -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. // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
bool TextureCubeMap::isCubeComplete() const bool TextureCubeMap::isCubeComplete() const
{ {
int baseWidth = getBaseLevelWidth(); size_t width = getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
int baseHeight = getBaseLevelHeight(); size_t height = getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
GLenum baseFormat = getBaseLevelInternalFormat(); if (width == 0 || width != height)
if (baseWidth <= 0 || baseWidth != baseHeight)
{ {
return false; 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 (getWidth(face, 0) != width ||
getHeight(face, 0) != height ||
if (faceBaseImage->getWidth() != baseWidth || getInternalFormat(face, 0) != internalFormat)
faceBaseImage->getHeight() != baseHeight ||
faceBaseImage->getInternalFormat() != baseFormat )
{ {
return false; return false;
} }
...@@ -563,28 +550,18 @@ bool TextureCubeMap::isCubeComplete() const ...@@ -563,28 +550,18 @@ bool TextureCubeMap::isCubeComplete() const
return true; 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 // Tests for texture sampling completeness
bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const Data &data) const bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{ {
int size = getBaseLevelWidth();
bool mipmapping = IsMipmapFiltered(samplerState); 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; return false;
} }
size_t size = getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0);
if (!gl::isPow2(size) && !data.extensions->textureNPOT) if (!gl::isPow2(size) && !data.extensions->textureNPOT)
{ {
if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
...@@ -645,11 +622,13 @@ bool TextureCubeMap::isMipmapComplete() const ...@@ -645,11 +622,13 @@ bool TextureCubeMap::isMipmapComplete() const
return false; 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)) if (!isFaceLevelComplete(face, level))
{ {
...@@ -661,18 +640,17 @@ bool TextureCubeMap::isMipmapComplete() const ...@@ -661,18 +640,17 @@ bool TextureCubeMap::isMipmapComplete() const
return true; 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()) if (isImmutable())
{ {
return true; return true;
} }
int baseSize = getBaseLevelWidth(); size_t baseSize = getWidth(target, 0);
if (baseSize == 0)
if (baseSize <= 0)
{ {
return false; return false;
} }
...@@ -686,14 +664,12 @@ bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const ...@@ -686,14 +664,12 @@ bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
} }
// Check that non-zero levels are consistent with the base level. // Check that non-zero levels are consistent with the base level.
const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex); if (getInternalFormat(target, level) != getInternalFormat(target, 0))
if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
{ {
return false; return false;
} }
if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) if (getWidth(target, level) != std::max<size_t>(1, baseSize >> level))
{ {
return false; return false;
} }
...@@ -711,48 +687,18 @@ Texture3D::~Texture3D() ...@@ -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 bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{ {
GLsizei width = getBaseLevelWidth(); size_t width = getWidth(GL_TEXTURE_3D, 0);
GLsizei height = getBaseLevelHeight(); size_t height = getHeight(GL_TEXTURE_3D, 0);
GLsizei depth = getBaseLevelDepth(); size_t depth = getDepth(GL_TEXTURE_3D, 0);
if (width == 0 || height == 0 || depth == 0)
if (width <= 0 || height <= 0 || depth <= 0)
{ {
return false; 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; return false;
} }
...@@ -767,9 +713,12 @@ bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data & ...@@ -767,9 +713,12 @@ bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const Data &
bool Texture3D::isMipmapComplete() const 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)) if (!isLevelComplete(level))
{ {
...@@ -780,20 +729,19 @@ bool Texture3D::isMipmapComplete() const ...@@ -780,20 +729,19 @@ bool Texture3D::isMipmapComplete() const
return true; 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()) if (isImmutable())
{ {
return true; return true;
} }
GLsizei width = getBaseLevelWidth(); size_t width = getWidth(GL_TEXTURE_3D, level);
GLsizei height = getBaseLevelHeight(); size_t height = getHeight(GL_TEXTURE_3D, level);
GLsizei depth = getBaseLevelDepth(); size_t depth = getDepth(GL_TEXTURE_3D, level);
if (width == 0 || height == 0 || depth == 0)
if (width <= 0 || height <= 0 || depth <= 0)
{ {
return false; return false;
} }
...@@ -803,24 +751,22 @@ bool Texture3D::isLevelComplete(int level) const ...@@ -803,24 +751,22 @@ bool Texture3D::isLevelComplete(int level) const
return true; return true;
} }
rx::Image *levelImage = mTexture->getImage(level, 0); if (getInternalFormat(GL_TEXTURE_3D, level) != getInternalFormat(GL_TEXTURE_3D, 0))
if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
{ {
return false; 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; 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; 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; return false;
} }
...@@ -837,48 +783,18 @@ Texture2DArray::~Texture2DArray() ...@@ -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 bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
{ {
GLsizei width = getBaseLevelWidth(); size_t width = getWidth(GL_TEXTURE_2D_ARRAY, 0);
GLsizei height = getBaseLevelHeight(); size_t height = getHeight(GL_TEXTURE_2D_ARRAY, 0);
GLsizei depth = getLayers(0); size_t depth = getDepth(GL_TEXTURE_2D_ARRAY, 0);
if (width == 0 || height == 0 || depth == 0)
if (width <= 0 || height <= 0 || depth <= 0)
{ {
return false; 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; return false;
} }
...@@ -893,9 +809,11 @@ bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const D ...@@ -893,9 +809,11 @@ bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const D
bool Texture2DArray::isMipmapComplete() const 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)) if (!isLevelComplete(level))
{ {
...@@ -906,20 +824,19 @@ bool Texture2DArray::isMipmapComplete() const ...@@ -906,20 +824,19 @@ bool Texture2DArray::isMipmapComplete() const
return true; 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()) if (isImmutable())
{ {
return true; return true;
} }
GLsizei width = getBaseLevelWidth(); size_t width = getWidth(GL_TEXTURE_2D_ARRAY, level);
GLsizei height = getBaseLevelHeight(); size_t height = getHeight(GL_TEXTURE_2D_ARRAY, level);
GLsizei layers = getLayers(0); size_t layers = getDepth(GL_TEXTURE_2D_ARRAY, 0);
if (width == 0 || height == 0 || layers == 0)
if (width <= 0 || height <= 0 || layers <= 0)
{ {
return false; return false;
} }
...@@ -929,22 +846,22 @@ bool Texture2DArray::isLevelComplete(int level) const ...@@ -929,22 +846,22 @@ bool Texture2DArray::isLevelComplete(int level) const
return true; return true;
} }
if (getInternalFormat(level) != getInternalFormat(0)) if (getInternalFormat(GL_TEXTURE_2D_ARRAY, level) != getInternalFormat(GL_TEXTURE_2D_ARRAY, 0))
{ {
return false; 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; 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; return false;
} }
if (getLayers(level) != layers) if (getDepth(GL_TEXTURE_2D_ARRAY, level) != layers)
{ {
return false; return false;
} }
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "angle_gl.h" #include "angle_gl.h"
#include <vector> #include <vector>
#include <map>
namespace egl namespace egl
{ {
...@@ -57,14 +58,10 @@ class Texture : public RefCountObject ...@@ -57,14 +58,10 @@ class Texture : public RefCountObject
void setUsage(GLenum usage); void setUsage(GLenum usage);
GLenum getUsage() const; GLenum getUsage() const;
GLint getBaseLevelWidth() const; size_t getWidth(GLenum target, size_t level) const;
GLint getBaseLevelHeight() const; size_t getHeight(GLenum target, size_t level) const;
GLint getBaseLevelDepth() const; size_t getDepth(GLenum target, size_t level) const;
GLenum getBaseLevelInternalFormat() const; GLenum getInternalFormat(GLenum target, size_t level) const;
GLsizei getWidth(const ImageIndex &index) const;
GLsizei getHeight(const ImageIndex &index) const;
GLenum getInternalFormat(const ImageIndex &index) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const = 0; virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const = 0;
...@@ -100,8 +97,6 @@ class Texture : public RefCountObject ...@@ -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. 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: protected:
int mipLevels() const;
const rx::Image *getBaseLevelImage() const;
static unsigned int issueTextureSerial(); static unsigned int issueTextureSerial();
rx::TextureImpl *mTexture; rx::TextureImpl *mTexture;
...@@ -113,11 +108,39 @@ class Texture : public RefCountObject ...@@ -113,11 +108,39 @@ class Texture : public RefCountObject
GLenum mTarget; 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; const unsigned int mTextureSerial;
static unsigned int mCurrentTextureSerial; static unsigned int mCurrentTextureSerial;
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture); 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 class Texture2D : public Texture
...@@ -127,12 +150,6 @@ class Texture2D : public Texture ...@@ -127,12 +150,6 @@ class Texture2D : public Texture
virtual ~Texture2D(); 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, Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
const PixelUnpackState &unpack, const uint8_t *pixels) override; const PixelUnpackState &unpack, const uint8_t *pixels) override;
...@@ -154,7 +171,7 @@ class Texture2D : public Texture ...@@ -154,7 +171,7 @@ class Texture2D : public Texture
DISALLOW_COPY_AND_ASSIGN(Texture2D); DISALLOW_COPY_AND_ASSIGN(Texture2D);
bool isMipmapComplete() const; bool isMipmapComplete() const;
bool isLevelComplete(int level) const; bool isLevelComplete(size_t level) const;
egl::Surface *mSurface; egl::Surface *mSurface;
}; };
...@@ -166,12 +183,6 @@ class TextureCubeMap : public Texture ...@@ -166,12 +183,6 @@ class TextureCubeMap : public Texture
virtual ~TextureCubeMap(); 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; virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
bool isCubeComplete() const; bool isCubeComplete() const;
...@@ -183,7 +194,7 @@ class TextureCubeMap : public Texture ...@@ -183,7 +194,7 @@ class TextureCubeMap : public Texture
DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
bool isMipmapComplete() const; bool isMipmapComplete() const;
bool isFaceLevelComplete(int faceIndex, int level) const; bool isFaceLevelComplete(GLenum target, size_t level) const;
}; };
class Texture3D : public Texture class Texture3D : public Texture
...@@ -193,20 +204,13 @@ class Texture3D : public Texture ...@@ -193,20 +204,13 @@ class Texture3D : public Texture
virtual ~Texture3D(); 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; virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture3D); DISALLOW_COPY_AND_ASSIGN(Texture3D);
bool isMipmapComplete() const; bool isMipmapComplete() const;
bool isLevelComplete(int level) const; bool isLevelComplete(size_t level) const;
}; };
class Texture2DArray : public Texture class Texture2DArray : public Texture
...@@ -216,20 +220,13 @@ class Texture2DArray : public Texture ...@@ -216,20 +220,13 @@ class Texture2DArray : public Texture
virtual ~Texture2DArray(); 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; virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
private: private:
DISALLOW_COPY_AND_ASSIGN(Texture2DArray); DISALLOW_COPY_AND_ASSIGN(Texture2DArray);
bool isMipmapComplete() const; 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 ...@@ -1230,28 +1230,11 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
const gl::Caps &caps = context->getCaps(); 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; GLuint maxDimension = 0;
switch (target) switch (target)
{ {
case GL_TEXTURE_2D: case GL_TEXTURE_2D:
{ maxDimension = caps.max2DTextureSize;
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;
}
}
break; break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
...@@ -1260,48 +1243,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi ...@@ -1260,48 +1243,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{ maxDimension = caps.maxCubeMapTextureSize;
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;
}
}
break; break;
case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_2D_ARRAY:
{ maxDimension = caps.max2DTextureSize;
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;
}
}
break; break;
case GL_TEXTURE_3D: case GL_TEXTURE_3D:
{ maxDimension = caps.max3DTextureSize;
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;
}
}
break; break;
default: default:
...@@ -1309,6 +1259,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi ...@@ -1309,6 +1259,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false; return false;
} }
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture) if (!texture)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
...@@ -1329,21 +1280,17 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi ...@@ -1329,21 +1280,17 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false; return false;
} }
if (formatInfo.compressed) if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
{ {
if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) || context->recordError(Error(GL_INVALID_OPERATION));
((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight)) return false;
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
} }
if (isSubImage) if (isSubImage)
{ {
if (xoffset + width > textureLevelWidth || if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
yoffset + height > textureLevelHeight || static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
zoffset >= textureLevelDepth) static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
{ {
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
...@@ -1371,7 +1318,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi ...@@ -1371,7 +1318,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
} }
} }
*textureFormatOut = textureInternalFormat; *textureFormatOut = texture->getInternalFormat(target, level);
return true; return true;
} }
...@@ -1786,12 +1733,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach ...@@ -1786,12 +1733,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
if (tex2d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
} }
break; break;
...@@ -1812,12 +1753,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach ...@@ -1812,12 +1753,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
if (texcube->isCompressed(textarget, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
} }
break; break;
...@@ -1825,6 +1760,13 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach ...@@ -1825,6 +1760,13 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_ENUM)); context->recordError(Error(GL_INVALID_ENUM));
return false; 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; return true;
......
...@@ -21,218 +21,118 @@ ...@@ -21,218 +21,118 @@
namespace gl namespace gl
{ {
static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height, bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
gl::Texture2D *texture) 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; 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; return false;
} }
if (format != GL_NONE) if (level < 0 || xoffset < 0 ||
{ std::numeric_limits<GLsizei>::max() - xoffset < width ||
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level)) std::numeric_limits<GLsizei>::max() - yoffset < height)
{
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))
{ {
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
return true; if (!isSubImage && !isCompressed && internalformat != format)
}
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)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
if (compressed != texture->isCompressed(target, level)) const gl::Caps &caps = context->getCaps();
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
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; return false;
} }
} }
else if (IsCubemapTextureTarget(target))
if (compressed)
{ {
if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || if (!isSubImage && width != height)
(height % 4 != 0 && height != texture->getHeight(target, 0)))
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
}
if (xoffset + width > texture->getWidth(target, level) || if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
yoffset + height > texture->getHeight(target, level)) static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
{ {
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
}
} }
else
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))
{ {
context->recordError(Error(GL_INVALID_ENUM)); context->recordError(Error(GL_INVALID_ENUM));
return false; return false;
} }
if (!ValidImageSize(context, target, level, width, height, 1)) gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
{ if (!texture)
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)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
const gl::Caps &caps = context->getCaps(); if (isSubImage)
gl::Texture *texture = NULL;
GLenum textureInternalFormat = GL_NONE;
switch (target)
{ {
case GL_TEXTURE_2D: if (format != GL_NONE)
{ {
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, 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))
{ {
context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
texture = tex2d;
} }
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X: if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
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 (!isSubImage && width != height) context->recordError(Error(GL_INVALID_VALUE));
{ return false;
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;
}
} }
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
} }
else
if (!texture)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); if (texture->isImmutable())
return false; {
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; return false;
} }
// Verify zero border GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
if (border != 0) const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
if (isCompressed != actualFormatInfo.compressed)
{ {
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
if (isCompressed) if (isCompressed)
{ {
if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "common/mathutil.h" #include "common/mathutil.h"
#include "common/utilities.h"
namespace gl namespace gl
{ {
...@@ -310,33 +311,14 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -310,33 +311,14 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
const gl::Caps &caps = context->getCaps(); 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) switch (target)
{ {
case GL_TEXTURE_2D: 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) || context->recordError(Error(GL_INVALID_VALUE));
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) return false;
{
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;
}
} }
break; break;
...@@ -346,83 +328,45 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -346,83 +328,45 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (!isSubImage && width != height)
{ {
if (!isSubImage && width != height) context->recordError(Error(GL_INVALID_VALUE));
{ return false;
context->recordError(Error(GL_INVALID_VALUE)); }
return false;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
if (textureCube) {
{ context->recordError(Error(GL_INVALID_VALUE));
textureCompressed = textureCube->isCompressed(target, level); return false;
textureInternalFormat = textureCube->getInternalFormat(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
}
} }
break; break;
case GL_TEXTURE_3D: 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) || context->recordError(Error(GL_INVALID_VALUE));
static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) || return false;
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;
}
} }
break; break;
case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_2D_ARRAY:
{ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) || static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) || static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level)) {
{ context->recordError(Error(GL_INVALID_VALUE));
context->recordError(Error(GL_INVALID_VALUE)); return false;
return false; }
} break;
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;
default: default:
context->recordError(Error(GL_INVALID_ENUM)); context->recordError(Error(GL_INVALID_ENUM));
return false; return false;
} }
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture) if (!texture)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
...@@ -436,7 +380,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -436,7 +380,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
} }
// Validate texture formats // Validate texture formats
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat); const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
if (isCompressed) if (isCompressed)
{ {
...@@ -475,22 +419,12 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -475,22 +419,12 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
// Validate sub image parameters // Validate sub image parameters
if (isSubImage) if (isSubImage)
{ {
if (isCompressed != textureCompressed) if (isCompressed != actualFormatInfo.compressed)
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; 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) if (width == 0 || height == 0 || depth == 0)
{ {
return false; return false;
...@@ -510,9 +444,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -510,9 +444,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
return false; return false;
} }
if (xoffset + width > textureLevelWidth || if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
yoffset + height > textureLevelHeight || static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
zoffset + depth > textureLevelDepth) static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
{ {
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
...@@ -1067,13 +1001,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att ...@@ -1067,13 +1001,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
if (texArray->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
} }
break; break;
...@@ -1090,13 +1017,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att ...@@ -1090,13 +1017,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
if (tex3d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
} }
break; break;
...@@ -1104,6 +1024,13 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att ...@@ -1104,6 +1024,13 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; 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; return true;
......
...@@ -1453,7 +1453,8 @@ void GL_APIENTRY GenerateMipmap(GLenum target) ...@@ -1453,7 +1453,8 @@ void GL_APIENTRY GenerateMipmap(GLenum target)
return; 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 TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat); const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
...@@ -1484,7 +1485,7 @@ void GL_APIENTRY GenerateMipmap(GLenum target) ...@@ -1484,7 +1485,7 @@ void GL_APIENTRY GenerateMipmap(GLenum target)
} }
// Non-power of 2 ES2 check // 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)); ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
context->recordError(Error(GL_INVALID_OPERATION)); 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