Fix CopyTexSubImage validation.
Now that we preserve the sized-ness information, we can validate
CopyTexSubImage and related methods correctly.
Fixed a lot of WebGL 2 tests when using ANGLE.
BUG=angleproject:1228
Change-Id: I959322c0a9bb16a2f16d60dce7cd1e63ca95b45a
Reviewed-on: https://chromium-review.googlesource.com/362618
Reviewed-by: Zhenyao Mo <zmo@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index ab575f1..1bbfe86 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -1649,7 +1649,7 @@
GLsizei width,
GLsizei height,
GLint border,
- GLenum *textureFormatOut)
+ Format *textureFormatOut)
{
if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0)
{
@@ -1786,7 +1786,10 @@
}
}
- *textureFormatOut = texture->getFormat(target, level).asSized();
+ if (textureFormatOut)
+ {
+ *textureFormatOut = texture->getFormat(target, level);
+ }
return true;
}
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
index 56f88cb..a2b3601 100644
--- a/src/libANGLE/validationES.h
+++ b/src/libANGLE/validationES.h
@@ -23,6 +23,7 @@
namespace gl
{
class Context;
+struct Format;
class Program;
class Shader;
class ValidationContext;
@@ -143,7 +144,7 @@
GLsizei width,
GLsizei height,
GLint border,
- GLenum *textureInternalFormatOut);
+ Format *textureFormatOut);
bool ValidateDrawArrays(ValidationContext *context,
GLenum mode,
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
index 540ed1a..c25d1e5 100644
--- a/src/libANGLE/validationES2.cpp
+++ b/src/libANGLE/validationES2.cpp
@@ -630,29 +630,28 @@
GLsizei height,
GLint border)
{
- GLenum textureInternalFormat = GL_NONE;
-
if (!ValidTexture2DDestinationTarget(context, target))
{
context->handleError(Error(GL_INVALID_ENUM, "Invalid texture target"));
return false;
}
+ Format textureFormat = Format::Invalid();
if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
- xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat))
+ xoffset, yoffset, 0, x, y, width, height, border,
+ &textureFormat))
{
return false;
}
const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getFormat().asSized();
- const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
- GLenum textureFormat = internalFormatInfo.format;
+ const auto &formatInfo = *textureFormat.info;
// [OpenGL ES 2.0.24] table 3.9
if (isSubImage)
{
- switch (textureFormat)
+ switch (formatInfo.format)
{
case GL_ALPHA:
if (colorbufferFormat != GL_ALPHA8_EXT &&
@@ -750,8 +749,7 @@
return false;
}
- if (internalFormatInfo.type == GL_FLOAT &&
- !context->getExtensions().textureFloat)
+ if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
{
context->handleError(Error(GL_INVALID_OPERATION));
return false;
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index a1e11cd..bb9827a 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -770,36 +770,42 @@
return first == 0 || first == second;
}
-static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle)
+static bool IsValidES3CopyTexImageCombination(const Format &textureFormat,
+ const Format &framebufferFormat,
+ GLuint readBufferHandle)
{
- const InternalFormat &textureInternalFormatInfo = GetInternalFormatInfo(textureInternalFormat);
- const InternalFormat &framebufferInternalFormatInfo = GetInternalFormatInfo(frameBufferInternalFormat);
+ const auto &textureFormatInfo = *textureFormat.info;
+ const auto &framebufferFormatInfo = *framebufferFormat.info;
static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations();
- if (conversionSet.find(CopyConversion(textureInternalFormatInfo.format, framebufferInternalFormatInfo.format)) != conversionSet.end())
+ if (conversionSet.find(CopyConversion(textureFormatInfo.format,
+ framebufferFormatInfo.format)) != conversionSet.end())
{
// Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
// must both be signed, unsigned, or fixed point and both source and destinations
// must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
// conversion between fixed and floating point.
- if ((textureInternalFormatInfo.colorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.colorEncoding == GL_SRGB))
+ if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
+ (framebufferFormatInfo.colorEncoding == GL_SRGB))
{
return false;
}
- if (((textureInternalFormatInfo.componentType == GL_INT) != (framebufferInternalFormatInfo.componentType == GL_INT )) ||
- ((textureInternalFormatInfo.componentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.componentType == GL_UNSIGNED_INT)))
+ if (((textureFormatInfo.componentType == GL_INT) !=
+ (framebufferFormatInfo.componentType == GL_INT)) ||
+ ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
+ (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
{
return false;
}
- if ((textureInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
- textureInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
- textureInternalFormatInfo.componentType == GL_FLOAT) &&
- !(framebufferInternalFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
- framebufferInternalFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
- framebufferInternalFormatInfo.componentType == GL_FLOAT))
+ if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ textureFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ textureFormatInfo.componentType == GL_FLOAT) &&
+ !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED ||
+ framebufferFormatInfo.componentType == GL_FLOAT))
{
return false;
}
@@ -821,15 +827,16 @@
if (readBufferHandle != 0)
{
// Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer
- if (framebufferInternalFormatInfo.pixelBytes > 0)
+ if (framebufferFormat.sized)
{
- sourceEffectiveFormat = &framebufferInternalFormatInfo;
+ sourceEffectiveFormat = &framebufferFormatInfo;
}
else
{
// Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
// texture. We can use the same table we use when creating textures to get its effective sized format.
- GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
+ GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferFormatInfo.format,
+ framebufferFormatInfo.type);
sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
}
}
@@ -837,10 +844,11 @@
{
// The effective internal format must be derived from the source framebuffer's channel sizes.
// This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
- if (framebufferInternalFormatInfo.colorEncoding == GL_LINEAR)
+ if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
{
GLenum effectiveFormat;
- if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat))
+ if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
+ &effectiveFormat))
{
sourceEffectiveFormat = &GetInternalFormatInfo(effectiveFormat);
}
@@ -849,14 +857,15 @@
return false;
}
}
- else if (framebufferInternalFormatInfo.colorEncoding == GL_SRGB)
+ else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
{
// SRGB buffers can only be copied to sized format destinations according to table 3.18
- if ((textureInternalFormatInfo.pixelBytes > 0) &&
- (framebufferInternalFormatInfo.redBits >= 1 && framebufferInternalFormatInfo.redBits <= 8) &&
- (framebufferInternalFormatInfo.greenBits >= 1 && framebufferInternalFormatInfo.greenBits <= 8) &&
- (framebufferInternalFormatInfo.blueBits >= 1 && framebufferInternalFormatInfo.blueBits <= 8) &&
- (framebufferInternalFormatInfo.alphaBits >= 1 && framebufferInternalFormatInfo.alphaBits <= 8))
+ if (textureFormat.sized &&
+ (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
+ (framebufferFormatInfo.greenBits >= 1 &&
+ framebufferFormatInfo.greenBits <= 8) &&
+ (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
+ (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
{
sourceEffectiveFormat = &GetInternalFormatInfo(GL_SRGB8_ALPHA8);
}
@@ -872,25 +881,20 @@
}
}
- if (textureInternalFormatInfo.pixelBytes > 0)
+ if (textureFormat.sized)
{
// Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination
// format is sized, component sizes of the source and destination formats must exactly
// match if the destination format exists.
- if (!EqualOrFirstZero(textureInternalFormatInfo.redBits,
- sourceEffectiveFormat->redBits) ||
- !EqualOrFirstZero(textureInternalFormatInfo.greenBits,
- sourceEffectiveFormat->greenBits) ||
- !EqualOrFirstZero(textureInternalFormatInfo.blueBits,
- sourceEffectiveFormat->blueBits) ||
- !EqualOrFirstZero(textureInternalFormatInfo.alphaBits,
- sourceEffectiveFormat->alphaBits))
+ if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
+ !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
+ !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
+ !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
{
return false;
}
}
-
return true; // A conversion function exists, and no rule in the specification has precluded conversion
// between these formats.
}
@@ -912,14 +916,14 @@
GLsizei height,
GLint border)
{
- GLenum textureInternalFormat = GL_NONE;
+ Format textureFormat = Format::Invalid();
if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
- xoffset, yoffset, zoffset, x, y, width, height,
- border, &textureInternalFormat))
+ xoffset, yoffset, zoffset, x, y, width, height, border,
+ &textureFormat))
{
return false;
}
- ASSERT(textureInternalFormat != GL_NONE || !isSubImage);
+ ASSERT(textureFormat.valid() || !isSubImage);
const auto &state = context->getGLState();
gl::Framebuffer *framebuffer = state.getReadFramebuffer();
@@ -937,12 +941,11 @@
return false;
}
- const gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer();
- GLenum colorbufferInternalFormat = source->getFormat().asSized();
+ const FramebufferAttachment *source = framebuffer->getReadColorbuffer();
if (isSubImage)
{
- if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat,
+ if (!IsValidES3CopyTexImageCombination(textureFormat, source->getFormat(),
readFramebufferID))
{
context->handleError(Error(GL_INVALID_OPERATION));
@@ -951,8 +954,10 @@
}
else
{
- if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat,
- readFramebufferID))
+ // Use format/type from the source FBO. (Might not be perfect for all cases?)
+ const auto framebufferFormat = source->getFormat();
+ Format copyFormat(internalformat, framebufferFormat.format, framebufferFormat.type);
+ if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
{
context->handleError(Error(GL_INVALID_OPERATION));
return false;
diff --git a/src/tests/deqp_support/deqp_gles2_test_expectations.txt b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
index 209d8f9..5ea0f13 100644
--- a/src/tests/deqp_support/deqp_gles2_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles2_test_expectations.txt
@@ -80,7 +80,6 @@
1020 WIN : dEQP-GLES2.functional.texture.mipmap.cube.projected.linear_nearest = FAIL
1020 WIN : dEQP-GLES2.functional.texture.mipmap.cube.bias.linear_nearest = FAIL
1020 WIN : dEQP-GLES2.functional.texture.mipmap.cube.bias.linear_linear = FAIL
-1021 WIN : dEQP-GLES2.functional.texture.specification.basic_copyteximage2d.cube_luminance = FAIL
1025 WIN : dEQP-GLES2.functional.fragment_ops.depth_stencil.stencil_depth_funcs.stencil_* = FAIL
1025 WIN : dEQP-GLES2.functional.fragment_ops.depth_stencil.stencil_ops.* = FAIL
1025 WIN : dEQP-GLES2.functional.fragment_ops.depth_stencil.write_mask.* = FAIL
diff --git a/src/tests/deqp_support/deqp_gles3_test_expectations.txt b/src/tests/deqp_support/deqp_gles3_test_expectations.txt
index 6a32c03..31a53b3 100644
--- a/src/tests/deqp_support/deqp_gles3_test_expectations.txt
+++ b/src/tests/deqp_support/deqp_gles3_test_expectations.txt
@@ -122,14 +122,6 @@
1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureoffset.sampler3d_float_fragment = FAIL
1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojoffset.sampler3d_fixed_fragment = FAIL
1092 WIN : dEQP-GLES3.functional.shaders.texture_functions.textureprojoffset.sampler3d_float_fragment = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.2d_rgba = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.2d_alpha = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.2d_luminance_alpha = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.2d_rgb = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.cube_rgba = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.cube_alpha = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.cube_luminance_alpha = FAIL
-1095 WIN : dEQP-GLES3.functional.texture.specification.basic_copytexsubimage2d.cube_rgb = FAIL
1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.stencil_depth_funcs.stencil_* = FAIL
1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.stencil_ops.* = FAIL
1096 WIN : dEQP-GLES3.functional.fragment_ops.depth_stencil.write_mask.* = FAIL