Commit a9be0dc6 by Geoff Lang

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

BUG=angle:681 Change-Id: Ifb3f52d6348e4479181e66f1c39578f49e9dcf76 Reviewed-on: https://chromium-review.googlesource.com/235613Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarBrandon Jones <bajones@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 24d5811b
......@@ -98,17 +98,17 @@ GLuint TextureAttachment::id() const
GLsizei TextureAttachment::getWidth() const
{
return mTexture->getWidth(mIndex);
return mTexture->getWidth(mIndex.type, mIndex.mipIndex);
}
GLsizei TextureAttachment::getHeight() const
{
return mTexture->getHeight(mIndex);
return mTexture->getHeight(mIndex.type, mIndex.mipIndex);
}
GLenum TextureAttachment::getInternalFormat() const
{
return mTexture->getInternalFormat(mIndex);
return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex);
}
GLenum TextureAttachment::type() const
......
......@@ -21,6 +21,7 @@
#include "angle_gl.h"
#include <vector>
#include <map>
namespace egl
{
......@@ -57,14 +58,10 @@ class Texture : public RefCountObject
void setUsage(GLenum usage);
GLenum getUsage() const;
GLint getBaseLevelWidth() const;
GLint getBaseLevelHeight() const;
GLint getBaseLevelDepth() const;
GLenum getBaseLevelInternalFormat() const;
GLsizei getWidth(const ImageIndex &index) const;
GLsizei getHeight(const ImageIndex &index) const;
GLenum getInternalFormat(const ImageIndex &index) const;
size_t getWidth(GLenum target, size_t level) const;
size_t getHeight(GLenum target, size_t level) const;
size_t getDepth(GLenum target, size_t level) const;
GLenum getInternalFormat(GLenum target, size_t level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const = 0;
......@@ -100,8 +97,6 @@ class Texture : public RefCountObject
static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
protected:
int mipLevels() const;
const rx::Image *getBaseLevelImage() const;
static unsigned int issueTextureSerial();
rx::TextureImpl *mTexture;
......@@ -113,11 +108,39 @@ class Texture : public RefCountObject
GLenum mTarget;
struct ImageIdentifier
{
GLenum target;
size_t level;
ImageIdentifier();
ImageIdentifier(GLenum target, size_t level);
bool operator<(const ImageIdentifier &other) const;
};
struct ImageDesc
{
Extents size;
GLenum internalFormat;
ImageDesc();
ImageDesc(const Extents &size, GLenum internalFormat);
};
const unsigned int mTextureSerial;
static unsigned int mCurrentTextureSerial;
private:
DISALLOW_COPY_AND_ASSIGN(Texture);
const ImageDesc &getImageDesc(const ImageIdentifier& index) const;
void setImageDesc(const ImageIdentifier& index, const ImageDesc &desc);
void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat);
void clearImageDescs();
typedef std::map<ImageIdentifier, ImageDesc> ImageDescMap;
ImageDescMap mImageDescs;
};
class Texture2D : public Texture
......@@ -127,12 +150,6 @@ class Texture2D : public Texture
virtual ~Texture2D();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
const PixelUnpackState &unpack, const uint8_t *pixels) override;
......@@ -154,7 +171,7 @@ class Texture2D : public Texture
DISALLOW_COPY_AND_ASSIGN(Texture2D);
bool isMipmapComplete() const;
bool isLevelComplete(int level) const;
bool isLevelComplete(size_t level) const;
egl::Surface *mSurface;
};
......@@ -166,12 +183,6 @@ class TextureCubeMap : public Texture
virtual ~TextureCubeMap();
GLsizei getWidth(GLenum target, GLint level) const;
GLsizei getHeight(GLenum target, GLint level) const;
GLenum getInternalFormat(GLenum target, GLint level) const;
bool isCompressed(GLenum target, GLint level) const;
bool isDepth(GLenum target, GLint level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
bool isCubeComplete() const;
......@@ -183,7 +194,7 @@ class TextureCubeMap : public Texture
DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
bool isMipmapComplete() const;
bool isFaceLevelComplete(int faceIndex, int level) const;
bool isFaceLevelComplete(GLenum target, size_t level) const;
};
class Texture3D : public Texture
......@@ -193,20 +204,13 @@ class Texture3D : public Texture
virtual ~Texture3D();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLsizei getDepth(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
private:
DISALLOW_COPY_AND_ASSIGN(Texture3D);
bool isMipmapComplete() const;
bool isLevelComplete(int level) const;
bool isLevelComplete(size_t level) const;
};
class Texture2DArray : public Texture
......@@ -216,20 +220,13 @@ class Texture2DArray : public Texture
virtual ~Texture2DArray();
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLsizei getLayers(GLint level) const;
GLenum getInternalFormat(GLint level) const;
bool isCompressed(GLint level) const;
bool isDepth(GLint level) const;
virtual bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
private:
DISALLOW_COPY_AND_ASSIGN(Texture2DArray);
bool isMipmapComplete() const;
bool isLevelComplete(int level) const;
bool isLevelComplete(size_t level) const;
};
}
......
......@@ -1230,28 +1230,11 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL;
GLenum textureInternalFormat = GL_NONE;
GLint textureLevelWidth = 0;
GLint textureLevelHeight = 0;
GLint textureLevelDepth = 0;
GLuint maxDimension = 0;
switch (target)
{
case GL_TEXTURE_2D:
{
gl::Texture2D *texture2d = context->getTexture2D();
if (texture2d)
{
textureInternalFormat = texture2d->getInternalFormat(level);
textureLevelWidth = texture2d->getWidth(level);
textureLevelHeight = texture2d->getHeight(level);
textureLevelDepth = 1;
texture = texture2d;
maxDimension = caps.max2DTextureSize;
}
}
maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
......@@ -1260,48 +1243,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{
gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
if (textureCube)
{
textureInternalFormat = textureCube->getInternalFormat(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
maxDimension = caps.maxCubeMapTextureSize;
}
}
maxDimension = caps.maxCubeMapTextureSize;
break;
case GL_TEXTURE_2D_ARRAY:
{
gl::Texture2DArray *texture2dArray = context->getTexture2DArray();
if (texture2dArray)
{
textureInternalFormat = texture2dArray->getInternalFormat(level);
textureLevelWidth = texture2dArray->getWidth(level);
textureLevelHeight = texture2dArray->getHeight(level);
textureLevelDepth = texture2dArray->getLayers(level);
texture = texture2dArray;
maxDimension = caps.max2DTextureSize;
}
}
maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_3D:
{
gl::Texture3D *texture3d = context->getTexture3D();
if (texture3d)
{
textureInternalFormat = texture3d->getInternalFormat(level);
textureLevelWidth = texture3d->getWidth(level);
textureLevelHeight = texture3d->getHeight(level);
textureLevelDepth = texture3d->getDepth(level);
texture = texture3d;
maxDimension = caps.max3DTextureSize;
}
}
maxDimension = caps.max3DTextureSize;
break;
default:
......@@ -1309,6 +1259,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false;
}
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
......@@ -1329,21 +1280,17 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false;
}
if (formatInfo.compressed)
if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
{
if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) ||
((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (isSubImage)
{
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset >= textureLevelDepth)
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
......@@ -1371,7 +1318,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
}
}
*textureFormatOut = textureInternalFormat;
*textureFormatOut = texture->getInternalFormat(target, level);
return true;
}
......@@ -1786,12 +1733,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
if (tex2d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1812,12 +1753,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
if (texcube->isCompressed(textarget, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1825,6 +1760,13 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level));
if (internalFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
return true;
......
......@@ -21,218 +21,118 @@
namespace gl
{
static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height,
GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
gl::Texture2D *texture)
bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type, const GLvoid *pixels)
{
if (!texture)
if (!ValidTexture2DDestinationTarget(context, target))
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (compressed != texture->isCompressed(level))
if (!ValidImageSize(context, target, level, width, height, 1))
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (format != GL_NONE)
{
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (compressed)
{
if ((width % 4 != 0 && width != texture->getWidth(level)) ||
(height % 4 != 0 && height != texture->getHeight(level)))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (xoffset + width > texture->getWidth(level) ||
yoffset + height > texture->getHeight(level))
if (level < 0 || xoffset < 0 ||
std::numeric_limits<GLsizei>::max() - xoffset < width ||
std::numeric_limits<GLsizei>::max() - yoffset < height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
return true;
}
static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height,
GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
gl::TextureCubeMap *texture)
{
if (!texture)
if (!isSubImage && !isCompressed && internalformat != format)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (compressed != texture->isCompressed(target, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
const gl::Caps &caps = context->getCaps();
if (format != GL_NONE)
if (target == GL_TEXTURE_2D)
{
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
if (compressed)
else if (IsCubemapTextureTarget(target))
{
if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
(height % 4 != 0 && height != texture->getHeight(target, 0)))
if (!isSubImage && width != height)
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
if (xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
return true;
}
bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLint border, GLenum format, GLenum type, const GLvoid *pixels)
{
if (!ValidTexture2DDestinationTarget(context, target))
else
{
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (!ValidImageSize(context, target, level, width, height, 1))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (level < 0 || xoffset < 0 ||
std::numeric_limits<GLsizei>::max() - xoffset < width ||
std::numeric_limits<GLsizei>::max() - yoffset < height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (!isSubImage && !isCompressed && internalformat != format)
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL;
GLenum textureInternalFormat = GL_NONE;
switch (target)
if (isSubImage)
{
case GL_TEXTURE_2D:
if (format != GL_NONE)
{
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2D *tex2d = context->getTexture2D();
if (tex2d)
{
textureInternalFormat = tex2d->getInternalFormat(level);
texture = tex2d;
}
if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
level, format, type, tex2d))
if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
texture = tex2d;
}
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
{
if (!isSubImage && width != height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::TextureCubeMap *texCube = context->getTextureCubeMap();
if (texCube)
{
textureInternalFormat = texCube->getInternalFormat(target, level);
texture = texCube;
}
if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
target, level, format, type, texCube))
{
return false;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
if (!texture)
else
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
if (texture->isImmutable())
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (!isSubImage && texture->isImmutable())
// Verify zero border
if (border != 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
// Verify zero border
if (border != 0)
GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
if (isCompressed != actualFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_VALUE));
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
if (isCompressed)
{
if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
......
......@@ -16,6 +16,7 @@
#include "libANGLE/FramebufferAttachment.h"
#include "common/mathutil.h"
#include "common/utilities.h"
namespace gl
{
......@@ -310,33 +311,14 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
const gl::Caps &caps = context->getCaps();
gl::Texture *texture = NULL;
bool textureCompressed = false;
GLenum textureInternalFormat = GL_NONE;
GLint textureLevelWidth = 0;
GLint textureLevelHeight = 0;
GLint textureLevelDepth = 0;
switch (target)
{
case GL_TEXTURE_2D:
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2D *texture2d = context->getTexture2D();
if (texture2d)
{
textureCompressed = texture2d->isCompressed(level);
textureInternalFormat = texture2d->getInternalFormat(level);
textureLevelWidth = texture2d->getWidth(level);
textureLevelHeight = texture2d->getHeight(level);
textureLevelDepth = 1;
texture = texture2d;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
......@@ -346,83 +328,45 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
if (!isSubImage && width != height)
{
if (!isSubImage && width != height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
if (textureCube)
{
textureCompressed = textureCube->isCompressed(target, level);
textureInternalFormat = textureCube->getInternalFormat(target, level);
textureLevelWidth = textureCube->getWidth(target, level);
textureLevelHeight = textureCube->getHeight(target, level);
textureLevelDepth = 1;
texture = textureCube;
}
if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
case GL_TEXTURE_3D:
if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
{
if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture3D *texture3d = context->getTexture3D();
if (texture3d)
{
textureCompressed = texture3d->isCompressed(level);
textureInternalFormat = texture3d->getInternalFormat(level);
textureLevelWidth = texture3d->getWidth(level);
textureLevelHeight = texture3d->getHeight(level);
textureLevelDepth = texture3d->getDepth(level);
texture = texture3d;
}
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
case GL_TEXTURE_2D_ARRAY:
{
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2DArray *texture2darray = context->getTexture2DArray();
if (texture2darray)
{
textureCompressed = texture2darray->isCompressed(level);
textureInternalFormat = texture2darray->getInternalFormat(level);
textureLevelWidth = texture2darray->getWidth(level);
textureLevelHeight = texture2darray->getHeight(level);
textureLevelDepth = texture2darray->getLayers(level);
texture = texture2darray;
}
}
break;
case GL_TEXTURE_2D_ARRAY:
if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
gl::Texture *texture = context->getTargetTexture(IsCubemapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
......@@ -436,7 +380,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
}
// Validate texture formats
GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
if (isCompressed)
{
......@@ -475,22 +419,12 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
// Validate sub image parameters
if (isSubImage)
{
if (isCompressed != textureCompressed)
if (isCompressed != actualFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
if (isCompressed)
{
if ((width % 4 != 0 && width != textureLevelWidth) ||
(height % 4 != 0 && height != textureLevelHeight))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
if (width == 0 || height == 0 || depth == 0)
{
return false;
......@@ -510,9 +444,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
if (xoffset + width > textureLevelWidth ||
yoffset + height > textureLevelHeight ||
zoffset + depth > textureLevelDepth)
if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
......@@ -1067,13 +1001,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
if (texArray->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1090,13 +1017,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
if (tex3d->isCompressed(level))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
break;
......@@ -1104,6 +1024,13 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
if (internalFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
}
return true;
......
......@@ -1453,7 +1453,8 @@ void GL_APIENTRY GenerateMipmap(GLenum target)
return;
}
GLenum internalFormat = texture->getBaseLevelInternalFormat();
GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
GLenum internalFormat = texture->getInternalFormat(baseTarget, 0);
const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
......@@ -1484,7 +1485,7 @@ void GL_APIENTRY GenerateMipmap(GLenum target)
}
// Non-power of 2 ES2 check
if (!context->getExtensions().textureNPOT && (!isPow2(texture->getBaseLevelWidth()) || !isPow2(texture->getBaseLevelHeight())))
if (!context->getExtensions().textureNPOT && (!isPow2(texture->getWidth(baseTarget, 0)) || !isPow2(texture->getHeight(baseTarget, 0))))
{
ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
context->recordError(Error(GL_INVALID_OPERATION));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment