Commit d9a2e7bf by Alexis Hetu Committed by Alexis Hétu

Fixed format validations

Format validations were failing if the exact same format wasn't used between different texture related calls to the same texture, even when the formats were equivalent, so I added a GetSizedInternalFormat function based on a format map (courtesy of Angle). The validation checks were also unified in utilities.cpp and used wherever texture formats were used, to make sure Image objects used in Texture objects always use the sized format, so that format comparisons work properly. Change-Id: I72fc8fb1b0f135ac679c274866e5b8e223541e7f Reviewed-on: https://swiftshader-review.googlesource.com/4082Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent d18c069d
......@@ -468,6 +468,7 @@ namespace egl
}
break;
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
switch(type)
{
case GL_UNSIGNED_BYTE: return sw::FORMAT_A8R8G8B8;
......@@ -735,6 +736,7 @@ namespace egl
case GL_RGBA_INTEGER:
return sw::FORMAT_A8B8G8R8UI;
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
return sw::FORMAT_A8R8G8B8;
case GL_ALPHA:
case GL_ALPHA8_EXT:
......@@ -923,7 +925,8 @@ namespace egl
case GL_SRGB8_ALPHA8:
case GL_RGBA: return sizeof(unsigned char) * 4;
case GL_RGBA_INTEGER: return sizeof(unsigned char) * 4;
case GL_BGRA_EXT: return sizeof(unsigned char) * 4;
case GL_BGRA_EXT:
case GL_BGRA8_EXT: return sizeof(unsigned char)* 4;
default: UNREACHABLE(format);
}
break;
......@@ -1226,6 +1229,7 @@ namespace egl
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
default: UNREACHABLE(format);
......@@ -1267,6 +1271,7 @@ namespace egl
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
case GL_SRGB8:
......@@ -1441,6 +1446,7 @@ namespace egl
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
default: UNREACHABLE(format);
......@@ -1471,6 +1477,7 @@ namespace egl
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
case GL_DEPTH_COMPONENT:
......@@ -1505,6 +1512,7 @@ namespace egl
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
default: UNREACHABLE(format);
......@@ -1535,6 +1543,7 @@ namespace egl
case GL_RGBA:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break;
case GL_DEPTH_COMPONENT16:
......
......@@ -339,13 +339,13 @@ GLsizei Texture2D::getHeight(GLenum target, GLint level) const
GLenum Texture2D::getFormat(GLenum target, GLint level) const
{
ASSERT(target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D);
return image[level] ? image[level]->getFormat() : 0;
return image[level] ? image[level]->getFormat() : GL_NONE;
}
GLenum Texture2D::getType(GLenum target, GLint level) const
{
ASSERT(target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D);
return image[level] ? image[level]->getType() : 0;
return image[level] ? image[level]->getType() : GL_NONE;
}
sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
......@@ -716,13 +716,13 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
GLenum TextureCubeMap::getFormat(GLenum target, GLint level) const
{
int face = CubeFaceIndex(target);
return image[face][level] ? image[face][level]->getFormat() : 0;
return image[face][level] ? image[face][level]->getFormat() : GL_NONE;
}
GLenum TextureCubeMap::getType(GLenum target, GLint level) const
{
int face = CubeFaceIndex(target);
return image[face][level] ? image[face][level]->getType() : 0;
return image[face][level] ? image[face][level]->getType() : GL_NONE;
}
sw::Format TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
......
......@@ -407,13 +407,13 @@ GLsizei Texture2D::getHeight(GLenum target, GLint level) const
GLenum Texture2D::getFormat(GLenum target, GLint level) const
{
ASSERT(target == GL_TEXTURE_2D);
return image[level] ? image[level]->getFormat() : 0;
return image[level] ? image[level]->getFormat() : GL_NONE;
}
GLenum Texture2D::getType(GLenum target, GLint level) const
{
ASSERT(target == GL_TEXTURE_2D);
return image[level] ? image[level]->getType() : 0;
return image[level] ? image[level]->getType() : GL_NONE;
}
sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
......
......@@ -578,13 +578,13 @@ GLsizei Texture2D::getHeight(GLenum target, GLint level) const
GLenum Texture2D::getFormat(GLenum target, GLint level) const
{
ASSERT(target == GL_TEXTURE_2D);
return image[level] ? image[level]->getFormat() : 0;
return image[level] ? image[level]->getFormat() : GL_NONE;
}
GLenum Texture2D::getType(GLenum target, GLint level) const
{
ASSERT(target == GL_TEXTURE_2D);
return image[level] ? image[level]->getType() : 0;
return image[level] ? image[level]->getType() : GL_NONE;
}
sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
......@@ -678,7 +678,8 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
image[level]->unbind(this);
}
image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE);
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[level])
{
......@@ -713,7 +714,8 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
image[level]->unbind(this);
}
image[level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE);
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[level])
{
......@@ -733,7 +735,7 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
copy(renderTarget, sourceRect, format, 0, 0, 0, image[level]);
copy(renderTarget, sourceRect, sizedInternalFormat, 0, 0, 0, image[level]);
}
renderTarget->release();
......@@ -1079,7 +1081,8 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma
image[face][level]->unbind(this);
}
image[face][level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE);
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[face][level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[face][level])
{
......@@ -1247,7 +1250,8 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
image[face][level]->unbind(this);
}
image[face][level] = new egl::Image(this, width, height, format, GL_UNSIGNED_BYTE);
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[face][level] = new egl::Image(this, width, height, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[face][level])
{
......@@ -1267,7 +1271,7 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
copy(renderTarget, sourceRect, format, 0, 0, 0, image[face][level]);
copy(renderTarget, sourceRect, sizedInternalFormat, 0, 0, 0, image[face][level]);
}
renderTarget->release();
......@@ -1484,13 +1488,13 @@ GLsizei Texture3D::getDepth(GLenum target, GLint level) const
GLenum Texture3D::getFormat(GLenum target, GLint level) const
{
ASSERT(target == getTarget());
return image[level] ? image[level]->getFormat() : 0;
return image[level] ? image[level]->getFormat() : GL_NONE;
}
GLenum Texture3D::getType(GLenum target, GLint level) const
{
ASSERT(target == getTarget());
return image[level] ? image[level]->getType() : 0;
return image[level] ? image[level]->getType() : GL_NONE;
}
sw::Format Texture3D::getInternalFormat(GLenum target, GLint level) const
......@@ -1580,7 +1584,8 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
image[level]->unbind(this);
}
image[level] = new egl::Image(this, width, height, depth, format, GL_UNSIGNED_BYTE);
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[level] = new egl::Image(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[level])
{
......@@ -1592,7 +1597,7 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
void Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const egl::Image::UnpackInfo& unpackInfo, const void *pixels)
{
Texture::subImage(xoffset, yoffset, zoffset, width, height, format, depth, type, unpackInfo, pixels, image[level]);
Texture::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpackInfo, pixels, image[level]);
}
void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels)
......@@ -1615,7 +1620,8 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z,
image[level]->unbind(this);
}
image[level] = new egl::Image(this, width, height, depth, format, GL_UNSIGNED_BYTE);
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
image[level] = new egl::Image(this, width, height, depth, sizedInternalFormat, GL_UNSIGNED_BYTE);
if(!image[level])
{
......@@ -1636,7 +1642,7 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z,
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
for(GLint sliceZ = 0; sliceZ < depth; ++sliceZ, ++sourceRect.slice)
{
copy(renderTarget, sourceRect, format, 0, 0, sliceZ, image[level]);
copy(renderTarget, sourceRect, sizedInternalFormat, 0, 0, sliceZ, image[level]);
}
}
......
......@@ -46,49 +46,13 @@ static bool validImageSize(GLint level, GLsizei width, GLsizei height)
return true;
}
static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum format, es2::Texture *texture)
{
if(!texture)
{
return error(GL_INVALID_OPERATION, false);
}
if(compressed != texture->isCompressed(target, level))
{
return error(GL_INVALID_OPERATION, false);
}
if(format != GL_NONE && format != texture->getFormat(target, level))
{
return error(GL_INVALID_OPERATION, false);
}
if(compressed)
{
if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
(height % 4 != 0 && height != texture->getHeight(target, 0)) ||
(depth % 4 != 0 && depth != texture->getDepth(target, 0)))
{
return error(GL_INVALID_OPERATION, false);
}
}
if(xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, level) ||
zoffset + depth > texture->getDepth(target, level))
{
return error(GL_INVALID_VALUE, false);
}
return true;
}
static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
{
GLenum formatError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
if(formatError != GL_NONE)
GLenum validationError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
if(validationError != GL_NONE)
{
return error(formatError, false);
return error(validationError, false);
}
switch(textureFormat)
......@@ -706,7 +670,7 @@ GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint inter
return error(GL_INVALID_OPERATION);
}
texture->setImage(level, width, height, depth, internalformat, type, context->getUnpackInfo(), pixels);
texture->setImage(level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), pixels);
}
}
......@@ -747,9 +711,16 @@ GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xo
{
es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray();
if(validateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, format, texture))
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
{
texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getUnpackInfo(), pixels);
texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), pixels);
}
else
{
return error(validationError);
}
}
}
......@@ -800,9 +771,10 @@ GL_APICALL void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLin
GLenum colorbufferFormat = source->getFormat();
es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray();
if(!validateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture))
GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
if(validationError != GL_NONE)
{
return;
return error(validationError);
}
GLenum textureFormat = texture->getFormat(target, level);
......@@ -852,10 +824,10 @@ GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, G
return error(GL_INVALID_OPERATION);
default:
{
GLenum formatError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
if(formatError != GL_NONE)
GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
if(validationError != GL_NONE)
{
return error(formatError);
return error(validationError);
}
}
}
......@@ -901,10 +873,10 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
return error(GL_INVALID_VALUE);
}
GLenum formatError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
if(formatError != GL_NONE)
GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
if(validationError != GL_NONE)
{
return error(formatError);
return error(validationError);
}
if(width == 0 || height == 0 || depth == 0 || data == NULL)
......@@ -3875,7 +3847,7 @@ GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum
for(int level = 0; level < levels; ++level)
{
texture->setImage(level, width, height, internalformat, type, context->getUnpackInfo(), NULL);
texture->setImage(level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), NULL);
width = std::max(1, (width / 2));
height = std::max(1, (height / 2));
}
......@@ -3894,7 +3866,7 @@ GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum
{
for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
{
texture->setImage(face, level, width, height, internalformat, type, context->getUnpackInfo(), NULL);
texture->setImage(face, level, width, height, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), NULL);
}
width = std::max(1, (width / 2));
height = std::max(1, (height / 2));
......@@ -3945,7 +3917,7 @@ GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum
for(int level = 0; level < levels; ++level)
{
texture->setImage(level, width, height, depth, internalformat, type, context->getUnpackInfo(), NULL);
texture->setImage(level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), NULL);
width = std::max(1, (width / 2));
height = std::max(1, (height / 2));
depth = std::max(1, (depth / 2));
......@@ -3970,7 +3942,7 @@ GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum
{
for(int face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; ++face)
{
texture->setImage(level, width, height, depth, internalformat, type, context->getUnpackInfo(), NULL);
texture->setImage(level, width, height, depth, GetSizedInternalFormat(internalformat, type), type, context->getUnpackInfo(), NULL);
}
width = std::max(1, (width / 2));
height = std::max(1, (height / 2));
......
......@@ -41,7 +41,10 @@ namespace es2
GLint floatToInt(GLfloat value);
bool IsCompressed(GLenum format, egl::GLint clientVersion);
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
GLenum ValidateCompressedFormat(GLenum format, egl::GLint clientVersion, bool expectCompressedFormats);
GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture);
GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture);
bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, egl::GLint clientVersion);
bool IsDepthTexture(GLenum format);
bool IsStencilTexture(GLenum format);
......
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