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) ...@@ -328,7 +328,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
if(IsRenderbuffer(mColorbufferType[i])) if(IsRenderbuffer(mColorbufferType[i]))
{ {
if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion(), false)) if(!IsColorRenderable(colorbuffer->getFormat(), egl::getClientVersion()))
{ {
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
} }
...@@ -337,7 +337,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples) ...@@ -337,7 +337,7 @@ GLenum Framebuffer::completeness(int &width, int &height, int &samples)
{ {
GLenum format = colorbuffer->getFormat(); GLenum format = colorbuffer->getFormat();
if(!IsColorRenderable(format, egl::getClientVersion(), true)) if(!IsColorRenderable(format, egl::getClientVersion()))
{ {
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
} }
......
...@@ -431,22 +431,7 @@ void Texture::subImage(egl::Context *context, GLint xoffset, GLint yoffset, GLin ...@@ -431,22 +431,7 @@ void Texture::subImage(egl::Context *context, GLint xoffset, GLint yoffset, GLin
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
} }
if(width + xoffset > image->getWidth() || height + yoffset > image->getHeight() || depth + zoffset > image->getDepth()) if(pixels && width > 0 && height > 0 && depth > 0)
{
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)
{ {
image->loadImageData(context, xoffset, yoffset, zoffset, width, height, depth, format, type, unpackInfo, pixels); 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 ...@@ -459,16 +444,6 @@ void Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GL
return error(GL_INVALID_OPERATION); 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 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); 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 ...@@ -773,28 +748,31 @@ void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
egl::Image *renderTarget = source->getRenderTarget(0); if(width > 0 && height > 0)
if(!renderTarget)
{ {
ERR("Failed to retrieve the render target."); egl::Image *renderTarget = source->getRenderTarget(0);
return error(GL_OUT_OF_MEMORY);
}
Renderbuffer* renderbuffer = source->getReadColorbuffer(); if(!renderTarget)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
if(!renderbuffer) Renderbuffer* renderbuffer = source->getReadColorbuffer();
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
sw::SliceRect sourceRect(x, y, x + width, y + height, 0); if(!renderbuffer)
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); {
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) void Texture2D::setSharedImage(egl::Image *sharedImage)
...@@ -1415,28 +1393,31 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi ...@@ -1415,28 +1393,31 @@ void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLi
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
egl::Image *renderTarget = source->getRenderTarget(0); if(width > 0 && height > 0)
if(!renderTarget)
{ {
ERR("Failed to retrieve the render target."); egl::Image *renderTarget = source->getRenderTarget(0);
return error(GL_OUT_OF_MEMORY);
}
Renderbuffer* renderbuffer = source->getReadColorbuffer(); if(!renderTarget)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
if(!renderbuffer) Renderbuffer* renderbuffer = source->getReadColorbuffer();
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
sw::SliceRect sourceRect(x, y, x + width, y + height, 0); if(!renderbuffer)
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); {
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() void TextureCubeMap::generateMipmaps()
...@@ -1758,28 +1739,31 @@ void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo ...@@ -1758,28 +1739,31 @@ void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yo
return error(GL_INVALID_VALUE); return error(GL_INVALID_VALUE);
} }
egl::Image *renderTarget = source->getRenderTarget(0); if(width > 0 && height > 0)
if(!renderTarget)
{ {
ERR("Failed to retrieve the render target."); egl::Image *renderTarget = source->getRenderTarget(0);
return error(GL_OUT_OF_MEMORY);
}
Renderbuffer* renderbuffer = source->getReadColorbuffer(); if(!renderTarget)
{
ERR("Failed to retrieve the render target.");
return error(GL_OUT_OF_MEMORY);
}
if(!renderbuffer) Renderbuffer* renderbuffer = source->getReadColorbuffer();
{
ERR("Failed to retrieve the source colorbuffer.");
return;
}
sw::SliceRect sourceRect = {x, y, x + width, y + height, 0}; if(!renderbuffer)
sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight()); {
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) void Texture3D::setSharedImage(egl::Image *sharedImage)
......
...@@ -729,21 +729,19 @@ GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xo ...@@ -729,21 +729,19 @@ GL_APICALL void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xo
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture); GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
if(validationError == GL_NONE) if(validationError != GL_NONE)
{ {
GLenum validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type)); return error(validationError);
if(validationError != GL_NONE)
{
return error(validationError);
}
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); 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 ...@@ -793,7 +791,7 @@ 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();
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) if(validationError != GL_NONE)
{ {
return error(validationError); return error(validationError);
...@@ -935,7 +933,7 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level ...@@ -935,7 +933,7 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
return error(GL_INVALID_OPERATION); 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)) ((xoffset % 4) != 0) || ((yoffset % 4) != 0))
{ {
return error(GL_INVALID_OPERATION); return error(GL_INVALID_OPERATION);
...@@ -967,7 +965,8 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level ...@@ -967,7 +965,8 @@ GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level
if(is_ETC2_EAC) if(is_ETC2_EAC)
{ {
if(((width + xoffset) != texture->getWidth(target, level)) || 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); return error(GL_INVALID_OPERATION);
} }
...@@ -4085,7 +4084,7 @@ GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internal ...@@ -4085,7 +4084,7 @@ GL_APICALL void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internal
return; return;
} }
if(!IsColorRenderable(internalformat, egl::getClientVersion(), false) && if(!IsColorRenderable(internalformat, egl::getClientVersion()) &&
!IsDepthRenderable(internalformat, egl::getClientVersion()) && !IsDepthRenderable(internalformat, egl::getClientVersion()) &&
!IsStencilRenderable(internalformat, egl::getClientVersion())) !IsStencilRenderable(internalformat, egl::getClientVersion()))
{ {
......
...@@ -45,21 +45,23 @@ namespace es2 ...@@ -45,21 +45,23 @@ namespace es2
bool IsCompressed(GLenum format, GLint clientVersion); bool IsCompressed(GLenum format, GLint clientVersion);
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type); GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
GLenum ValidateCompressedFormat(GLenum format, GLint clientVersion, bool expectCompressedFormats); 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, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLenum ValidateSubImageParams(bool compressed, GLsizei width, GLsizei height, GLsizei depth, GLint xoffset, GLint yoffset, GLint zoffset, GLenum target, GLint level, GLenum sizedInternalFormat, Texture *texture); 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 IsValidReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type, GLint clientVersion);
bool IsDepthTexture(GLenum format); bool IsDepthTexture(GLenum format);
bool IsStencilTexture(GLenum format); bool IsStencilTexture(GLenum format);
bool IsCubemapTextureTarget(GLenum target); bool IsCubemapTextureTarget(GLenum target);
int CubeFaceIndex(GLenum cubeTarget); int CubeFaceIndex(GLenum cubeTarget);
bool IsTextureTarget(GLenum target); 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); GLsizei GetTypeSize(GLenum type);
bool IsColorRenderable(GLenum internalformat, GLint clientVersion, bool isTexture); bool IsColorRenderable(GLint internalformat, GLint clientVersion);
bool IsMipmappable(GLenum format, sw::Format internalFormat, GLint clientVersion); bool IsDepthRenderable(GLint internalformat, GLint clientVersion);
bool IsDepthRenderable(GLenum internalformat, GLint clientVersion); bool IsStencilRenderable(GLint internalformat, GLint clientVersion);
bool IsStencilRenderable(GLenum 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 // 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. // 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