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);
Texture2D::~Texture2D() if (mTarget == GL_TEXTURE_CUBE_MAP)
{
if (mSurface)
{ {
mSurface->releaseTexImage(EGL_BACK_BUFFER); for (size_t face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
mSurface = NULL; {
setImageDesc(ImageIdentifier(face, level), levelInfo);
}
}
else
{
setImageDesc(ImageIdentifier(mTarget, level), levelInfo);
}
} }
} }
GLsizei Texture2D::getWidth(GLint level) const Texture::ImageIdentifier::ImageIdentifier()
: ImageIdentifier(GL_TEXTURE_2D, 0)
{ {
if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
return mTexture->getImage(level, 0)->getWidth();
else
return 0;
} }
GLsizei Texture2D::getHeight(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)->getHeight();
else
return 0;
} }
GLenum Texture2D::getInternalFormat(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)->getInternalFormat(); }
else
return GL_NONE; Texture::ImageDesc::ImageDesc()
: ImageDesc(Extents(0, 0, 0), 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, 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:
{
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; 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:
{
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; break;
case GL_TEXTURE_2D_ARRAY: 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; break;
case GL_TEXTURE_3D: 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; 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) ||
((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight))
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; 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,96 +21,6 @@ ...@@ -21,96 +21,6 @@
namespace gl 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)
{
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (compressed != texture->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
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))
{
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)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (compressed != texture->isCompressed(target, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (format != GL_NONE)
{
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (compressed)
{
if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
(height % 4 != 0 && height != texture->getHeight(target, 0)))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, 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, bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type, const GLvoid *pixels) GLint border, GLenum format, GLenum type, const GLvoid *pixels)
...@@ -143,11 +53,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -143,11 +53,7 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
const gl::Caps &caps = context->getCaps(); const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL; if (target == GL_TEXTURE_2D)
GLenum textureInternalFormat = GL_NONE;
switch (target)
{
case GL_TEXTURE_2D:
{ {
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))
...@@ -155,30 +61,8 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -155,30 +61,8 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
gl::Texture2D *tex2d = context->getTexture2D();
if (tex2d)
{
textureInternalFormat = tex2d->getInternalFormat(level);
texture = tex2d;
} }
else if (IsCubemapTextureTarget(target))
if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
level, format, type, tex2d))
{
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 (!isSubImage && width != height) if (!isSubImage && width != height)
{ {
...@@ -192,38 +76,46 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -192,38 +76,46 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
gl::TextureCubeMap *texCube = context->getTextureCubeMap();
if (texCube)
{
textureInternalFormat = texCube->getInternalFormat(target, level);
texture = texCube;
} }
else
if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
target, level, format, type, texCube))
{ {
context->recordError(Error(GL_INVALID_ENUM));
return false; return false;
} }
}
break;
default: gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
context->recordError(Error(GL_INVALID_ENUM)); if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
if (!texture) if (isSubImage)
{
if (format != GL_NONE)
{
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
}
if (!isSubImage && texture->isImmutable()) if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
else
{
if (texture->isImmutable())
{ {
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
}
// Verify zero border // Verify zero border
if (border != 0) if (border != 0)
...@@ -232,7 +124,15 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -232,7 +124,15 @@ bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level,
return false; return false;
} }
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
if (isCompressed != actualFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
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,34 +311,15 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -310,34 +311,15 @@ 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) || if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level)) static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{ {
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; 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;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X: case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
...@@ -346,7 +328,6 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -346,7 +328,6 @@ 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)); context->recordError(Error(GL_INVALID_VALUE));
...@@ -358,22 +339,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -358,22 +339,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; 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;
}
}
break; break;
case GL_TEXTURE_3D: case GL_TEXTURE_3D:
{
if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) || if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) || static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level)) static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
...@@ -381,22 +349,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -381,22 +349,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; 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))
...@@ -404,18 +359,6 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -404,18 +359,6 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; 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; break;
default: default:
...@@ -423,6 +366,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level, ...@@ -423,6 +366,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
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,17 +1017,17 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att ...@@ -1090,17 +1017,17 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE)); context->recordError(Error(GL_INVALID_VALUE));
return false; return false;
} }
}
break;
gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex); default:
if (tex3d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
}
break;
default: const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
if (internalFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION)); context->recordError(Error(GL_INVALID_OPERATION));
return false; return false;
} }
......
...@@ -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