Commit d2faaa99 by Nicolas Capens Committed by Nicolas Capens

Fix internalformat handling.

- Use internalformat parameter if valid, instead of deriving from format/type parameters. - Validate format/type/internalformat parameters in CopyTexSubImage(). - Moved early-out optimizations after validation. - Removed duplicate validation. - Use GLint consistently for internalformat parameters. Change-Id: I377c6bb5381602d13d281f19985aa4f11d201099 Reviewed-on: https://swiftshader-review.googlesource.com/14488Tested-by: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com>
parent 05bcbe6b
......@@ -328,7 +328,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
if(IsRenderbuffer(mColorbufferType[i]))
{
if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion(), false))
if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
......@@ -337,7 +337,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
{
GLenum format = colorbuffer->getFormat();
if(!IsColorRenderable(format, egl::getClientVersion(), true))
if(!IsColorRenderable(format, egl::getClientVersion()))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
......
......@@ -431,22 +431,7 @@ void Texture::subImage(egl::Context *context, GLint xoffset, GLint yoffset, GLin
return error(GL_INVALID_OPERATION);
}
if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight() || depth + zoffset > image->getDepth())
{
return error(GL_INVALID_VALUE);
}
if(IsCompressed(image->getFormat(), egl::getClientVersion()))
{
return error(GL_INVALID_OPERATION);
}
if(format != image->getFormat())
{
return error(GL_INVALID_OPERATION);
}
if(pixels)
if(pixels && width > 0 && height > 0 && depth > 0)
{
image->loadImageData(context, xoffset, yoffset, zoffset, width, height, depth, format, type, unpackInfo, pixels);
}
......@@ -459,16 +444,6 @@ void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GL
return error(GL_INVALID_OPERATION);
}
if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight() || depth + zoffset > image->getDepth())
{
return error(GL_INVALID_VALUE);
}
if(format != image->getFormat())
{
return error(GL_INVALID_OPERATION);
}
if(pixels && (imageSize > 0)) // imageSize's correlation to width and height is already validated with egl::ComputeCompressedSize() at the API level
{
image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, imageSize, pixels);
......@@ -773,28 +748,31 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_VALUE);
}
egl::Image *renderTarget = source->getRenderTarget(0);
if(!renderTarget)
if(width > 0 && height > 0)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
egl::Image *renderTarget = source->getRenderTarget(0);
Renderbuffer* renderbuffer = source->getReadColorbuffer();
if(!renderTarget)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
if(!renderbuffer)
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
Renderbuffer* renderbuffer = source->getReadColorbuffer();
sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
if(!renderbuffer)
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
renderTarget->release();
copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
renderTarget->release();
}
}
void Texture2D::setSharedImage(egl::Image *sharedImage)
......@@ -1415,28 +1393,31 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi
return error(GL_INVALID_VALUE);
}
egl::Image *renderTarget = source->getRenderTarget(0);
if(!renderTarget)
if(width > 0 && height > 0)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
egl::Image *renderTarget = source->getRenderTarget(0);
Renderbuffer* renderbuffer = source->getReadColorbuffer();
if(!renderTarget)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
if(!renderbuffer)
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
Renderbuffer* renderbuffer = source->getReadColorbuffer();
sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
if(!renderbuffer)
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, zoffset, image[face][level]);
sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
renderTarget->release();
copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, zoffset, image[face][level]);
renderTarget->release();
}
}
void TextureCubeMap::generateMipmaps()
......@@ -1758,28 +1739,31 @@ void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_VALUE);
}
egl::Image *renderTarget = source->getRenderTarget(0);
if(!renderTarget)
if(width > 0 && height > 0)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
egl::Image *renderTarget = source->getRenderTarget(0);
Renderbuffer* renderbuffer = source->getReadColorbuffer();
if(!renderTarget)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
if(!renderbuffer)
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
Renderbuffer* renderbuffer = source->getReadColorbuffer();
sw::SliceRect sourceRect = {x, y, x + width, y + height, 0};
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
if(!renderbuffer)
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
sw::SliceRect sourceRect = {x, y, x + width, y + height, 0};
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
renderTarget->release();
copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
renderTarget->release();
}
}
void Texture3D::setSharedImage(egl::Image *sharedImage)
......
......@@ -902,7 +902,6 @@ void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLs
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
{
GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
if(validationError != GL_NONE)
{
......@@ -941,12 +940,6 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_VALUE);
}
GLenum validationError = ValidateCompressedFormat(format, egl::getClientVersion(), true);
if(validationError != GL_NONE)
{
return error(validationError);
}
if(imageSize != egl::ComputeCompressedSize(width, height, format))
{
return error(GL_INVALID_VALUE);
......@@ -956,11 +949,6 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
if(context)
{
if(imageSize != egl::ComputeCompressedSize(width, height, format))
{
return error(GL_INVALID_VALUE);
}
if(xoffset % 4 != 0 || yoffset % 4 != 0)
{
// We wait to check the offsets until this point, because the multiple-of-four restriction does not exist unless DXT1 textures are supported
......@@ -973,41 +961,37 @@ void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yo
{
es2::Texture2D *texture = context->getTexture2D();
GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
return error(validationError);
}
if(validationError == GL_NONE)
{
texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
}
else
validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
}
else if(es2::IsCubemapTextureTarget(target))
{
es2::TextureCubeMap *texture = context->getTextureCubeMap();
GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
return error(validationError);
}
if(validationError == GL_NONE)
{
texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
}
else
validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
}
else UNREACHABLE(target);
}
......@@ -1136,11 +1120,6 @@ void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
return error(GL_INVALID_VALUE);
}
if(width == 0 || height == 0)
{
return;
}
es2::Context *context = es2::getContext();
if(context)
......@@ -1171,7 +1150,7 @@ void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
}
else UNREACHABLE(target);
GLenum validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, GL_NONE, texture);
GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, width, height, GL_NONE, GL_NONE, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
return error(validationError);
......@@ -4759,7 +4738,7 @@ void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum inter
GLint clientVersion = context->getClientVersion();
if(IsColorRenderable(internalformat, clientVersion, false))
if(IsColorRenderable(internalformat, clientVersion))
{
context->setRenderbufferStorage(new es2::Colorbuffer(width, height, internalformat, samples));
}
......@@ -5102,9 +5081,10 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(validationError);
}
if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
validationError = ValidateTextureFormatType(format, type, internalformat, context->getClientVersion());
if(validationError != GL_NONE)
{
return;
return error(validationError);
}
if(border != 0)
......@@ -5142,7 +5122,7 @@ void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width,
return error(GL_INVALID_ENUM);
}
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum sizedInternalFormat = GetSizedInternalFormat(internalformat, type);
validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
if(validationError != GL_NONE)
......@@ -5501,57 +5481,47 @@ void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLs
return error(GL_INVALID_VALUE);
}
if(!ValidateTextureFormatType(format, type, format, egl::getClientVersion()))
{
return;
}
if(width == 0 || height == 0)
{
return;
}
es2::Context *context = es2::getContext();
if(context)
{
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
if(target == GL_TEXTURE_2D)
{
es2::Texture2D *texture = context->getTexture2D();
validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
return error(validationError);
}
else
validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
}
else if(es2::IsCubemapTextureTarget(target))
{
es2::TextureCubeMap *texture = context->getTextureCubeMap();
validationError = ValidateSubImageParams(false, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
return error(validationError);
}
else
validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, 1, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
}
else UNREACHABLE(target);
}
......@@ -6349,9 +6319,15 @@ void TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei wi
return error(GL_INVALID_ENUM);
}
if(!ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion()))
if(internalformat != (GLint)format)
{
return;
return error(GL_INVALID_OPERATION);
}
GLenum validationError = ValidateTextureFormatType(format, type, internalformat, egl::getClientVersion());
if(validationError != GL_NONE)
{
return error(validationError);
}
if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))
......@@ -6430,21 +6406,19 @@ void TexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
return error(validationError);
}
if(validationError == GL_NONE)
{
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
}
else
validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
}
}
......@@ -6487,8 +6461,7 @@ void CopyTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint yoffs
es2::Texture3D *texture = context->getTexture3D();
GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
return error(validationError);
......@@ -6616,7 +6589,6 @@ void CompressedTexSubImage3DOES(GLenum target, GLint level, GLint xoffset, GLint
}
GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
if(validationError != GL_NONE)
{
return error(validationError);
......
......@@ -729,21 +729,19 @@ GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xo
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
if(validationError == GL_NONE)
GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
return error(validationError);
}
else
validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
if(validationError != GL_NONE)
{
return error(validationError);
}
texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
}
}
......@@ -793,7 +791,7 @@ 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();
GLenum validationError = ValidateSubImageParams(false, width, height, 1, xoffset, yoffset, zoffset, target, level, GL_NONE, texture);
GLenum validationError = ValidateSubImageParams(false, true, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_NONE, GL_NONE, texture, context->getClientVersion());
if(validationError != GL_NONE)
{
return error(validationError);
......@@ -935,7 +933,7 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
return error(GL_INVALID_OPERATION);
}
if(((width % 4) != 0) || ((height % 4) != 0) ||
if(((width % 4) != 0) || ((height % 4) != 0) ||
((xoffset % 4) != 0) || ((yoffset % 4) != 0))
{
return error(GL_INVALID_OPERATION);
......@@ -967,7 +965,8 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
if(is_ETC2_EAC)
{
if(((width + xoffset) != texture->getWidth(target, level)) ||
((height + yoffset) != texture->getHeight(target, level)))
((height + yoffset) != texture->getHeight(target, level)) ||
((depth + zoffset) != texture->getDepth(target, level)))
{
return error(GL_INVALID_OPERATION);
}
......@@ -4085,7 +4084,7 @@ GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internal
return;
}
if(!IsColorRenderable(internalformat, egl::getClientVersion(), false) &&
if(!IsColorRenderable(internalformat, egl::getClientVersion()) &&
!IsDepthRenderable(internalformat, egl::getClientVersion()) &&
!IsStencilRenderable(internalformat, egl::getClientVersion()))
{
......
......@@ -520,31 +520,40 @@ namespace es2
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
#if(ASTC_SUPPORT)
return ((clientVersion >= 3) && ()) ? (expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION) : GL_INVALID_ENUM;
#else
return GL_INVALID_ENUM;
#endif
#if(ASTC_SUPPORT)
return ((clientVersion >= 3) && ()) ? (expectCompressedFormats ? GL_NONE : GL_INVALID_OPERATION) : GL_INVALID_ENUM;
#else
return GL_INVALID_ENUM;
#endif
default:
return expectCompressedFormats ? GL_INVALID_ENUM : GL_NONE; // Not compressed format
}
}
GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture)
GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLenum type, Texture *texture, GLint clientVersion)
{
if(!texture)
{
return GL_INVALID_OPERATION;
}
if(compressed != texture->isCompressed(target, level))
GLenum sizedInternalFormat = texture->getFormat(target, level);
if(compressed)
{
return GL_INVALID_OPERATION;
if(format != sizedInternalFormat)
{
return GL_INVALID_OPERATION;
}
}
if(sizedInternalFormat != GL_NONE && sizedInternalFormat != texture->getFormat(target, level))
else if(!copy) // CopyTexSubImage doesn't have format/type parameters.
{
return GL_INVALID_OPERATION;
GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, clientVersion);
if(validationError != GL_NONE)
{
return validationError;
}
}
if(compressed)
......@@ -565,7 +574,8 @@ namespace es2
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)
GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, Texture *texture, GLint clientVersion)
{
if(!texture)
{
......@@ -577,9 +587,15 @@ namespace es2
return GL_INVALID_OPERATION;
}
if(sizedInternalFormat != GL_NONE && sizedInternalFormat != GetSizedInternalFormat(texture->getFormat(target, level), texture->getType(target, level)))
if(!copy)
{
return GL_INVALID_OPERATION;
GLenum sizedInternalFormat = texture->getFormat(target, level);
GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, clientVersion);
if(validationError != GL_NONE)
{
return validationError;
}
}
if(compressed)
......@@ -761,7 +777,7 @@ namespace es2
return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target) || target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
}
bool ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion)
GLenum ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion)
{
switch(type)
{
......@@ -785,11 +801,11 @@ namespace es2
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
if(clientVersion < 3)
{
return error(GL_INVALID_ENUM, false);
return GL_INVALID_ENUM;
}
break;
default:
return error(GL_INVALID_ENUM, false);
return GL_INVALID_ENUM;
}
switch(format)
......@@ -811,22 +827,42 @@ namespace es2
case GL_RGBA_INTEGER:
if(clientVersion < 3)
{
return error(GL_INVALID_ENUM, false);
return GL_INVALID_ENUM;
}
break;
default:
return error(GL_INVALID_ENUM, false);
return GL_INVALID_ENUM;
}
if((GLenum)internalformat != format)
{
if(clientVersion < 3)
{
return error(GL_INVALID_OPERATION, false);
}
switch(internalformat)
{
// Unsized internal formats:
case GL_ALPHA:
case GL_RGB:
case GL_RGBA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_BGRA_EXT: // GL_EXT_texture_format_BGRA8888
case GL_DEPTH_STENCIL: // GL_OES_packed_depth_stencil (GL_DEPTH_STENCIL_OES)
case GL_DEPTH_COMPONENT: // GL_OES_depth_texture
case GL_RED: // = GL_RED_EXT in GL_EXT_texture_rg
case GL_RG: // = GL_RG_EXT in GL_EXT_texture_rg
break;
case GL_RED_INTEGER:
case GL_RG_INTEGER:
case GL_RGB_INTEGER:
case GL_RGBA_INTEGER:
if(clientVersion < 3)
{
return GL_INVALID_ENUM;
}
break;
// Sized internal formats:
case GL_ALPHA8_EXT:
case GL_LUMINANCE8_ALPHA8_EXT:
case GL_LUMINANCE8_EXT:
case GL_R8:
case GL_R8UI:
case GL_R8I:
......@@ -885,7 +921,7 @@ namespace es2
case GL_RGB9_E5:
break;
default:
return error(GL_INVALID_ENUM, false);
return GL_INVALID_ENUM;
}
}
......@@ -906,7 +942,7 @@ namespace es2
case GL_UNSIGNED_INT_2_10_10_10_REV: VALIDATE_INTERNALFORMAT(GL_RGB10_A2, GL_RGB5_A1)
case GL_HALF_FLOAT: VALIDATE_INTERNALFORMAT(GL_RGBA16F)
case GL_FLOAT: VALIDATE_INTERNALFORMAT(GL_RGBA32F, GL_RGBA16F)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RGBA_INTEGER:
......@@ -919,7 +955,7 @@ namespace es2
case GL_UNSIGNED_INT: VALIDATE_INTERNALFORMAT(GL_RGBA32UI)
case GL_INT: VALIDATE_INTERNALFORMAT(GL_RGBA32I)
case GL_UNSIGNED_INT_2_10_10_10_REV: VALIDATE_INTERNALFORMAT(GL_RGB10_A2UI)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RGB:
......@@ -933,7 +969,7 @@ namespace es2
case GL_UNSIGNED_INT_5_9_9_9_REV: VALIDATE_INTERNALFORMAT(GL_RGB9_E5)
case GL_HALF_FLOAT: VALIDATE_INTERNALFORMAT(GL_RGB16F, GL_R11F_G11F_B10F, GL_RGB9_E5)
case GL_FLOAT: VALIDATE_INTERNALFORMAT(GL_RGB32F, GL_RGB16F, GL_R11F_G11F_B10F, GL_RGB9_E5)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RGB_INTEGER:
......@@ -945,7 +981,7 @@ namespace es2
case GL_SHORT: VALIDATE_INTERNALFORMAT(GL_RGB16I)
case GL_UNSIGNED_INT: VALIDATE_INTERNALFORMAT(GL_RGB32UI)
case GL_INT: VALIDATE_INTERNALFORMAT(GL_RGB32I)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RG:
......@@ -956,7 +992,7 @@ namespace es2
case GL_HALF_FLOAT_OES: break;
case GL_HALF_FLOAT: VALIDATE_INTERNALFORMAT(GL_RG16F)
case GL_FLOAT: VALIDATE_INTERNALFORMAT(GL_RG32F, GL_RG16F)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RG_INTEGER:
......@@ -968,7 +1004,7 @@ namespace es2
case GL_SHORT: VALIDATE_INTERNALFORMAT(GL_RG16I)
case GL_UNSIGNED_INT: VALIDATE_INTERNALFORMAT(GL_RG32UI)
case GL_INT: VALIDATE_INTERNALFORMAT(GL_RG32I)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RED:
......@@ -979,7 +1015,7 @@ namespace es2
case GL_HALF_FLOAT_OES: break;
case GL_HALF_FLOAT: VALIDATE_INTERNALFORMAT(GL_R16F)
case GL_FLOAT: VALIDATE_INTERNALFORMAT(GL_R32F, GL_R16F)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_RED_INTEGER:
......@@ -991,7 +1027,7 @@ namespace es2
case GL_SHORT: VALIDATE_INTERNALFORMAT(GL_R16I)
case GL_UNSIGNED_INT: VALIDATE_INTERNALFORMAT(GL_R32UI)
case GL_INT: VALIDATE_INTERNALFORMAT(GL_R32I)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_DEPTH_COMPONENT:
......@@ -1000,7 +1036,7 @@ namespace es2
case GL_UNSIGNED_SHORT: VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT16)
case GL_UNSIGNED_INT: VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT16)
case GL_FLOAT: VALIDATE_INTERNALFORMAT(GL_DEPTH_COMPONENT32F)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_DEPTH_STENCIL:
......@@ -1008,41 +1044,61 @@ namespace es2
{
case GL_UNSIGNED_INT_24_8: VALIDATE_INTERNALFORMAT(GL_DEPTH24_STENCIL8)
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV: VALIDATE_INTERNALFORMAT(GL_DEPTH32F_STENCIL8)
default: return error(GL_INVALID_OPERATION, false);
default: return GL_INVALID_OPERATION;
}
break;
case GL_LUMINANCE_ALPHA:
switch(type)
{
case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_ALPHA8_EXT)
case GL_HALF_FLOAT_OES:
case GL_FLOAT:
break;
default:
return GL_INVALID_OPERATION;
}
break;
case GL_LUMINANCE:
switch(type)
{
case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_EXT)
case GL_HALF_FLOAT_OES:
case GL_FLOAT:
break;
default:
return GL_INVALID_OPERATION;
}
break;
case GL_ALPHA:
switch(type)
{
case GL_UNSIGNED_BYTE:
case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_ALPHA8_EXT)
case GL_HALF_FLOAT_OES:
case GL_FLOAT:
break;
default:
return error(GL_INVALID_OPERATION, false);
return GL_INVALID_OPERATION;
}
break;
case GL_BGRA_EXT:
if(type != GL_UNSIGNED_BYTE)
{
return error(GL_INVALID_OPERATION, false);
return GL_INVALID_OPERATION;
}
break;
default:
UNREACHABLE(format);
return error(GL_INVALID_ENUM, false);
return GL_INVALID_ENUM;
}
#undef VALIDATE_INTERNALFORMAT
if((GLenum)internalformat != format && !validSizedInternalformat)
{
return error(GL_INVALID_OPERATION, false);
return GL_INVALID_OPERATION;
}
return true;
return GL_NONE;
}
GLsizei GetTypeSize(GLenum type)
......@@ -1077,22 +1133,17 @@ namespace es2
return 1;
}
bool IsColorRenderable(GLenum internalformat, GLint clientVersion, bool isTexture)
bool IsColorRenderable(GLint internalformat, GLint clientVersion)
{
switch(internalformat)
{
case GL_RED_EXT:
case GL_RG_EXT:
case GL_RGB:
case GL_RGBA:
return isTexture;
case GL_RGBA4:
case GL_RGB5_A1:
case GL_RGB565:
case GL_R8_EXT:
case GL_RG8_EXT:
case GL_RGB8_OES:
case GL_RGBA8_OES:
case GL_R8:
case GL_RG8:
case GL_RGB8:
case GL_RGBA8:
case GL_R16F:
case GL_RG16F:
case GL_RGB16F:
......@@ -1148,25 +1199,7 @@ namespace es2
return false;
}
bool IsMipmappable(GLenum internalformat, sw::Format internalFormat, GLint clientVersion)
{
if(sw::Surface::isNonNormalizedInteger(internalFormat))
{
return false;
}
switch(internalformat)
{
case GL_ALPHA8_EXT:
case GL_LUMINANCE8_EXT:
case GL_LUMINANCE8_ALPHA8_EXT:
return true;
default:
return IsColorRenderable(internalformat, clientVersion, true);
}
}
bool IsDepthRenderable(GLenum internalformat, GLint clientVersion)
bool IsDepthRenderable(GLint internalformat, GLint clientVersion)
{
switch(internalformat)
{
......@@ -1220,6 +1253,10 @@ namespace es2
case GL_RG32F:
case GL_RGB32F:
case GL_RGBA32F:
case GL_R8_SNORM:
case GL_RG8_SNORM:
case GL_RGB8_SNORM:
case GL_RGBA8_SNORM:
return false;
default:
UNIMPLEMENTED();
......@@ -1228,7 +1265,7 @@ namespace es2
return false;
}
bool IsStencilRenderable(GLenum internalformat, GLint clientVersion)
bool IsStencilRenderable(GLint internalformat, GLint clientVersion)
{
switch(internalformat)
{
......@@ -1282,6 +1319,10 @@ namespace es2
case GL_DEPTH_COMPONENT24:
case GL_DEPTH_COMPONENT32_OES:
case GL_DEPTH_COMPONENT32F:
case GL_R8_SNORM:
case GL_RG8_SNORM:
case GL_RGB8_SNORM:
case GL_RGBA8_SNORM:
return false;
default:
UNIMPLEMENTED();
......@@ -1290,6 +1331,24 @@ namespace es2
return false;
}
bool IsMipmappable(GLint internalformat, sw::Format format, GLint clientVersion)
{
if(sw::Surface::isNonNormalizedInteger(format))
{
return false;
}
switch(internalformat)
{
case GL_ALPHA8_EXT:
case GL_LUMINANCE8_EXT:
case GL_LUMINANCE8_ALPHA8_EXT:
return true;
default:
return IsColorRenderable(internalformat, clientVersion);
}
}
std::string ParseUniformName(const std::string &name, unsigned int *outSubscript)
{
// Strip any trailing array operator and retrieve the subscript
......
......@@ -45,21 +45,23 @@ namespace es2
bool IsCompressed(GLenum format, GLint clientVersion);
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
GLenum ValidateCompressedFormat(GLenum format, 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);
GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLenum type, Texture *texture, GLint clientVersion);
GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, Texture *texture, GLint clientVersion);
bool IsValidReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type, GLint clientVersion);
bool IsDepthTexture(GLenum format);
bool IsStencilTexture(GLenum format);
bool IsCubemapTextureTarget(GLenum target);
int CubeFaceIndex(GLenum cubeTarget);
bool IsTextureTarget(GLenum target);
bool ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion);
GLenum ValidateTextureFormatType(GLenum format, GLenum type, GLint internalformat, GLint clientVersion);
GLsizei GetTypeSize(GLenum type);
bool IsColorRenderable(GLenum internalformat, GLint clientVersion, bool isTexture);
bool IsMipmappable(GLenum format, sw::Format internalFormat, GLint clientVersion);
bool IsDepthRenderable(GLenum internalformat, GLint clientVersion);
bool IsStencilRenderable(GLenum internalformat, GLint clientVersion);
bool IsColorRenderable(GLint internalformat, GLint clientVersion);
bool IsDepthRenderable(GLint internalformat, GLint clientVersion);
bool IsStencilRenderable(GLint internalformat, GLint clientVersion);
bool IsMipmappable(GLint internalformat, sw::Format format, GLint clientVersion);
// Parse the base uniform name and array index. Returns the base name of the uniform. outSubscript is
// set to GL_INVALID_INDEX if the provided name is not an array or the array index is invalid.
......
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