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
......
...@@ -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