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/14488
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp
index fa01ff3..fc0c4a3 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.cpp
+++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -328,7 +328,7 @@
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 format = colorbuffer->getFormat();
- if(!IsColorRenderable(format, egl::getClientVersion(), true))
+ if(!IsColorRenderable(format, egl::getClientVersion()))
{
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
}
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index ff58214..77e6d3f 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -431,22 +431,7 @@
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 @@
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 @@
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);
+
+ if(!renderTarget)
+ {
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ Renderbuffer* renderbuffer = source->getReadColorbuffer();
+
+ if(!renderbuffer)
+ {
+ ERR("Failed to retrieve the source colorbuffer.");
+ return;
+ }
+
+ sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
+ sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
+
+ copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
+
+ renderTarget->release();
}
-
- Renderbuffer* renderbuffer = source->getReadColorbuffer();
-
- if(!renderbuffer)
- {
- ERR("Failed to retrieve the source colorbuffer.");
- return;
- }
-
- sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
- sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
-
- copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
-
- renderTarget->release();
}
void Texture2D::setSharedImage(egl::Image *sharedImage)
@@ -1415,28 +1393,31 @@
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);
+
+ if(!renderTarget)
+ {
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ Renderbuffer* renderbuffer = source->getReadColorbuffer();
+
+ if(!renderbuffer)
+ {
+ ERR("Failed to retrieve the source colorbuffer.");
+ return;
+ }
+
+ sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
+ sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
+
+ copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, zoffset, image[face][level]);
+
+ renderTarget->release();
}
-
- Renderbuffer* renderbuffer = source->getReadColorbuffer();
-
- if(!renderbuffer)
- {
- ERR("Failed to retrieve the source colorbuffer.");
- return;
- }
-
- sw::SliceRect sourceRect(x, y, x + width, y + height, 0);
- sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
-
- copy(renderTarget, sourceRect, image[face][level]->getFormat(), xoffset, yoffset, zoffset, image[face][level]);
-
- renderTarget->release();
}
void TextureCubeMap::generateMipmaps()
@@ -1758,28 +1739,31 @@
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);
+
+ if(!renderTarget)
+ {
+ ERR("Failed to retrieve the render target.");
+ return error(GL_OUT_OF_MEMORY);
+ }
+
+ Renderbuffer* renderbuffer = source->getReadColorbuffer();
+
+ if(!renderbuffer)
+ {
+ ERR("Failed to retrieve the source colorbuffer.");
+ return;
+ }
+
+ sw::SliceRect sourceRect = {x, y, x + width, y + height, 0};
+ sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
+
+ copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
+
+ renderTarget->release();
}
-
- Renderbuffer* renderbuffer = source->getReadColorbuffer();
-
- if(!renderbuffer)
- {
- ERR("Failed to retrieve the source colorbuffer.");
- return;
- }
-
- sw::SliceRect sourceRect = {x, y, x + width, y + height, 0};
- sourceRect.clip(0, 0, renderbuffer->getWidth(), renderbuffer->getHeight());
-
- copy(renderTarget, sourceRect, image[level]->getFormat(), xoffset, yoffset, zoffset, image[level]);
-
- renderTarget->release();
}
void Texture3D::setSharedImage(egl::Image *sharedImage)
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index 3d7aa42..08abb33 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -902,7 +902,6 @@
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 @@
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 @@
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 @@
{
es2::Texture2D *texture = context->getTexture2D();
- GLenum validationError = ValidateSubImageParams(true, width, height, xoffset, yoffset, target, level, sizedInternalFormat, texture);
-
- if(validationError == GL_NONE)
- {
- validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
- }
-
- if(validationError == GL_NONE)
- {
- texture->subImageCompressed(level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
- }
- else
+ GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
+ if(validationError != GL_NONE)
{
return error(validationError);
}
+
+ 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)
- {
- validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
- }
-
- if(validationError == GL_NONE)
- {
- texture->subImageCompressed(target, level, xoffset, yoffset, width, height, sizedInternalFormat, imageSize, data);
- }
- else
+ GLenum validationError = ValidateSubImageParams(true, false, target, level, xoffset, yoffset, width, height, format, GL_NONE, texture, context->getClientVersion());
+ if(validationError != GL_NONE)
{
return error(validationError);
}
+
+ 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 @@
return error(GL_INVALID_VALUE);
}
- if(width == 0 || height == 0)
- {
- return;
- }
-
es2::Context *context = es2::getContext();
if(context)
@@ -1171,7 +1150,7 @@
}
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 @@
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 @@
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 @@
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 @@
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)
- {
- texture->subImage(context, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
- }
- else
+ GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
+ if(validationError != GL_NONE)
{
return error(validationError);
}
+
+ 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)
- {
- texture->subImage(context, target, level, xoffset, yoffset, width, height, sizedInternalFormat, type, context->getUnpackInfo(), data);
- }
- else
+ GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, width, height, format, type, texture, context->getClientVersion());
+ if(validationError != GL_NONE)
{
return error(validationError);
}
+
+ 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 @@
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 @@
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
- GLenum validationError = ValidateSubImageParams(false, width, height, depth, xoffset, yoffset, zoffset, target, level, sizedInternalFormat, texture);
-
- if(validationError == GL_NONE)
- {
- validationError = context->getPixels(&data, type, context->getRequiredBufferSize(width, height, depth, sizedInternalFormat, type));
- }
-
- if(validationError == GL_NONE)
- {
- texture->subImage(context, level, xoffset, yoffset, zoffset, width, height, depth, sizedInternalFormat, type, context->getUnpackInfo(), data);
- }
- else
+ GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
+ if(validationError != GL_NONE)
{
return error(validationError);
}
+
+ 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 @@
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 @@
}
GLenum validationError = context->getPixels(&data, texture->getType(target, level), imageSize);
-
if(validationError != GL_NONE)
{
return error(validationError);
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 2d646ec..0e006c3 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -729,21 +729,19 @@
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 = 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);
- }
- else
+ GLenum validationError = ValidateSubImageParams(false, false, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, texture, context->getClientVersion());
+ if(validationError != GL_NONE)
{
return error(validationError);
}
+
+ 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 @@
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 @@
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 @@
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 @@
return;
}
- if(!IsColorRenderable(internalformat, egl::getClientVersion(), false) &&
+ if(!IsColorRenderable(internalformat, egl::getClientVersion()) &&
!IsDepthRenderable(internalformat, egl::getClientVersion()) &&
!IsStencilRenderable(internalformat, egl::getClientVersion()))
{
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 0d86291..1cc650c 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -520,31 +520,40 @@
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))
- {
- return GL_INVALID_OPERATION;
- }
+ GLenum sizedInternalFormat = texture->getFormat(target, level);
- if(sizedInternalFormat != GL_NONE && sizedInternalFormat != texture->getFormat(target, level))
+ if(compressed)
{
- return GL_INVALID_OPERATION;
+ if(format != sizedInternalFormat)
+ {
+ return GL_INVALID_OPERATION;
+ }
+ }
+ else if(!copy) // CopyTexSubImage doesn't have format/type parameters.
+ {
+ GLenum validationError = ValidateTextureFormatType(format, type, sizedInternalFormat, clientVersion);
+ if(validationError != GL_NONE)
+ {
+ return validationError;
+ }
}
if(compressed)
@@ -565,7 +574,8 @@
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 @@
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 @@
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 @@
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 @@
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 @@
case GL_RGB9_E5:
break;
default:
- return error(GL_INVALID_ENUM, false);
+ return GL_INVALID_ENUM;
}
}
@@ -906,7 +942,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
{
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:
- case GL_LUMINANCE:
- case GL_ALPHA:
switch(type)
{
- case GL_UNSIGNED_BYTE:
+ case GL_UNSIGNED_BYTE: VALIDATE_INTERNALFORMAT(GL_LUMINANCE8_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_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: VALIDATE_INTERNALFORMAT(GL_ALPHA8_EXT)
+ case GL_HALF_FLOAT_OES:
+ case GL_FLOAT:
+ break;
+ default:
+ 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 @@
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 @@
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 @@
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 @@
return false;
}
- bool IsStencilRenderable(GLenum internalformat, GLint clientVersion)
+ bool IsStencilRenderable(GLint internalformat, GLint clientVersion)
{
switch(internalformat)
{
@@ -1282,6 +1319,10 @@
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 @@
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
diff --git a/src/OpenGL/libGLESv2/utilities.h b/src/OpenGL/libGLESv2/utilities.h
index 6e18252..7240999 100644
--- a/src/OpenGL/libGLESv2/utilities.h
+++ b/src/OpenGL/libGLESv2/utilities.h
@@ -45,21 +45,23 @@
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.