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 ...@@ -468,6 +468,7 @@ namespace egl
} }
break; break;
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
switch(type) switch(type)
{ {
case GL_UNSIGNED_BYTE: return sw::FORMAT_A8R8G8B8; case GL_UNSIGNED_BYTE: return sw::FORMAT_A8R8G8B8;
...@@ -735,6 +736,7 @@ namespace egl ...@@ -735,6 +736,7 @@ namespace egl
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
return sw::FORMAT_A8B8G8R8UI; return sw::FORMAT_A8B8G8R8UI;
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
return sw::FORMAT_A8R8G8B8; return sw::FORMAT_A8R8G8B8;
case GL_ALPHA: case GL_ALPHA:
case GL_ALPHA8_EXT: case GL_ALPHA8_EXT:
...@@ -923,7 +925,8 @@ namespace egl ...@@ -923,7 +925,8 @@ namespace egl
case GL_SRGB8_ALPHA8: case GL_SRGB8_ALPHA8:
case GL_RGBA: return sizeof(unsigned char) * 4; case GL_RGBA: return sizeof(unsigned char) * 4;
case GL_RGBA_INTEGER: 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); default: UNREACHABLE(format);
} }
break; break;
...@@ -1226,6 +1229,7 @@ namespace egl ...@@ -1226,6 +1229,7 @@ namespace egl
case GL_RGBA: case GL_RGBA:
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer); LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break; break;
default: UNREACHABLE(format); default: UNREACHABLE(format);
...@@ -1267,6 +1271,7 @@ namespace egl ...@@ -1267,6 +1271,7 @@ namespace egl
case GL_RGBA: case GL_RGBA:
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer); LoadImageData<Bytes_4>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break; break;
case GL_SRGB8: case GL_SRGB8:
...@@ -1441,6 +1446,7 @@ namespace egl ...@@ -1441,6 +1446,7 @@ namespace egl
case GL_RGBA: case GL_RGBA:
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer); LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break; break;
default: UNREACHABLE(format); default: UNREACHABLE(format);
...@@ -1471,6 +1477,7 @@ namespace egl ...@@ -1471,6 +1477,7 @@ namespace egl
case GL_RGBA: case GL_RGBA:
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer); LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break; break;
case GL_DEPTH_COMPONENT: case GL_DEPTH_COMPONENT:
...@@ -1505,6 +1512,7 @@ namespace egl ...@@ -1505,6 +1512,7 @@ namespace egl
case GL_RGBA: case GL_RGBA:
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer); LoadImageData<Bytes_16>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break; break;
default: UNREACHABLE(format); default: UNREACHABLE(format);
...@@ -1535,6 +1543,7 @@ namespace egl ...@@ -1535,6 +1543,7 @@ namespace egl
case GL_RGBA: case GL_RGBA:
case GL_RGBA_INTEGER: case GL_RGBA_INTEGER:
case GL_BGRA_EXT: case GL_BGRA_EXT:
case GL_BGRA8_EXT:
LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer); LoadImageData<Bytes_8>(xoffset, yoffset, zoffset, width, height, depth, inputPitch, inputHeight, getPitch(), getHeight(), input, buffer);
break; break;
case GL_DEPTH_COMPONENT16: case GL_DEPTH_COMPONENT16:
......
...@@ -339,13 +339,13 @@ GLsizei Texture2D::getHeight(GLenum target, GLint level) const ...@@ -339,13 +339,13 @@ GLsizei Texture2D::getHeight(GLenum target, GLint level) const
GLenum Texture2D::getFormat(GLenum target, GLint level) const GLenum Texture2D::getFormat(GLenum target, GLint level) const
{ {
ASSERT(target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D); 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 GLenum Texture2D::getType(GLenum target, GLint level) const
{ {
ASSERT(target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D); 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 sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
...@@ -716,13 +716,13 @@ GLsizei TextureCubeMap::getHeight(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 GLenum TextureCubeMap::getFormat(GLenum target, GLint level) const
{ {
int face = CubeFaceIndex(target); 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 GLenum TextureCubeMap::getType(GLenum target, GLint level) const
{ {
int face = CubeFaceIndex(target); 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 sw::Format TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
......
...@@ -407,13 +407,13 @@ GLsizei Texture2D::getHeight(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 GLenum Texture2D::getFormat(GLenum target, GLint level) const
{ {
ASSERT(target == GL_TEXTURE_2D); 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 GLenum Texture2D::getType(GLenum target, GLint level) const
{ {
ASSERT(target == GL_TEXTURE_2D); 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 sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
......
...@@ -578,13 +578,13 @@ GLsizei Texture2D::getHeight(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 GLenum Texture2D::getFormat(GLenum target, GLint level) const
{ {
ASSERT(target == GL_TEXTURE_2D); 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 GLenum Texture2D::getType(GLenum target, GLint level) const
{ {
ASSERT(target == GL_TEXTURE_2D); 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 sw::Format Texture2D::getInternalFormat(GLenum target, GLint level) const
...@@ -678,7 +678,8 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL ...@@ -678,7 +678,8 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
image[level]->unbind(this); 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]) if(!image[level])
{ {
...@@ -713,7 +714,8 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei ...@@ -713,7 +714,8 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei
image[level]->unbind(this); 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]) if(!image[level])
{ {
...@@ -733,7 +735,7 @@ void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei ...@@ -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); sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); 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(); renderTarget->release();
...@@ -1079,7 +1081,8 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma ...@@ -1079,7 +1081,8 @@ void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum forma
image[face][level]->unbind(this); 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]) if(!image[face][level])
{ {
...@@ -1247,7 +1250,8 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint ...@@ -1247,7 +1250,8 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
image[face][level]->unbind(this); 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]) if(!image[face][level])
{ {
...@@ -1267,7 +1271,7 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint ...@@ -1267,7 +1271,7 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint
sw::SliceRect sourceRect(x, y, x + width, y + height, 0); sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); 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(); renderTarget->release();
...@@ -1484,13 +1488,13 @@ GLsizei Texture3D::getDepth(GLenum target, GLint level) const ...@@ -1484,13 +1488,13 @@ GLsizei Texture3D::getDepth(GLenum target, GLint level) const
GLenum Texture3D::getFormat(GLenum target, GLint level) const GLenum Texture3D::getFormat(GLenum target, GLint level) const
{ {
ASSERT(target == getTarget()); 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 GLenum Texture3D::getType(GLenum target, GLint level) const
{ {
ASSERT(target == getTarget()); 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 sw::Format Texture3D::getInternalFormat(GLenum target, GLint level) const
...@@ -1580,7 +1584,8 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL ...@@ -1580,7 +1584,8 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL
image[level]->unbind(this); 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]) if(!image[level])
{ {
...@@ -1592,7 +1597,7 @@ void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL ...@@ -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) 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) 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, ...@@ -1615,7 +1620,8 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z,
image[level]->unbind(this); 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]) if(!image[level])
{ {
...@@ -1636,7 +1642,7 @@ void Texture3D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLint z, ...@@ -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()); sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
for(GLint sliceZ = 0; sliceZ < depth; ++sliceZ, ++sourceRect.slice) 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]);
} }
} }
......
...@@ -57,84 +57,12 @@ static bool validImageSize(GLint level, GLsizei width, GLsizei height) ...@@ -57,84 +57,12 @@ static bool validImageSize(GLint level, GLsizei width, GLsizei height)
return true; return true;
} }
static bool validateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, 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)))
{
return error(GL_INVALID_OPERATION, false);
}
}
if(xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, level))
{
return error(GL_INVALID_VALUE, false);
}
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) static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
{ {
GLenum formatError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false); GLenum validationError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError, false); return error(validationError, false);
} }
// [OpenGL ES 2.0.24] table 3.9 // [OpenGL ES 2.0.24] table 3.9
...@@ -970,10 +898,10 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs ...@@ -970,10 +898,10 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
default: default:
{ {
GLenum formatError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true); GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
} }
break; break;
...@@ -1082,10 +1010,10 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -1082,10 +1010,10 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
GLenum formatError = ValidateCompressedFormat(format, egl::getClientVersion(), true); GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
if(width == 0 || height == 0 || data == NULL) if(width == 0 || height == 0 || data == NULL)
...@@ -1113,22 +1041,36 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -1113,22 +1041,36 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, GL_NONE);
if(target == GL_TEXTURE_2D) if(target == GL_TEXTURE_2D)
{ {
es2::Texture2D *texture = context->getTexture2D(); es2::Texture2D *texture = context->getTexture2D();
if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture)) GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
{ {
texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
}
else
{
return error(validationError);
} }
} }
else if(es2::IsCubemapTextureTarget(target)) else if(es2::IsCubemapTextureTarget(target))
{ {
es2::TextureCubeMap *texture = context->getTextureCubeMap(); es2::TextureCubeMap *texture = context->getTextureCubeMap();
if(validateSubImageParams(true, width, height, xoffset, yoffset, target, level, format, texture)) GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
{ {
texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
}
else
{
return error(validationError);
} }
} }
else UNREACHABLE(target); else UNREACHABLE(target);
...@@ -1293,9 +1235,10 @@ void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, ...@@ -1293,9 +1235,10 @@ void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
} }
else UNREACHABLE(target); else UNREACHABLE(target);
if(!validateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture)) GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture);
if(validationError != GL_NONE)
{ {
return; return error(validationError);
} }
texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
...@@ -5184,10 +5127,10 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5184,10 +5127,10 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
} }
} }
GLenum formatError = ValidateCompressedFormat(format, clientVersion, false); GLenum validationError = ValidateCompressedFormat(format, clientVersion, false);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
switch(format) switch(format)
...@@ -5904,6 +5847,8 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5904,6 +5847,8 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(GL_INVALID_ENUM); return error(GL_INVALID_ENUM);
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
if(target == GL_TEXTURE_2D) if(target == GL_TEXTURE_2D)
{ {
es2::Texture2D *texture = context->getTexture2D(); es2::Texture2D *texture = context->getTexture2D();
...@@ -5913,7 +5858,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5913,7 +5858,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->setImage(level, width, height, format, type, context->getUnpackInfo(), pixels); texture->setImage(level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), pixels);
} }
else else
{ {
...@@ -5924,7 +5869,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, ...@@ -5924,7 +5869,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
texture->setImage(target, level, width, height, format, type, context->getUnpackInfo(), pixels); texture->setImage(target, level, width, height, sizedInternalFormat, type, context->getUnpackInfo(), pixels);
} }
} }
} }
...@@ -6281,22 +6226,36 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs ...@@ -6281,22 +6226,36 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
if(target == GL_TEXTURE_2D) if(target == GL_TEXTURE_2D)
{ {
es2::Texture2D *texture = context->getTexture2D(); es2::Texture2D *texture = context->getTexture2D();
if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture)) GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
{ {
texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), pixels); texture->subImage(level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), pixels);
}
else
{
return error(validationError);
} }
} }
else if(es2::IsCubemapTextureTarget(target)) else if(es2::IsCubemapTextureTarget(target))
{ {
es2::TextureCubeMap *texture = context->getTextureCubeMap(); es2::TextureCubeMap *texture = context->getTextureCubeMap();
if(validateSubImageParams(false, width, height, xoffset, yoffset, target, level, format, texture)) GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
{ {
texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackInfo(), pixels); texture->subImage(target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), pixels);
}
else
{
return error(validationError);
} }
} }
else UNREACHABLE(target); else UNREACHABLE(target);
...@@ -7112,7 +7071,7 @@ void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei wi ...@@ -7112,7 +7071,7 @@ void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei wi
return error(GL_INVALID_OPERATION); 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);
} }
} }
...@@ -7152,9 +7111,16 @@ void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset, ...@@ -7152,9 +7111,16 @@ void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset,
{ {
es2::Texture3D *texture = context->getTexture3D(); es2::Texture3D *texture = context->getTexture3D();
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);
} }
} }
} }
...@@ -7198,9 +7164,11 @@ void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffs ...@@ -7198,9 +7164,11 @@ void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffs
es2::Texture3D *texture = context->getTexture3D(); es2::Texture3D *texture = context->getTexture3D();
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);
} }
texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
...@@ -7242,10 +7210,10 @@ void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat, ...@@ -7242,10 +7210,10 @@ void CompressedTexImage3DOES(GLenum target, GLint level, GLenum internalformat,
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
default: default:
{ {
GLenum formatError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true); GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
} }
} }
...@@ -7290,10 +7258,10 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint ...@@ -7290,10 +7258,10 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
GLenum formatError = ValidateCompressedFormat(format, egl::getClientVersion(), true); GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
if(width == 0 || height == 0 || depth == 0 || data == NULL) if(width == 0 || height == 0 || depth == 0 || data == NULL)
......
...@@ -46,49 +46,13 @@ static bool validImageSize(GLint level, GLsizei width, GLsizei height) ...@@ -46,49 +46,13 @@ static bool validImageSize(GLint level, GLsizei width, GLsizei height)
return true; 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) static bool validateColorBufferFormat(GLenum textureFormat, GLenum colorbufferFormat)
{ {
GLenum formatError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false); GLenum validationError = ValidateCompressedFormat(textureFormat, egl::getClientVersion(), false);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError, false); return error(validationError, false);
} }
switch(textureFormat) switch(textureFormat)
...@@ -706,7 +670,7 @@ GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint inter ...@@ -706,7 +670,7 @@ GL_APICALL void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint inter
return error(GL_INVALID_OPERATION); 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 ...@@ -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(); 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 ...@@ -800,9 +771,10 @@ GL_APICALL void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLin
GLenum colorbufferFormat = source->getFormat(); GLenum colorbufferFormat = source->getFormat();
es2::Texture3D *texture = (target == GL_TEXTURE_3D) ? context->getTexture3D() : context->getTexture2DArray(); 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); GLenum textureFormat = texture->getFormat(target, level);
...@@ -852,10 +824,10 @@ GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, G ...@@ -852,10 +824,10 @@ GL_APICALL void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, G
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
default: default:
{ {
GLenum formatError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true); GLenum validationError = ValidateCompressedFormat(internalformat, egl::getClientVersion(), true);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
} }
} }
...@@ -901,10 +873,10 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level ...@@ -901,10 +873,10 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
GLenum formatError = ValidateCompressedFormat(format, egl::getClientVersion(), true); GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
if(formatError != GL_NONE) if(validationError != GL_NONE)
{ {
return error(formatError); return error(validationError);
} }
if(width == 0 || height == 0 || depth == 0 || data == NULL) if(width == 0 || height == 0 || depth == 0 || data == NULL)
...@@ -3875,7 +3847,7 @@ GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum ...@@ -3875,7 +3847,7 @@ GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum
for(int level = 0; level < levels; ++level) 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)); width = std::max(1, (width / 2));
height = std::max(1, (height / 2)); height = std::max(1, (height / 2));
} }
...@@ -3894,7 +3866,7 @@ GL_APICALL void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum ...@@ -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) 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)); width = std::max(1, (width / 2));
height = std::max(1, (height / 2)); height = std::max(1, (height / 2));
...@@ -3945,7 +3917,7 @@ GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum ...@@ -3945,7 +3917,7 @@ GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum
for(int level = 0; level < levels; ++level) 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)); width = std::max(1, (width / 2));
height = std::max(1, (height / 2)); height = std::max(1, (height / 2));
depth = std::max(1, (depth / 2)); depth = std::max(1, (depth / 2));
...@@ -3970,7 +3942,7 @@ GL_APICALL void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum ...@@ -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) 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)); width = std::max(1, (width / 2));
height = std::max(1, (height / 2)); height = std::max(1, (height / 2));
......
...@@ -23,6 +23,154 @@ ...@@ -23,6 +23,154 @@
namespace es2 namespace es2
{ {
// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation
// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid
// format and type combinations.
typedef std::pair<GLenum, GLenum> FormatTypePair;
typedef std::pair<FormatTypePair, GLenum> FormatPair;
typedef std::map<FormatTypePair, GLenum> FormatMap;
// A helper function to insert data into the format map with fewer characters.
static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat)
{
map->insert(FormatPair(FormatTypePair(format, type), internalFormat));
}
FormatMap BuildFormatMap()
{
static const GLenum GL_BGRA4_ANGLEX = 0x6ABC;
static const GLenum GL_BGR5_A1_ANGLEX = 0x6ABD;
FormatMap map;
// | Format | Type | Internal format |
InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8);
InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM);
InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4);
InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1);
InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2);
InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F);
InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F);
InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I);
InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI);
InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8);
InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM);
InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565);
InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F);
InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5);
InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F);
InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F);
InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F);
InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI);
InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I);
InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI);
InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I);
InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI);
InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I);
InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8);
InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM);
InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F);
InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F);
InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F);
InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI);
InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I);
InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI);
InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I);
InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI);
InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I);
InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8);
InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM);
InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F);
InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F);
InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F);
InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI);
InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I);
InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI);
InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I);
InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI);
InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I);
InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT);
InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT);
InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT);
InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT);
InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT);
InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT);
InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT);
InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT);
InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT);
InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT);
InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT);
InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT);
InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT);
InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX);
InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX);
InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8);
InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8);
InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16);
InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES);
InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F);
InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8);
InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8);
InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8);
return map;
}
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
{
switch(internalFormat)
{
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_RED:
case GL_RG:
case GL_RGB:
case GL_RGBA:
case GL_RED_INTEGER:
case GL_RG_INTEGER:
case GL_RGB_INTEGER:
case GL_RGBA_INTEGER:
case GL_BGRA_EXT:
case GL_DEPTH_COMPONENT:
case GL_DEPTH_STENCIL:
case GL_SRGB_EXT:
case GL_SRGB_ALPHA_EXT:
{
static const FormatMap formatMap = BuildFormatMap();
FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type));
return (iter != formatMap.end()) ? iter->second : GL_NONE;
}
default:
return internalFormat;
}
}
unsigned int UniformComponentCount(GLenum type) unsigned int UniformComponentCount(GLenum type)
{ {
switch(type) switch(type)
...@@ -377,6 +525,78 @@ namespace es2 ...@@ -377,6 +525,78 @@ namespace es2
} }
} }
GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)
{
if(!texture)
{
return GL_INVALID_OPERATION;
}
if(compressed != texture->isCompressed(target, level))
{
return GL_INVALID_OPERATION;
}
if(sizedInternalFormat != GL_NONE && sizedInternalFormat != texture->getFormat(target, level))
{
return GL_INVALID_OPERATION;
}
if(compressed)
{
if((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
(height % 4 != 0 && height != texture->getHeight(target, 0)))
{
return GL_INVALID_OPERATION;
}
}
if(xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, level))
{
return GL_INVALID_VALUE;
}
return GL_NONE;
}
GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)
{
if(!texture)
{
return GL_INVALID_OPERATION;
}
if(compressed != texture->isCompressed(target, level))
{
return GL_INVALID_OPERATION;
}
if(sizedInternalFormat != GL_NONE && sizedInternalFormat != GetSizedInternalFormat(texture->getFormat(target, level), texture->getType(target, level)))
{
return GL_INVALID_OPERATION;
}
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 GL_INVALID_OPERATION;
}
}
if(xoffset + width > texture->getWidth(target, level) ||
yoffset + height > texture->getHeight(target, level) ||
zoffset + depth > texture->getDepth(target, level))
{
return GL_INVALID_VALUE;
}
return GL_NONE;
}
bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, egl::GLint clientVersion) bool ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, egl::GLint clientVersion)
{ {
switch(format) switch(format)
...@@ -452,7 +672,9 @@ namespace es2 ...@@ -452,7 +672,9 @@ namespace es2
bool IsStencilTexture(GLenum format) bool IsStencilTexture(GLenum format)
{ {
return format == GL_STENCIL_INDEX_OES || return format == GL_STENCIL_INDEX_OES ||
format == GL_DEPTH_STENCIL_OES; format == GL_DEPTH_STENCIL_OES ||
format == GL_DEPTH24_STENCIL8 ||
format == GL_DEPTH32F_STENCIL8;
} }
bool IsCubemapTextureTarget(GLenum target) bool IsCubemapTextureTarget(GLenum target)
......
...@@ -41,7 +41,10 @@ namespace es2 ...@@ -41,7 +41,10 @@ namespace es2
GLint floatToInt(GLfloat value); GLint floatToInt(GLfloat value);
bool IsCompressed(GLenum format, egl::GLint clientVersion); bool IsCompressed(GLenum format, egl::GLint clientVersion);
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
GLenum ValidateCompressedFormat(GLenum format, egl::GLint clientVersion, bool expectCompressedFormats); 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 ValidReadPixelsFormatType(GLenum internalFormat, GLenum internalType, GLenum format, GLenum type, egl::GLint clientVersion);
bool IsDepthTexture(GLenum format); bool IsDepthTexture(GLenum format);
bool IsStencilTexture(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