// // Copyright 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. //
// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
if (!context->getExtensions().copyTexture3dANGLE)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable); returnfalse;
}
if (!ValidTexture3DTarget(context, source->getType()))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); returnfalse;
}
// Table 1.1 from the ANGLE_copy_texture_3d spec switch (GetUnsizedFormat(srcInternalFormat))
{ case GL_ALPHA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_RED: case GL_RED_INTEGER: case GL_RG: case GL_RG_INTEGER: case GL_RGB: case GL_RGB_INTEGER: case GL_RGBA: case GL_RGBA_INTEGER: case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL: break; default:
context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
srcInternalFormat); returnfalse;
}
if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); returnfalse;
}
// Table 1.0 from the ANGLE_copy_texture_3d spec switch (internalFormat)
{ case GL_RGB: case GL_RGBA: case GL_LUMINANCE: case GL_LUMINANCE_ALPHA: case GL_ALPHA: case GL_R8: case GL_R8_SNORM: case GL_R16F: case GL_R32F: case GL_R8UI: case GL_R8I: case GL_R16UI: case GL_R16I: case GL_R32UI: case GL_R32I: case GL_RG: case GL_RG8: case GL_RG8_SNORM: case GL_RG16F: case GL_RG32F: case GL_RG8UI: case GL_RG8I: case GL_RG16UI: case GL_RG16I: case GL_RG32UI: case GL_RG32I: case GL_RGB8: case GL_RGBX8_ANGLE: case GL_SRGB8: case GL_RGB565: case GL_RGB8_SNORM: case GL_R11F_G11F_B10F: case GL_RGB9_E5: case GL_RGB16F: case GL_RGB32F: case GL_RGB8UI: case GL_RGB8I: case GL_RGB16UI: case GL_RGB16I: case GL_RGB32UI: case GL_RGB32I: case GL_RGBA8: case GL_SRGB8_ALPHA8: case GL_RGBA8_SNORM: case GL_RGB5_A1: case GL_RGBA4: case GL_RGB10_A2: case GL_RGBA16F: case GL_RGBA32F: case GL_RGBA8UI: case GL_RGBA8I: case GL_RGB10_A2UI: case GL_RGBA16UI: case GL_RGBA16I: case GL_RGBA32I: case GL_RGBA32UI: break; default:
context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
internalFormat); returnfalse;
}
returntrue;
}
} // anonymous namespace
staticbool ValidateTexImageFormatCombination(const Context *context,
angle::EntryPoint entryPoint,
TextureType target,
GLenum internalFormat,
GLenum format,
GLenum type)
{ // Different validation if on desktop api if (context->getClientType() == EGL_OPENGL_API)
{ // The type and format are valid if any supported internal format has that type and format if (!ValidDesktopFormat(format))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); returnfalse;
}
if (!ValidDesktopType(type))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType); returnfalse;
}
} else
{ // The type and format are valid if any supported internal format has that type and format. // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats if (gl::IsYuvFormat(format))
{ if (!context->getExtensions().yuvInternalFormatANGLE)
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); returnfalse;
}
} else
{ if (!ValidES3Format(format))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); returnfalse;
}
}
// For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE // error instead of a GL_INVALID_ENUM error. As this validation function is only called in // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error. if (!ValidES3InternalFormat(internalFormat))
{
context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
internalFormat); returnfalse;
}
// From the ES 3.0 spec section 3.8.3: // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an // INVALID_OPERATION error. if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, k3DDepthStencil); returnfalse;
}
if (context->getClientType() == EGL_OPENGL_API)
{ // Check if this is a valid format combination to load texture data if (!ValidDesktopFormatCombination(format, type, internalFormat))
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination); returnfalse;
}
} else
{ // Check if this is a valid format combination to load texture data // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats if (gl::IsYuvFormat(format))
{ if (type != GL_UNSIGNED_BYTE)
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
kInvalidFormatCombination); returnfalse;
}
} else
{ if (!ValidES3FormatCombination(format, type, internalFormat))
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
kInvalidFormatCombination); returnfalse;
}
}
}
if (gl::IsYuvFormat(format))
{ // According to ANGLE_yuv_internal_format, the texture needs to be an immutable // texture, texture target can only be TEXTURE_2D and there is no mipmap support if (!context->getExtensions().yuvInternalFormatANGLE || !isSubImage)
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); returnfalse;
}
if (target != TextureTarget::_2D)
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); returnfalse;
}
const InternalFormat &actualFormatInfo = isSubImage
? *texture->getFormat(target, level).info
: GetInternalFormatInfo(internalformat, type); if (isCompressed)
{ // compressedTexSubImage does not generate GL_INVALID_ENUM when format is unknown or invalid if (!isSubImage)
{ if (!actualFormatInfo.compressed && !actualFormatInfo.paletted)
{
context->validationError(entryPoint, GL_INVALID_ENUM, kCompressedMismatch); returnfalse;
}
if (!actualFormatInfo.textureSupport(context->getClientVersion(),
context->getExtensions()))
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); returnfalse;
}
}
if (texType == TextureType::_2DArray)
{
GLenum compressedDataFormat = isSubImage ? format : internalformat; if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
compressedDataFormat))
{ // Error already generated. returnfalse;
}
}
if (texType == TextureType::_3D)
{
GLenum compressedDataFormat = isSubImage ? format : internalformat; if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint, compressedDataFormat))
{ // Error already generated. returnfalse;
}
}
// Check for pixel unpack buffer related API errors
Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack); if (pixelUnpackBuffer != nullptr)
{ // ...data is not evenly divisible into the number of bytes needed to store in memory a // datum // indicated by type. if (!isCompressed)
{
size_t offset = reinterpret_cast<size_t>(pixels);
size_t dataBytesPerPixel = static_cast<size_t>(GetTypeInfo(type).bytes);
// ...the buffer object's data store is currently mapped but not persistently. if (pixelUnpackBuffer->isMapped() && !pixelUnpackBuffer->isPersistentlyMapped())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped); returnfalse;
}
}
if (context->getExtensions().webglCompatibilityANGLE)
{ // Define: // DataStoreWidth = (GL_UNPACK_ROW_LENGTH ? GL_UNPACK_ROW_LENGTH : width) // DataStoreHeight = (GL_UNPACK_IMAGE_HEIGHT ? GL_UNPACK_IMAGE_HEIGHT : height) // // WebGL 2.0 imposes the following additional constraints: // // 1) texImage2D and texSubImage2D generate INVALID_OPERATION if: // GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth // except for texImage2D if no GL_PIXEL_UNPACK_BUFFER is // bound and _pixels_ is null. // // 2) texImage3D and texSubImage3D generate INVALID_OPERATION if: // GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth // GL_UNPACK_SKIP_ROWS + height > DataStoreHeight // except for texImage3D if no GL_PIXEL_UNPACK_BUFFER is // bound and _pixels_ is null. if (!pixelUnpackBuffer && !pixels && !isSubImage)
{ // Exception case for texImage2D or texImage3D, above.
} else
{ constauto &unpack = context->getState().getUnpackState();
GLint dataStoreWidth = unpack.rowLength ? unpack.rowLength : width; if (unpack.skipPixels + width > dataStoreWidth)
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
kInvalidUnpackParametersForWebGL); returnfalse;
} if (target == TextureTarget::_3D || target == TextureTarget::_2DArray)
{
GLint dataStoreHeight = unpack.imageHeight ? unpack.imageHeight : height; if (unpack.skipRows + height > dataStoreHeight)
{
context->validationError(entryPoint, GL_INVALID_OPERATION,
kInvalidUnpackParametersForWebGL); returnfalse;
}
}
}
}
// 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.
// SNORM is not supported (e.g. is not in the tables of "effective internal format" that // correspond to internal formats. if (textureFormatInfo.componentType == GL_SIGNED_NORMALIZED)
{ returnfalse;
}
// Section 3.8.5 of the GLES 3.0.3 (and section 8.6 of the GLES 3.2) spec has a caveat, that // the KHR dEQP tests enforce: // // Note that the above rules disallow matches where some components sizes are smaller and // others are larger (such as RGB10_A2). if (!textureFormatInfo.sized && (framebufferFormatInfo.internalFormat == GL_RGB10_A2))
{ returnfalse;
}
// GLES specification 3.0.3, sec 3.8.5, pg 139-140: // The effective internal format of the source buffer is determined with the following rules // applied in order: // * If the source buffer is a texture or renderbuffer that was created with a sized internal // format then the effective internal format is the source buffer's sized internal format. // * If the source buffer is a texture that was created with an unsized base internal format, // then the effective internal format is the source image array's effective internal // format, as specified by table 3.12, which is determined from the <format> and <type> // that were used when the source image array was specified by TexImage*. // * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18 // where Destination Internal Format matches internalformat and where the [source channel // sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17 // is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the // FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB. const InternalFormat *sourceEffectiveFormat = nullptr; if (readBufferHandle.value != 0)
{ // Not the default framebuffer, therefore the read buffer must be a user-created texture or // renderbuffer if (framebufferFormatInfo.sized)
{
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.
sourceEffectiveFormat =
&GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
}
} else
{ // 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 (framebufferFormatInfo.colorEncoding == GL_LINEAR)
{
GLenum effectiveFormat; if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
&effectiveFormat))
{
sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
} else
{ returnfalse;
}
} elseif (framebufferFormatInfo.colorEncoding == GL_SRGB)
{ // SRGB buffers can only be copied to sized format destinations according to table 3.18 if (textureFormatInfo.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 = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
} else
{ returnfalse;
}
} else
{
UNREACHABLE(); returnfalse;
}
}
if (textureFormatInfo.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(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
!EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
!EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
!EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
{ returnfalse;
}
}
returntrue; // A conversion function exists, and no rule in the specification has precluded // conversion between these formats.
}
if (!ValidateFramebufferComplete(context, entryPoint, framebuffer))
{ returnfalse;
}
// needIntrinsic = true. Treat renderToTexture textures as single sample since they will be // resolved before copying if (!framebuffer->isDefault() &&
!ValidateFramebufferNotMultisampled(context, entryPoint, framebuffer, true))
{ returnfalse;
}
// According to ES 3.x spec, if the internalformat of the texture // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION. if (textureFormat.info->internalFormat == GL_RGB9_E5)
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat); returnfalse;
}
if (texture->getImmutableFormat())
{
context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable); returnfalse;
}
returntrue;
}
bool ValidateES3TexStorageParametersFormat(const Context *context,
angle::EntryPoint entryPoint,
TextureType target,
GLsizei levels,
GLenum internalformat,
GLsizei width,
GLsizei height,
GLsizei depth)
{ // From ANGLE_texture_external_yuv_sampling: // Texture target can only be TEXTURE_2D, there is no mipmap support if (gl::IsYuvFormat(internalformat))
{ if (!context->getExtensions().yuvInternalFormatANGLE)
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat); returnfalse;
}
if (target != TextureType::_2D)
{
context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget); returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.