Commit 0c8abca1 by Jamie Madill Committed by Commit Bot

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/362618Reviewed-by: 's avatarZhenyao Mo <zmo@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>
parent a3944d4f
......@@ -1649,7 +1649,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
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 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
}
}
*textureFormatOut = texture->getFormat(target, level).asSized();
if (textureFormatOut)
{
*textureFormatOut = texture->getFormat(target, level);
}
return true;
}
......
......@@ -23,6 +23,7 @@ class Image;
namespace gl
{
class Context;
struct Format;
class Program;
class Shader;
class ValidationContext;
......@@ -143,7 +144,7 @@ bool ValidateCopyTexImageParametersBase(ValidationContext *context,
GLsizei width,
GLsizei height,
GLint border,
GLenum *textureInternalFormatOut);
Format *textureFormatOut);
bool ValidateDrawArrays(ValidationContext *context,
GLenum mode,
......
......@@ -630,29 +630,28 @@ bool ValidateES2CopyTexImageParameters(ValidationContext *context,
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 @@ bool ValidateES2CopyTexImageParameters(ValidationContext *context,
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;
......
......@@ -770,36 +770,42 @@ static bool EqualOrFirstZero(GLuint first, GLuint second)
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 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
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 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
{
// 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 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
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 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
}
}
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 @@ bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
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 @@ bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
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 @@ bool ValidateES3CopyTexImageParametersBase(ValidationContext *context,
}
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;
......
......@@ -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
......
......@@ -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
......
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