summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libANGLE/validationES2.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/validationES2.cpp')
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES2.cpp6351
1 files changed, 0 insertions, 6351 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
deleted file mode 100644
index 5e505aa607..0000000000
--- a/src/3rdparty/angle/src/libANGLE/validationES2.cpp
+++ /dev/null
@@ -1,6351 +0,0 @@
-//
-// Copyright (c) 2013-2014 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.
-//
-
-// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
-
-#include "libANGLE/validationES2.h"
-
-#include <cstdint>
-
-#include "common/mathutil.h"
-#include "common/string_utils.h"
-#include "common/utilities.h"
-#include "libANGLE/Context.h"
-#include "libANGLE/ErrorStrings.h"
-#include "libANGLE/Framebuffer.h"
-#include "libANGLE/FramebufferAttachment.h"
-#include "libANGLE/Renderbuffer.h"
-#include "libANGLE/Shader.h"
-#include "libANGLE/Texture.h"
-#include "libANGLE/Uniform.h"
-#include "libANGLE/VertexArray.h"
-#include "libANGLE/formatutils.h"
-#include "libANGLE/validationES.h"
-#include "libANGLE/validationES3.h"
-
-namespace gl
-{
-
-namespace
-{
-
-bool IsPartialBlit(gl::Context *context,
- const FramebufferAttachment *readBuffer,
- const FramebufferAttachment *writeBuffer,
- GLint srcX0,
- GLint srcY0,
- GLint srcX1,
- GLint srcY1,
- GLint dstX0,
- GLint dstY0,
- GLint dstX1,
- GLint dstY1)
-{
- const Extents &writeSize = writeBuffer->getSize();
- const Extents &readSize = readBuffer->getSize();
-
- if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
- dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
- {
- return true;
- }
-
- if (context->getGLState().isScissorTestEnabled())
- {
- const Rectangle &scissor = context->getGLState().getScissor();
- return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
- scissor.height < writeSize.height;
- }
-
- return false;
-}
-
-template <typename T>
-bool ValidatePathInstances(gl::Context *context,
- GLsizei numPaths,
- const void *paths,
- GLuint pathBase)
-{
- const auto *array = static_cast<const T *>(paths);
-
- for (GLsizei i = 0; i < numPaths; ++i)
- {
- const GLuint pathName = array[i] + pathBase;
- if (context->hasPath(pathName) && !context->hasPathData(pathName))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
- return false;
- }
- }
- return true;
-}
-
-bool ValidateInstancedPathParameters(gl::Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLenum transformType,
- const GLfloat *transformValues)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- if (paths == nullptr)
- {
- context->handleError(InvalidValue() << "No path name array.");
- return false;
- }
-
- if (numPaths < 0)
- {
- context->handleError(InvalidValue() << "Invalid (negative) numPaths.");
- return false;
- }
-
- if (!angle::IsValueInRangeForNumericType<std::uint32_t>(numPaths))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
- return false;
- }
-
- std::uint32_t pathNameTypeSize = 0;
- std::uint32_t componentCount = 0;
-
- switch (pathNameType)
- {
- case GL_UNSIGNED_BYTE:
- pathNameTypeSize = sizeof(GLubyte);
- if (!ValidatePathInstances<GLubyte>(context, numPaths, paths, pathBase))
- return false;
- break;
-
- case GL_BYTE:
- pathNameTypeSize = sizeof(GLbyte);
- if (!ValidatePathInstances<GLbyte>(context, numPaths, paths, pathBase))
- return false;
- break;
-
- case GL_UNSIGNED_SHORT:
- pathNameTypeSize = sizeof(GLushort);
- if (!ValidatePathInstances<GLushort>(context, numPaths, paths, pathBase))
- return false;
- break;
-
- case GL_SHORT:
- pathNameTypeSize = sizeof(GLshort);
- if (!ValidatePathInstances<GLshort>(context, numPaths, paths, pathBase))
- return false;
- break;
-
- case GL_UNSIGNED_INT:
- pathNameTypeSize = sizeof(GLuint);
- if (!ValidatePathInstances<GLuint>(context, numPaths, paths, pathBase))
- return false;
- break;
-
- case GL_INT:
- pathNameTypeSize = sizeof(GLint);
- if (!ValidatePathInstances<GLint>(context, numPaths, paths, pathBase))
- return false;
- break;
-
- default:
- context->handleError(InvalidEnum() << "Invalid path name type.");
- return false;
- }
-
- switch (transformType)
- {
- case GL_NONE:
- componentCount = 0;
- break;
- case GL_TRANSLATE_X_CHROMIUM:
- case GL_TRANSLATE_Y_CHROMIUM:
- componentCount = 1;
- break;
- case GL_TRANSLATE_2D_CHROMIUM:
- componentCount = 2;
- break;
- case GL_TRANSLATE_3D_CHROMIUM:
- componentCount = 3;
- break;
- case GL_AFFINE_2D_CHROMIUM:
- case GL_TRANSPOSE_AFFINE_2D_CHROMIUM:
- componentCount = 6;
- break;
- case GL_AFFINE_3D_CHROMIUM:
- case GL_TRANSPOSE_AFFINE_3D_CHROMIUM:
- componentCount = 12;
- break;
- default:
- context->handleError(InvalidEnum() << "Invalid transformation.");
- return false;
- }
- if (componentCount != 0 && transformValues == nullptr)
- {
- context->handleError(InvalidValue() << "No transform array given.");
- return false;
- }
-
- angle::CheckedNumeric<std::uint32_t> checkedSize(0);
- checkedSize += (numPaths * pathNameTypeSize);
- checkedSize += (numPaths * sizeof(GLfloat) * componentCount);
- if (!checkedSize.IsValid())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
- return false;
- }
-
- return true;
-}
-
-bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
-{
- // Table 1.1 from the CHROMIUM_copy_texture spec
- switch (GetUnsizedFormat(internalFormat))
- {
- case GL_RED:
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_RGB:
- case GL_RGBA:
- case GL_RGB8:
- case GL_RGBA8:
- case GL_BGRA_EXT:
- case GL_BGRA8_EXT:
- return true;
-
- default:
- return false;
- }
-}
-
-bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
-{
- return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
-}
-
-bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
-{
- // Table 1.0 from the CHROMIUM_copy_texture spec
- switch (internalFormat)
- {
- case GL_RGB:
- case GL_RGBA:
- case GL_RGB8:
- case GL_RGBA8:
- case GL_BGRA_EXT:
- case GL_BGRA8_EXT:
- case GL_SRGB_EXT:
- case GL_SRGB_ALPHA_EXT:
- case GL_R8:
- case GL_R8UI:
- case GL_RG8:
- case GL_RG8UI:
- case GL_SRGB8:
- case GL_RGB565:
- case GL_RGB8UI:
- case GL_RGB10_A2:
- case GL_SRGB8_ALPHA8:
- case GL_RGB5_A1:
- case GL_RGBA4:
- case GL_RGBA8UI:
- case GL_RGB9_E5:
- case GL_R16F:
- case GL_R32F:
- case GL_RG16F:
- case GL_RG32F:
- case GL_RGB16F:
- case GL_RGB32F:
- case GL_RGBA16F:
- case GL_RGBA32F:
- case GL_R11F_G11F_B10F:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- case GL_ALPHA:
- return true;
-
- default:
- return false;
- }
-}
-
-bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
-{
- return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
-}
-
-bool IsValidCopyTextureDestinationFormatType(Context *context, GLint internalFormat, GLenum type)
-{
- if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
- {
- return false;
- }
-
- if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
- {
- context->handleError(InvalidOperation()
- << "Invalid combination of type and internalFormat.");
- return false;
- }
-
- const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
- if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
- {
- return false;
- }
-
- return true;
-}
-
-bool IsValidCopyTextureDestinationTargetEnum(Context *context, GLenum target)
-{
- switch (target)
- {
- case GL_TEXTURE_2D:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- return true;
-
- case GL_TEXTURE_RECTANGLE_ANGLE:
- return context->getExtensions().textureRectangle;
-
- default:
- return false;
- }
-}
-
-bool IsValidCopyTextureDestinationTarget(Context *context, GLenum textureType, GLenum target)
-{
- if (IsCubeMapTextureTarget(target))
- {
- return textureType == GL_TEXTURE_CUBE_MAP;
- }
- else
- {
- return textureType == target;
- }
-}
-
-bool IsValidCopyTextureSourceTarget(Context *context, GLenum target)
-{
- switch (target)
- {
- case GL_TEXTURE_2D:
- return true;
- case GL_TEXTURE_RECTANGLE_ANGLE:
- return context->getExtensions().textureRectangle;
-
- // TODO(geofflang): accept GL_TEXTURE_EXTERNAL_OES if the texture_external extension is
- // supported
-
- default:
- return false;
- }
-}
-
-bool IsValidCopyTextureSourceLevel(Context *context, GLenum target, GLint level)
-{
- if (!ValidMipLevel(context, target, level))
- {
- return false;
- }
-
- if (level > 0 && context->getClientVersion() < ES_3_0)
- {
- return false;
- }
-
- return true;
-}
-
-bool IsValidCopyTextureDestinationLevel(Context *context,
- GLenum target,
- GLint level,
- GLsizei width,
- GLsizei height)
-{
- if (!ValidMipLevel(context, target, level))
- {
- return false;
- }
-
- const Caps &caps = context->getCaps();
- if (target == GL_TEXTURE_2D)
- {
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
- {
- return false;
- }
- }
- else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
- {
- ASSERT(level == 0);
- if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
- static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
- {
- return false;
- }
- }
- else if (IsCubeMapTextureTarget(target))
- {
- if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool IsValidStencilFunc(GLenum func)
-{
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GEQUAL:
- case GL_GREATER:
- case GL_NOTEQUAL:
- return true;
-
- default:
- return false;
- }
-}
-
-bool IsValidStencilFace(GLenum face)
-{
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- return true;
-
- default:
- return false;
- }
-}
-
-bool IsValidStencilOp(GLenum op)
-{
- switch (op)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- return true;
-
- default:
- return false;
- }
-}
-
-bool ValidateES2CopyTexImageParameters(ValidationContext *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- bool isSubImage,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLint border)
-{
- if (!ValidTexture2DDestinationTarget(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
- {
- context->handleError(InvalidValue() << "Invalid texture dimensions.");
- return false;
- }
-
- Format textureFormat = Format::Invalid();
- if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage,
- xoffset, yoffset, 0, x, y, width, height, border,
- &textureFormat))
- {
- return false;
- }
-
- const gl::Framebuffer *framebuffer = context->getGLState().getReadFramebuffer();
- GLenum colorbufferFormat =
- framebuffer->getReadColorbuffer()->getFormat().info->sizedInternalFormat;
- const auto &formatInfo = *textureFormat.info;
-
- // [OpenGL ES 2.0.24] table 3.9
- if (isSubImage)
- {
- switch (formatInfo.format)
- {
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_LUMINANCE:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_RED_EXT:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
- colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_RG_EXT:
- if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
- colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- case GL_ETC1_RGB8_OES:
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
-
- if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloat)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- }
- else
- {
- switch (internalformat)
- {
- case GL_ALPHA:
- if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_LUMINANCE:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_RED_EXT:
- if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
- colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_RG_EXT:
- if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
- colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
- colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_RGB:
- if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
- colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_LUMINANCE_ALPHA:
- case GL_RGBA:
- if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
- colorbufferFormat != GL_BGR5_A1_ANGLEX)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->getExtensions().textureCompressionDXT1)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- else
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->getExtensions().textureCompressionDXT3)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- else
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->getExtensions().textureCompressionDXT5)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- else
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (context->getExtensions().compressedETC1RGB8Texture)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- if (context->getExtensions().lossyETCDecode)
- {
- context->handleError(InvalidOperation()
- << "ETC lossy decode formats can't be copied to.");
- return false;
- }
- else
- {
- context->handleError(InvalidEnum()
- << "ANGLE_lossy_etc_decode extension is not supported.");
- return false;
- }
- break;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH_STENCIL_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (context->getExtensions().depthTextures)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
- default:
- context->handleError(InvalidEnum());
- return false;
- }
- }
-
- // If width or height is zero, it is a no-op. Return false without setting an error.
- return (width > 0 && height > 0);
-}
-
-bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
-{
- switch (cap)
- {
- // EXT_multisample_compatibility
- case GL_MULTISAMPLE_EXT:
- case GL_SAMPLE_ALPHA_TO_ONE_EXT:
- return context->getExtensions().multisampleCompatibility;
-
- case GL_CULL_FACE:
- case GL_POLYGON_OFFSET_FILL:
- case GL_SAMPLE_ALPHA_TO_COVERAGE:
- case GL_SAMPLE_COVERAGE:
- case GL_SCISSOR_TEST:
- case GL_STENCIL_TEST:
- case GL_DEPTH_TEST:
- case GL_BLEND:
- case GL_DITHER:
- return true;
-
- case GL_PRIMITIVE_RESTART_FIXED_INDEX:
- case GL_RASTERIZER_DISCARD:
- return (context->getClientMajorVersion() >= 3);
-
- case GL_DEBUG_OUTPUT_SYNCHRONOUS:
- case GL_DEBUG_OUTPUT:
- return context->getExtensions().debug;
-
- case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
- return queryOnly && context->getExtensions().bindGeneratesResource;
-
- case GL_CLIENT_ARRAYS_ANGLE:
- return queryOnly && context->getExtensions().clientArrays;
-
- case GL_FRAMEBUFFER_SRGB_EXT:
- return context->getExtensions().sRGBWriteControl;
-
- case GL_SAMPLE_MASK:
- return context->getClientVersion() >= Version(3, 1);
-
- case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
- return queryOnly && context->getExtensions().robustResourceInitialization;
-
- default:
- return false;
- }
-}
-
-// Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
-// 3.1.
-bool IsValidESSLCharacter(unsigned char c)
-{
- // Printing characters are valid except " $ ` @ \ ' DEL.
- if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
- c != '\'')
- {
- return true;
- }
-
- // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
- if (c >= 9 && c <= 13)
- {
- return true;
- }
-
- return false;
-}
-
-bool IsValidESSLString(const char *str, size_t len)
-{
- for (size_t i = 0; i < len; i++)
- {
- if (!IsValidESSLCharacter(str[i]))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool IsValidESSLShaderSourceString(const char *str, size_t len, bool lineContinuationAllowed)
-{
- enum class ParseState
- {
- // Have not seen an ASCII non-whitespace character yet on
- // this line. Possible that we might see a preprocessor
- // directive.
- BEGINING_OF_LINE,
-
- // Have seen at least one ASCII non-whitespace character
- // on this line.
- MIDDLE_OF_LINE,
-
- // Handling a preprocessor directive. Passes through all
- // characters up to the end of the line. Disables comment
- // processing.
- IN_PREPROCESSOR_DIRECTIVE,
-
- // Handling a single-line comment. The comment text is
- // replaced with a single space.
- IN_SINGLE_LINE_COMMENT,
-
- // Handling a multi-line comment. Newlines are passed
- // through to preserve line numbers.
- IN_MULTI_LINE_COMMENT
- };
-
- ParseState state = ParseState::BEGINING_OF_LINE;
- size_t pos = 0;
-
- while (pos < len)
- {
- char c = str[pos];
- char next = pos + 1 < len ? str[pos + 1] : 0;
-
- // Check for newlines
- if (c == '\n' || c == '\r')
- {
- if (state != ParseState::IN_MULTI_LINE_COMMENT)
- {
- state = ParseState::BEGINING_OF_LINE;
- }
-
- pos++;
- continue;
- }
-
- switch (state)
- {
- case ParseState::BEGINING_OF_LINE:
- if (c == ' ')
- {
- // Maintain the BEGINING_OF_LINE state until a non-space is seen
- pos++;
- }
- else if (c == '#')
- {
- state = ParseState::IN_PREPROCESSOR_DIRECTIVE;
- pos++;
- }
- else
- {
- // Don't advance, re-process this character with the MIDDLE_OF_LINE state
- state = ParseState::MIDDLE_OF_LINE;
- }
- break;
-
- case ParseState::MIDDLE_OF_LINE:
- if (c == '/' && next == '/')
- {
- state = ParseState::IN_SINGLE_LINE_COMMENT;
- pos++;
- }
- else if (c == '/' && next == '*')
- {
- state = ParseState::IN_MULTI_LINE_COMMENT;
- pos++;
- }
- else if (lineContinuationAllowed && c == '\\' && (next == '\n' || next == '\r'))
- {
- // Skip line continuation characters
- }
- else if (!IsValidESSLCharacter(c))
- {
- return false;
- }
- pos++;
- break;
-
- case ParseState::IN_PREPROCESSOR_DIRECTIVE:
- // Line-continuation characters may not be permitted.
- // Otherwise, just pass it through. Do not parse comments in this state.
- if (!lineContinuationAllowed && c == '\\')
- {
- return false;
- }
- pos++;
- break;
-
- case ParseState::IN_SINGLE_LINE_COMMENT:
- // Line-continuation characters are processed before comment processing.
- // Advance string if a new line character is immediately behind
- // line-continuation character.
- if (c == '\\' && (next == '\n' || next == '\r'))
- {
- pos++;
- }
- pos++;
- break;
-
- case ParseState::IN_MULTI_LINE_COMMENT:
- if (c == '*' && next == '/')
- {
- state = ParseState::MIDDLE_OF_LINE;
- pos++;
- }
- pos++;
- break;
- }
- }
-
- return true;
-}
-
-bool ValidateWebGLNamePrefix(ValidationContext *context, const GLchar *name)
-{
- ASSERT(context->isWebGL());
-
- // WebGL 1.0 [Section 6.16] GLSL Constructs
- // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
- if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), WebglBindAttribLocationReservedPrefix);
- return false;
- }
-
- return true;
-}
-
-bool ValidateWebGLNameLength(ValidationContext *context, size_t length)
-{
- ASSERT(context->isWebGL());
-
- if (context->isWebGL1() && length > 256)
- {
- // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
- // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
- // locations.
- ANGLE_VALIDATION_ERR(context, InvalidValue(), WebglNameLengthLimitExceeded);
-
- return false;
- }
- else if (length > 1024)
- {
- // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
- // uniform and attribute locations.
- ANGLE_VALIDATION_ERR(context, InvalidValue(), Webgl2NameLengthLimitExceeded);
- return false;
- }
-
- return true;
-}
-
-} // anonymous namespace
-
-bool ValidateES2TexImageParameters(Context *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- bool isCompressed,
- bool isSubImage,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- GLsizei imageSize,
- const void *pixels)
-{
- if (!ValidTexture2DDestinationTarget(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- if (!ValidImageSizeParameters(context, target, level, width, height, 1, isSubImage))
- {
- context->handleError(InvalidValue());
- return false;
- }
-
- if (!ValidMipLevel(context, target, level))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
- return false;
- }
-
- if (xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width ||
- std::numeric_limits<GLsizei>::max() - yoffset < height)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), ResourceMaxTextureSize);
- return false;
- }
-
- // From GL_CHROMIUM_color_buffer_float_rgb[a]:
- // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
- // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
- // internalformat parameter and format parameter of TexImage2D must match is lifted for this
- // case.
- bool nonEqualFormatsAllowed =
- (internalformat == GL_RGB32F && context->getExtensions().colorBufferFloatRGB) ||
- (internalformat == GL_RGBA32F && context->getExtensions().colorBufferFloatRGBA);
-
- if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- const gl::Caps &caps = context->getCaps();
-
- if (target == GL_TEXTURE_2D)
- {
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
- {
- context->handleError(InvalidValue());
- return false;
- }
- }
- else if (target == GL_TEXTURE_RECTANGLE_ANGLE)
- {
- ASSERT(level == 0);
- if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
- static_cast<GLuint>(height) > caps.maxRectangleTextureSize)
- {
- context->handleError(InvalidValue());
- return false;
- }
- if (isCompressed)
- {
- context->handleError(InvalidEnum()
- << "Rectangle texture cannot have a compressed format.");
- return false;
- }
- }
- else if (IsCubeMapTextureTarget(target))
- {
- if (!isSubImage && width != height)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), CubemapFacesEqualDimensions);
- return false;
- }
-
- if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
- {
- context->handleError(InvalidValue());
- return false;
- }
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
-
- gl::Texture *texture =
- context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
- if (!texture)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
- return false;
- }
-
- if (isSubImage)
- {
- const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
- if (textureInternalFormat.internalFormat == GL_NONE)
- {
- context->handleError(InvalidOperation() << "Texture level does not exist.");
- return false;
- }
-
- if (format != GL_NONE)
- {
- if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
- textureInternalFormat.sizedInternalFormat)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
- return false;
- }
- }
-
- if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
- static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
- {
- context->handleError(InvalidValue());
- return false;
- }
-
- if (width > 0 && height > 0 && pixels == nullptr &&
- context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack) == nullptr)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), PixelDataNull);
- return false;
- }
- }
- else
- {
- if (texture->getImmutableFormat())
- {
- context->handleError(InvalidOperation());
- return false;
- }
- }
-
- // Verify zero border
- if (border != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidBorder);
- return false;
- }
-
- if (isCompressed)
- {
- GLenum actualInternalFormat =
- isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
- : internalformat;
- switch (actualInternalFormat)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->getExtensions().textureCompressionDXT1)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->getExtensions().textureCompressionDXT3)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->getExtensions().textureCompressionDXT5)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
- break;
- case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
- case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
- if (!context->getExtensions().textureCompressionS3TCsRGB)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (!context->getExtensions().compressedETC1RGB8Texture)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
- if (isSubImage)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- if (!context->getExtensions().lossyETCDecode)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidInternalFormat);
- return false;
- }
-
- if (isSubImage)
- {
- if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, width,
- height, texture->getWidth(target, level),
- texture->getHeight(target, level)))
- {
- context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
- return false;
- }
-
- if (format != actualInternalFormat)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidFormat);
- return false;
- }
- }
- else
- {
- if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height))
- {
- context->handleError(InvalidOperation() << "Invalid compressed format dimension.");
- return false;
- }
- }
- }
- else
- {
- // validate <type> by itself (used as secondary key below)
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_UNSIGNED_SHORT:
- case GL_UNSIGNED_INT:
- case GL_UNSIGNED_INT_24_8_OES:
- case GL_HALF_FLOAT_OES:
- case GL_FLOAT:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidType);
- return false;
- }
-
- // validate <format> + <type> combinations
- // - invalid <format> -> sets INVALID_ENUM
- // - invalid <format>+<type> combination -> sets INVALID_OPERATION
- switch (format)
- {
- case GL_ALPHA:
- case GL_LUMINANCE:
- case GL_LUMINANCE_ALPHA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_RED:
- case GL_RG:
- if (!context->getExtensions().textureRG)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- if (!context->getExtensions().textureFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_RGB:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_5_6_5:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_RGBA:
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- case GL_UNSIGNED_SHORT_4_4_4_4:
- case GL_UNSIGNED_SHORT_5_5_5_1:
- case GL_FLOAT:
- case GL_HALF_FLOAT_OES:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_BGRA_EXT:
- if (!context->getExtensions().textureFormatBGRA8888)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_SRGB_EXT:
- case GL_SRGB_ALPHA_EXT:
- if (!context->getExtensions().sRGB)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- switch (type)
- {
- case GL_UNSIGNED_BYTE:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are
- // handled below
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- break;
- case GL_DEPTH_COMPONENT:
- switch (type)
- {
- case GL_UNSIGNED_SHORT:
- case GL_UNSIGNED_INT:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- case GL_DEPTH_STENCIL_OES:
- switch (type)
- {
- case GL_UNSIGNED_INT_24_8_OES:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
- default:
- context->handleError(InvalidEnum());
- return false;
- }
-
- switch (format)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (context->getExtensions().textureCompressionDXT1)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (context->getExtensions().textureCompressionDXT3)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (context->getExtensions().textureCompressionDXT5)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (context->getExtensions().compressedETC1RGB8Texture)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- else
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- if (context->getExtensions().lossyETCDecode)
- {
- context->handleError(InvalidOperation()
- << "ETC lossy decode formats can't work with this type.");
- return false;
- }
- else
- {
- context->handleError(InvalidEnum()
- << "ANGLE_lossy_etc_decode extension is not supported.");
- return false;
- }
- break;
- case GL_DEPTH_COMPONENT:
- case GL_DEPTH_STENCIL_OES:
- if (!context->getExtensions().depthTextures)
- {
- context->handleError(InvalidValue());
- return false;
- }
- if (target != GL_TEXTURE_2D)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTargetAndFormat);
- return false;
- }
- // OES_depth_texture supports loading depth data and multiple levels,
- // but ANGLE_depth_texture does not
- if (pixels != nullptr)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), PixelDataNotNull);
- return false;
- }
- if (level != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), LevelNotZero);
- return false;
- }
- break;
- default:
- break;
- }
-
- if (!isSubImage)
- {
- switch (internalformat)
- {
- case GL_RGBA32F:
- if (!context->getExtensions().colorBufferFloatRGBA)
- {
- context->handleError(InvalidValue()
- << "Sized GL_RGBA32F internal format requires "
- "GL_CHROMIUM_color_buffer_float_rgba");
- return false;
- }
- if (type != GL_FLOAT)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- if (format != GL_RGBA)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
-
- case GL_RGB32F:
- if (!context->getExtensions().colorBufferFloatRGB)
- {
- context->handleError(InvalidValue()
- << "Sized GL_RGB32F internal format requires "
- "GL_CHROMIUM_color_buffer_float_rgb");
- return false;
- }
- if (type != GL_FLOAT)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- if (format != GL_RGB)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
- break;
-
- default:
- break;
- }
- }
-
- if (type == GL_FLOAT)
- {
- if (!context->getExtensions().textureFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- }
- else if (type == GL_HALF_FLOAT_OES)
- {
- if (!context->getExtensions().textureHalfFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- }
- }
-
- GLenum sizeCheckFormat = isSubImage ? format : internalformat;
- if (!ValidImageDataSize(context, target, width, height, 1, sizeCheckFormat, type, pixels,
- imageSize))
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateES2TexStorageParameters(Context *context,
- GLenum target,
- GLsizei levels,
- GLenum internalformat,
- GLsizei width,
- GLsizei height)
-{
- if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP &&
- target != GL_TEXTURE_RECTANGLE_ANGLE)
- {
- context->handleError(InvalidEnum());
- return false;
- }
-
- if (width < 1 || height < 1 || levels < 1)
- {
- context->handleError(InvalidValue());
- return false;
- }
-
- if (target == GL_TEXTURE_CUBE_MAP && width != height)
- {
- context->handleError(InvalidValue());
- return false;
- }
-
- if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1)
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- const gl::InternalFormat &formatInfo = gl::GetSizedInternalFormatInfo(internalformat);
- if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
- {
- context->handleError(InvalidEnum());
- return false;
- }
-
- const gl::Caps &caps = context->getCaps();
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
- static_cast<GLuint>(height) > caps.max2DTextureSize)
- {
- context->handleError(InvalidValue());
- return false;
- }
- break;
- case GL_TEXTURE_RECTANGLE_ANGLE:
- if (static_cast<GLuint>(width) > caps.maxRectangleTextureSize ||
- static_cast<GLuint>(height) > caps.maxRectangleTextureSize || levels != 1)
- {
- context->handleError(InvalidValue());
- return false;
- }
- if (formatInfo.compressed)
- {
- context->handleError(InvalidEnum()
- << "Rectangle texture cannot have a compressed format.");
- return false;
- }
- break;
- case GL_TEXTURE_CUBE_MAP:
- if (static_cast<GLuint>(width) > caps.maxCubeMapTextureSize ||
- static_cast<GLuint>(height) > caps.maxCubeMapTextureSize)
- {
- context->handleError(InvalidValue());
- return false;
- }
- break;
- default:
- context->handleError(InvalidEnum());
- return false;
- }
-
- if (levels != 1 && !context->getExtensions().textureNPOT)
- {
- if (!gl::isPow2(width) || !gl::isPow2(height))
- {
- context->handleError(InvalidOperation());
- return false;
- }
- }
-
- switch (internalformat)
- {
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
- if (!context->getExtensions().textureCompressionDXT1)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
- if (!context->getExtensions().textureCompressionDXT3)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
- if (!context->getExtensions().textureCompressionDXT5)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_ETC1_RGB8_OES:
- if (!context->getExtensions().compressedETC1RGB8Texture)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
- case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
- if (!context->getExtensions().lossyETCDecode)
- {
- context->handleError(InvalidEnum()
- << "ANGLE_lossy_etc_decode extension is not supported.");
- return false;
- }
- break;
- case GL_RGBA32F_EXT:
- case GL_RGB32F_EXT:
- case GL_ALPHA32F_EXT:
- case GL_LUMINANCE32F_EXT:
- case GL_LUMINANCE_ALPHA32F_EXT:
- if (!context->getExtensions().textureFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_RGBA16F_EXT:
- case GL_RGB16F_EXT:
- case GL_ALPHA16F_EXT:
- case GL_LUMINANCE16F_EXT:
- case GL_LUMINANCE_ALPHA16F_EXT:
- if (!context->getExtensions().textureHalfFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_R8_EXT:
- case GL_RG8_EXT:
- if (!context->getExtensions().textureRG)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_R16F_EXT:
- case GL_RG16F_EXT:
- if (!context->getExtensions().textureRG || !context->getExtensions().textureHalfFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_R32F_EXT:
- case GL_RG32F_EXT:
- if (!context->getExtensions().textureRG || !context->getExtensions().textureFloat)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- case GL_DEPTH_COMPONENT16:
- case GL_DEPTH_COMPONENT32_OES:
- case GL_DEPTH24_STENCIL8_OES:
- if (!context->getExtensions().depthTextures)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- if (target != GL_TEXTURE_2D)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- // ANGLE_depth_texture only supports 1-level textures
- if (levels != 1)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- break;
- default:
- break;
- }
-
- gl::Texture *texture = context->getTargetTexture(target);
- if (!texture || texture->id() == 0)
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- if (texture->getImmutableFormat())
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- return true;
-}
-
-bool ValidateDiscardFramebufferEXT(Context *context,
- GLenum target,
- GLsizei numAttachments,
- const GLenum *attachments)
-{
- if (!context->getExtensions().discardFramebuffer)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- bool defaultFramebuffer = false;
-
- switch (target)
- {
- case GL_FRAMEBUFFER:
- defaultFramebuffer =
- (context->getGLState().getTargetFramebuffer(GL_FRAMEBUFFER)->id() == 0);
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
- return false;
- }
-
- return ValidateDiscardFramebufferBase(context, target, numAttachments, attachments,
- defaultFramebuffer);
-}
-
-bool ValidateBindVertexArrayOES(Context *context, GLuint array)
-{
- if (!context->getExtensions().vertexArrayObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return ValidateBindVertexArrayBase(context, array);
-}
-
-bool ValidateDeleteVertexArraysOES(Context *context, GLsizei n, const GLuint *arrays)
-{
- if (!context->getExtensions().vertexArrayObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateGenVertexArraysOES(Context *context, GLsizei n, GLuint *arrays)
-{
- if (!context->getExtensions().vertexArrayObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateIsVertexArrayOES(Context *context, GLuint array)
-{
- if (!context->getExtensions().vertexArrayObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return true;
-}
-
-bool ValidateProgramBinaryOES(Context *context,
- GLuint program,
- GLenum binaryFormat,
- const void *binary,
- GLint length)
-{
- if (!context->getExtensions().getProgramBinary)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return ValidateProgramBinaryBase(context, program, binaryFormat, binary, length);
-}
-
-bool ValidateGetProgramBinaryOES(Context *context,
- GLuint program,
- GLsizei bufSize,
- GLsizei *length,
- GLenum *binaryFormat,
- void *binary)
-{
- if (!context->getExtensions().getProgramBinary)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return ValidateGetProgramBinaryBase(context, program, bufSize, length, binaryFormat, binary);
-}
-
-static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
-{
- switch (source)
- {
- case GL_DEBUG_SOURCE_API:
- case GL_DEBUG_SOURCE_SHADER_COMPILER:
- case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
- case GL_DEBUG_SOURCE_OTHER:
- // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
- return !mustBeThirdPartyOrApplication;
-
- case GL_DEBUG_SOURCE_THIRD_PARTY:
- case GL_DEBUG_SOURCE_APPLICATION:
- return true;
-
- default:
- return false;
- }
-}
-
-static bool ValidDebugType(GLenum type)
-{
- switch (type)
- {
- case GL_DEBUG_TYPE_ERROR:
- case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
- case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
- case GL_DEBUG_TYPE_PERFORMANCE:
- case GL_DEBUG_TYPE_PORTABILITY:
- case GL_DEBUG_TYPE_OTHER:
- case GL_DEBUG_TYPE_MARKER:
- case GL_DEBUG_TYPE_PUSH_GROUP:
- case GL_DEBUG_TYPE_POP_GROUP:
- return true;
-
- default:
- return false;
- }
-}
-
-static bool ValidDebugSeverity(GLenum severity)
-{
- switch (severity)
- {
- case GL_DEBUG_SEVERITY_HIGH:
- case GL_DEBUG_SEVERITY_MEDIUM:
- case GL_DEBUG_SEVERITY_LOW:
- case GL_DEBUG_SEVERITY_NOTIFICATION:
- return true;
-
- default:
- return false;
- }
-}
-
-bool ValidateDebugMessageControlKHR(Context *context,
- GLenum source,
- GLenum type,
- GLenum severity,
- GLsizei count,
- const GLuint *ids,
- GLboolean enabled)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
- return false;
- }
-
- if (!ValidDebugType(type) && type != GL_DONT_CARE)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
- return false;
- }
-
- if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSeverity);
- return false;
- }
-
- if (count > 0)
- {
- if (source == GL_DONT_CARE || type == GL_DONT_CARE)
- {
- context->handleError(
- InvalidOperation()
- << "If count is greater than zero, source and severity cannot be GL_DONT_CARE.");
- return false;
- }
-
- if (severity != GL_DONT_CARE)
- {
- context->handleError(
- InvalidOperation()
- << "If count is greater than zero, severity must be GL_DONT_CARE.");
- return false;
- }
- }
-
- return true;
-}
-
-bool ValidateDebugMessageInsertKHR(Context *context,
- GLenum source,
- GLenum type,
- GLuint id,
- GLenum severity,
- GLsizei length,
- const GLchar *buf)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (!context->getGLState().getDebug().isOutputEnabled())
- {
- // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
- // not generate an error.
- return false;
- }
-
- if (!ValidDebugSeverity(severity))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
- return false;
- }
-
- if (!ValidDebugType(type))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugType);
- return false;
- }
-
- if (!ValidDebugSource(source, true))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
- return false;
- }
-
- size_t messageLength = (length < 0) ? strlen(buf) : length;
- if (messageLength > context->getExtensions().maxDebugMessageLength)
- {
- context->handleError(InvalidValue()
- << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateDebugMessageCallbackKHR(Context *context,
- GLDEBUGPROCKHR callback,
- const void *userParam)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetDebugMessageLogKHR(Context *context,
- GLuint count,
- GLsizei bufSize,
- GLenum *sources,
- GLenum *types,
- GLuint *ids,
- GLenum *severities,
- GLsizei *lengths,
- GLchar *messageLog)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (bufSize < 0 && messageLog != nullptr)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- return true;
-}
-
-bool ValidatePushDebugGroupKHR(Context *context,
- GLenum source,
- GLuint id,
- GLsizei length,
- const GLchar *message)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (!ValidDebugSource(source, true))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidDebugSource);
- return false;
- }
-
- size_t messageLength = (length < 0) ? strlen(message) : length;
- if (messageLength > context->getExtensions().maxDebugMessageLength)
- {
- context->handleError(InvalidValue()
- << "Message length is larger than GL_MAX_DEBUG_MESSAGE_LENGTH.");
- return false;
- }
-
- size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
- if (currentStackSize >= context->getExtensions().maxDebugGroupStackDepth)
- {
- context
- ->handleError(StackOverflow()
- << "Cannot push more than GL_MAX_DEBUG_GROUP_STACK_DEPTH debug groups.");
- return false;
- }
-
- return true;
-}
-
-bool ValidatePopDebugGroupKHR(Context *context)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- size_t currentStackSize = context->getGLState().getDebug().getGroupStackDepth();
- if (currentStackSize <= 1)
- {
- context->handleError(StackUnderflow() << "Cannot pop the default debug group.");
- return false;
- }
-
- return true;
-}
-
-static bool ValidateObjectIdentifierAndName(Context *context, GLenum identifier, GLuint name)
-{
- switch (identifier)
- {
- case GL_BUFFER:
- if (context->getBuffer(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid buffer.");
- return false;
- }
- return true;
-
- case GL_SHADER:
- if (context->getShader(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid shader.");
- return false;
- }
- return true;
-
- case GL_PROGRAM:
- if (context->getProgram(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid program.");
- return false;
- }
- return true;
-
- case GL_VERTEX_ARRAY:
- if (context->getVertexArray(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid vertex array.");
- return false;
- }
- return true;
-
- case GL_QUERY:
- if (context->getQuery(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid query.");
- return false;
- }
- return true;
-
- case GL_TRANSFORM_FEEDBACK:
- if (context->getTransformFeedback(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid transform feedback.");
- return false;
- }
- return true;
-
- case GL_SAMPLER:
- if (context->getSampler(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid sampler.");
- return false;
- }
- return true;
-
- case GL_TEXTURE:
- if (context->getTexture(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid texture.");
- return false;
- }
- return true;
-
- case GL_RENDERBUFFER:
- if (context->getRenderbuffer(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid renderbuffer.");
- return false;
- }
- return true;
-
- case GL_FRAMEBUFFER:
- if (context->getFramebuffer(name) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid framebuffer.");
- return false;
- }
- return true;
-
- default:
- context->handleError(InvalidEnum() << "Invalid identifier.");
- return false;
- }
-}
-
-static bool ValidateLabelLength(Context *context, GLsizei length, const GLchar *label)
-{
- size_t labelLength = 0;
-
- if (length < 0)
- {
- if (label != nullptr)
- {
- labelLength = strlen(label);
- }
- }
- else
- {
- labelLength = static_cast<size_t>(length);
- }
-
- if (labelLength > context->getExtensions().maxLabelLength)
- {
- context->handleError(InvalidValue() << "Label length is larger than GL_MAX_LABEL_LENGTH.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateObjectLabelKHR(Context *context,
- GLenum identifier,
- GLuint name,
- GLsizei length,
- const GLchar *label)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (!ValidateObjectIdentifierAndName(context, identifier, name))
- {
- return false;
- }
-
- if (!ValidateLabelLength(context, length, label))
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetObjectLabelKHR(Context *context,
- GLenum identifier,
- GLuint name,
- GLsizei bufSize,
- GLsizei *length,
- GLchar *label)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (bufSize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- if (!ValidateObjectIdentifierAndName(context, identifier, name))
- {
- return false;
- }
-
- return true;
-}
-
-static bool ValidateObjectPtrName(Context *context, const void *ptr)
-{
- if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
- {
- context->handleError(InvalidValue() << "name is not a valid sync.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateObjectPtrLabelKHR(Context *context,
- const void *ptr,
- GLsizei length,
- const GLchar *label)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (!ValidateObjectPtrName(context, ptr))
- {
- return false;
- }
-
- if (!ValidateLabelLength(context, length, label))
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetObjectPtrLabelKHR(Context *context,
- const void *ptr,
- GLsizei bufSize,
- GLsizei *length,
- GLchar *label)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- if (bufSize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- if (!ValidateObjectPtrName(context, ptr))
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetPointervKHR(Context *context, GLenum pname, void **params)
-{
- if (!context->getExtensions().debug)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
- return false;
- }
-
- // TODO: represent this in Context::getQueryParameterInfo.
- switch (pname)
- {
- case GL_DEBUG_CALLBACK_FUNCTION:
- case GL_DEBUG_CALLBACK_USER_PARAM:
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBlitFramebufferANGLE(Context *context,
- GLint srcX0,
- GLint srcY0,
- GLint srcX1,
- GLint srcY1,
- GLint dstX0,
- GLint dstY0,
- GLint dstX1,
- GLint dstY1,
- GLbitfield mask,
- GLenum filter)
-{
- if (!context->getExtensions().framebufferBlit)
- {
- context->handleError(InvalidOperation() << "Blit extension not available.");
- return false;
- }
-
- if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
- {
- // TODO(jmadill): Determine if this should be available on other implementations.
- context->handleError(InvalidOperation() << "Scaling and flipping in "
- "BlitFramebufferANGLE not supported by this "
- "implementation.");
- return false;
- }
-
- if (filter == GL_LINEAR)
- {
- context->handleError(InvalidEnum() << "Linear blit not supported in this extension");
- return false;
- }
-
- Framebuffer *readFramebuffer = context->getGLState().getReadFramebuffer();
- Framebuffer *drawFramebuffer = context->getGLState().getDrawFramebuffer();
-
- if (mask & GL_COLOR_BUFFER_BIT)
- {
- const FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
- const FramebufferAttachment *drawColorAttachment = drawFramebuffer->getFirstColorbuffer();
-
- if (readColorAttachment && drawColorAttachment)
- {
- if (!(readColorAttachment->type() == GL_TEXTURE &&
- readColorAttachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
- readColorAttachment->type() != GL_RENDERBUFFER &&
- readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- for (size_t drawbufferIdx = 0;
- drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
- {
- const FramebufferAttachment *attachment =
- drawFramebuffer->getDrawBuffer(drawbufferIdx);
- if (attachment)
- {
- if (!(attachment->type() == GL_TEXTURE &&
- attachment->getTextureImageIndex().type == GL_TEXTURE_2D) &&
- attachment->type() != GL_RENDERBUFFER &&
- attachment->type() != GL_FRAMEBUFFER_DEFAULT)
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- // Return an error if the destination formats do not match
- if (!Format::EquivalentForBlit(attachment->getFormat(),
- readColorAttachment->getFormat()))
- {
- context->handleError(InvalidOperation());
- return false;
- }
- }
- }
-
- if (readFramebuffer->getSamples(context) != 0 &&
- IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
- srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
- {
- context->handleError(InvalidOperation());
- return false;
- }
- }
- }
-
- GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
- GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
- for (size_t i = 0; i < 2; i++)
- {
- if (mask & masks[i])
- {
- const FramebufferAttachment *readBuffer =
- readFramebuffer->getAttachment(attachments[i]);
- const FramebufferAttachment *drawBuffer =
- drawFramebuffer->getAttachment(attachments[i]);
-
- if (readBuffer && drawBuffer)
- {
- if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1))
- {
- // only whole-buffer copies are permitted
- context->handleError(InvalidOperation() << "Only whole-buffer depth and "
- "stencil blits are supported by "
- "this extension.");
- return false;
- }
-
- if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- }
- }
- }
-
- return ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, dstX0, dstY0,
- dstX1, dstY1, mask, filter);
-}
-
-bool ValidateClear(ValidationContext *context, GLbitfield mask)
-{
- Framebuffer *fbo = context->getGLState().getDrawFramebuffer();
- if (fbo->checkStatus(context) != GL_FRAMEBUFFER_COMPLETE)
- {
- context->handleError(InvalidFramebufferOperation());
- return false;
- }
-
- if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidClearMask);
- return false;
- }
-
- if (context->getExtensions().webglCompatibility && (mask & GL_COLOR_BUFFER_BIT) != 0)
- {
- constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
- GL_SIGNED_NORMALIZED};
-
- for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
- drawBufferIdx++)
- {
- if (!ValidateWebGLFramebufferAttachmentClearType(
- context, drawBufferIdx, validComponentTypes, ArraySize(validComponentTypes)))
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool ValidateDrawBuffersEXT(ValidationContext *context, GLsizei n, const GLenum *bufs)
-{
- if (!context->getExtensions().drawBuffers)
- {
- context->handleError(InvalidOperation() << "Extension not supported.");
- return false;
- }
-
- return ValidateDrawBuffersBase(context, n, bufs);
-}
-
-bool ValidateTexImage2D(Context *context,
- GLenum target,
- GLint level,
- GLint internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- const void *pixels)
-{
- if (context->getClientMajorVersion() < 3)
- {
- return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
- 0, 0, width, height, border, format, type, -1, pixels);
- }
-
- ASSERT(context->getClientMajorVersion() >= 3);
- return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
- 0, 0, width, height, 1, border, format, type, -1,
- pixels);
-}
-
-bool ValidateTexImage2DRobust(Context *context,
- GLenum target,
- GLint level,
- GLint internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLenum format,
- GLenum type,
- GLsizei bufSize,
- const void *pixels)
-{
- if (!ValidateRobustEntryPoint(context, bufSize))
- {
- return false;
- }
-
- if (context->getClientMajorVersion() < 3)
- {
- return ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
- 0, 0, width, height, border, format, type, bufSize,
- pixels);
- }
-
- ASSERT(context->getClientMajorVersion() >= 3);
- return ValidateES3TexImage2DParameters(context, target, level, internalformat, false, false, 0,
- 0, 0, width, height, 1, border, format, type, bufSize,
- pixels);
-}
-
-bool ValidateTexSubImage2D(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- const void *pixels)
-{
-
- if (context->getClientMajorVersion() < 3)
- {
- return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
- yoffset, width, height, 0, format, type, -1, pixels);
- }
-
- ASSERT(context->getClientMajorVersion() >= 3);
- return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
- yoffset, 0, width, height, 1, 0, format, type, -1,
- pixels);
-}
-
-bool ValidateTexSubImage2DRobustANGLE(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- GLsizei bufSize,
- const void *pixels)
-{
- if (!ValidateRobustEntryPoint(context, bufSize))
- {
- return false;
- }
-
- if (context->getClientMajorVersion() < 3)
- {
- return ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, xoffset,
- yoffset, width, height, 0, format, type, bufSize,
- pixels);
- }
-
- ASSERT(context->getClientMajorVersion() >= 3);
- return ValidateES3TexImage2DParameters(context, target, level, GL_NONE, false, true, xoffset,
- yoffset, 0, width, height, 1, 0, format, type, bufSize,
- pixels);
-}
-
-bool ValidateCompressedTexImage2D(Context *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLsizei imageSize,
- const void *data)
-{
- if (context->getClientMajorVersion() < 3)
- {
- if (!ValidateES2TexImageParameters(context, target, level, internalformat, true, false, 0,
- 0, width, height, border, GL_NONE, GL_NONE, -1, data))
- {
- return false;
- }
- }
- else
- {
- ASSERT(context->getClientMajorVersion() >= 3);
- if (!ValidateES3TexImage2DParameters(context, target, level, internalformat, true, false, 0,
- 0, 0, width, height, 1, border, GL_NONE, GL_NONE, -1,
- data))
- {
- return false;
- }
- }
-
- const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
- auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
- if (blockSizeOrErr.isError())
- {
- context->handleError(blockSizeOrErr.getError());
- return false;
- }
-
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), CompressedTextureDimensionsMustMatchData);
- return false;
- }
-
- if (target == GL_TEXTURE_RECTANGLE_ANGLE)
- {
- context->handleError(InvalidEnum() << "Rectangle texture cannot have a compressed format.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateCompressedTexImage2DRobustANGLE(Context *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- GLsizei width,
- GLsizei height,
- GLint border,
- GLsizei imageSize,
- GLsizei dataSize,
- const void *data)
-{
- if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
- {
- return false;
- }
-
- return ValidateCompressedTexImage2D(context, target, level, internalformat, width, height,
- border, imageSize, data);
-}
-bool ValidateCompressedTexSubImage2DRobustANGLE(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLsizei imageSize,
- GLsizei dataSize,
- const void *data)
-{
- if (!ValidateRobustCompressedTexImageBase(context, imageSize, dataSize))
- {
- return false;
- }
-
- return ValidateCompressedTexSubImage2D(context, target, level, xoffset, yoffset, width, height,
- format, imageSize, data);
-}
-
-bool ValidateCompressedTexSubImage2D(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLsizei imageSize,
- const void *data)
-{
- if (context->getClientMajorVersion() < 3)
- {
- if (!ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, xoffset,
- yoffset, width, height, 0, format, GL_NONE, -1, data))
- {
- return false;
- }
- }
- else
- {
- ASSERT(context->getClientMajorVersion() >= 3);
- if (!ValidateES3TexImage2DParameters(context, target, level, GL_NONE, true, true, xoffset,
- yoffset, 0, width, height, 1, 0, format, GL_NONE, -1,
- data))
- {
- return false;
- }
- }
-
- const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
- auto blockSizeOrErr = formatInfo.computeCompressedImageSize(gl::Extents(width, height, 1));
- if (blockSizeOrErr.isError())
- {
- context->handleError(blockSizeOrErr.getError());
- return false;
- }
-
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSizeOrErr.getResult())
- {
- context->handleError(InvalidValue());
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetBufferPointervOES(Context *context,
- BufferBinding target,
- GLenum pname,
- void **params)
-{
- return ValidateGetBufferPointervBase(context, target, pname, nullptr, params);
-}
-
-bool ValidateMapBufferOES(Context *context, BufferBinding target, GLenum access)
-{
- if (!context->getExtensions().mapBuffer)
- {
- context->handleError(InvalidOperation() << "Map buffer extension not available.");
- return false;
- }
-
- if (!ValidBufferType(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
- return false;
- }
-
- Buffer *buffer = context->getGLState().getTargetBuffer(target);
-
- if (buffer == nullptr)
- {
- context->handleError(InvalidOperation() << "Attempted to map buffer object zero.");
- return false;
- }
-
- if (access != GL_WRITE_ONLY_OES)
- {
- context->handleError(InvalidEnum() << "Non-write buffer mapping not supported.");
- return false;
- }
-
- if (buffer->isMapped())
- {
- context->handleError(InvalidOperation() << "Buffer is already mapped.");
- return false;
- }
-
- return ValidateMapBufferBase(context, target);
-}
-
-bool ValidateUnmapBufferOES(Context *context, BufferBinding target)
-{
- if (!context->getExtensions().mapBuffer)
- {
- context->handleError(InvalidOperation() << "Map buffer extension not available.");
- return false;
- }
-
- return ValidateUnmapBufferBase(context, target);
-}
-
-bool ValidateMapBufferRangeEXT(Context *context,
- BufferBinding target,
- GLintptr offset,
- GLsizeiptr length,
- GLbitfield access)
-{
- if (!context->getExtensions().mapBufferRange)
- {
- context->handleError(InvalidOperation() << "Map buffer range extension not available.");
- return false;
- }
-
- return ValidateMapBufferRangeBase(context, target, offset, length, access);
-}
-
-bool ValidateMapBufferBase(Context *context, BufferBinding target)
-{
- Buffer *buffer = context->getGLState().getTargetBuffer(target);
- ASSERT(buffer != nullptr);
-
- // Check if this buffer is currently being used as a transform feedback output buffer
- TransformFeedback *transformFeedback = context->getGLState().getCurrentTransformFeedback();
- if (transformFeedback != nullptr && transformFeedback->isActive())
- {
- for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
- {
- const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
- if (transformFeedbackBuffer.get() == buffer)
- {
- context->handleError(InvalidOperation()
- << "Buffer is currently bound for transform feedback.");
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool ValidateFlushMappedBufferRangeEXT(Context *context,
- BufferBinding target,
- GLintptr offset,
- GLsizeiptr length)
-{
- if (!context->getExtensions().mapBufferRange)
- {
- context->handleError(InvalidOperation() << "Map buffer range extension not available.");
- return false;
- }
-
- return ValidateFlushMappedBufferRangeBase(context, target, offset, length);
-}
-
-bool ValidateBindTexture(Context *context, GLenum target, GLuint texture)
-{
- Texture *textureObject = context->getTexture(texture);
- if (textureObject && textureObject->getTarget() != target && texture != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), TypeMismatch);
- return false;
- }
-
- if (!context->getGLState().isBindGeneratesResourceEnabled() &&
- !context->isTextureGenerated(texture))
- {
- context->handleError(InvalidOperation() << "Texture was not generated");
- return false;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- case GL_TEXTURE_CUBE_MAP:
- break;
-
- case GL_TEXTURE_RECTANGLE_ANGLE:
- if (!context->getExtensions().textureRectangle)
- {
- context->handleError(InvalidEnum()
- << "Context does not support GL_ANGLE_texture_rectangle");
- return false;
- }
- break;
-
- case GL_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY:
- if (context->getClientMajorVersion() < 3)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES3Required);
- return false;
- }
- break;
-
- case GL_TEXTURE_2D_MULTISAMPLE:
- if (context->getClientVersion() < Version(3, 1))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
- return false;
- }
- break;
-
- case GL_TEXTURE_EXTERNAL_OES:
- if (!context->getExtensions().eglImageExternal &&
- !context->getExtensions().eglStreamConsumerExternal)
- {
- context->handleError(InvalidEnum() << "External texture extension not enabled");
- return false;
- }
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBindUniformLocationCHROMIUM(Context *context,
- GLuint program,
- GLint location,
- const GLchar *name)
-{
- if (!context->getExtensions().bindUniformLocation)
- {
- context->handleError(InvalidOperation()
- << "GL_CHROMIUM_bind_uniform_location is not available.");
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return false;
- }
-
- if (location < 0)
- {
- context->handleError(InvalidValue() << "Location cannot be less than 0.");
- return false;
- }
-
- const Caps &caps = context->getCaps();
- if (static_cast<size_t>(location) >=
- (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
- {
- context->handleError(InvalidValue() << "Location must be less than "
- "(MAX_VERTEX_UNIFORM_VECTORS + "
- "MAX_FRAGMENT_UNIFORM_VECTORS) * 4");
- return false;
- }
-
- // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
- // shader-related entry points
- if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
- return false;
- }
-
- if (strncmp(name, "gl_", 3) == 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NameBeginsWithGL);
- return false;
- }
-
- return true;
-}
-
-bool ValidateCoverageModulationCHROMIUM(Context *context, GLenum components)
-{
- if (!context->getExtensions().framebufferMixedSamples)
- {
- context->handleError(InvalidOperation()
- << "GL_CHROMIUM_framebuffer_mixed_samples is not available.");
- return false;
- }
- switch (components)
- {
- case GL_RGB:
- case GL_RGBA:
- case GL_ALPHA:
- case GL_NONE:
- break;
- default:
- context->handleError(
- InvalidEnum()
- << "GLenum components is not one of GL_RGB, GL_RGBA, GL_ALPHA or GL_NONE.");
- return false;
- }
-
- return true;
-}
-
-// CHROMIUM_path_rendering
-
-bool ValidateMatrix(Context *context, GLenum matrixMode, const GLfloat *matrix)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
- return false;
- }
- if (matrix == nullptr)
- {
- context->handleError(InvalidOperation() << "Invalid matrix.");
- return false;
- }
- return true;
-}
-
-bool ValidateMatrixMode(Context *context, GLenum matrixMode)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (matrixMode != GL_PATH_MODELVIEW_CHROMIUM && matrixMode != GL_PATH_PROJECTION_CHROMIUM)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidMatrixMode);
- return false;
- }
- return true;
-}
-
-bool ValidateGenPaths(Context *context, GLsizei range)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- // range = 0 is undefined in NV_path_rendering.
- // we add stricter semantic check here and require a non zero positive range.
- if (range <= 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
- return false;
- }
-
- if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
- return false;
- }
-
- return true;
-}
-
-bool ValidateDeletePaths(Context *context, GLuint path, GLsizei range)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- // range = 0 is undefined in NV_path_rendering.
- // we add stricter semantic check here and require a non zero positive range.
- if (range <= 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidRange);
- return false;
- }
-
- angle::CheckedNumeric<std::uint32_t> checkedRange(path);
- checkedRange += range;
-
- if (!angle::IsValueInRangeForNumericType<std::uint32_t>(range) || !checkedRange.IsValid())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
- return false;
- }
- return true;
-}
-
-bool ValidatePathCommands(Context *context,
- GLuint path,
- GLsizei numCommands,
- const GLubyte *commands,
- GLsizei numCoords,
- GLenum coordType,
- const void *coords)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (!context->hasPath(path))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
- return false;
- }
-
- if (numCommands < 0)
- {
- context->handleError(InvalidValue() << "Invalid number of commands.");
- return false;
- }
- else if (numCommands > 0)
- {
- if (!commands)
- {
- context->handleError(InvalidValue() << "No commands array given.");
- return false;
- }
- }
-
- if (numCoords < 0)
- {
- context->handleError(InvalidValue() << "Invalid number of coordinates.");
- return false;
- }
- else if (numCoords > 0)
- {
- if (!coords)
- {
- context->handleError(InvalidValue() << "No coordinate array given.");
- return false;
- }
- }
-
- std::uint32_t coordTypeSize = 0;
- switch (coordType)
- {
- case GL_BYTE:
- coordTypeSize = sizeof(GLbyte);
- break;
-
- case GL_UNSIGNED_BYTE:
- coordTypeSize = sizeof(GLubyte);
- break;
-
- case GL_SHORT:
- coordTypeSize = sizeof(GLshort);
- break;
-
- case GL_UNSIGNED_SHORT:
- coordTypeSize = sizeof(GLushort);
- break;
-
- case GL_FLOAT:
- coordTypeSize = sizeof(GLfloat);
- break;
-
- default:
- context->handleError(InvalidEnum() << "Invalid coordinate type.");
- return false;
- }
-
- angle::CheckedNumeric<std::uint32_t> checkedSize(numCommands);
- checkedSize += (coordTypeSize * numCoords);
- if (!checkedSize.IsValid())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), IntegerOverflow);
- return false;
- }
-
- // early return skips command data validation when it doesn't exist.
- if (!commands)
- return true;
-
- GLsizei expectedNumCoords = 0;
- for (GLsizei i = 0; i < numCommands; ++i)
- {
- switch (commands[i])
- {
- case GL_CLOSE_PATH_CHROMIUM: // no coordinates.
- break;
- case GL_MOVE_TO_CHROMIUM:
- case GL_LINE_TO_CHROMIUM:
- expectedNumCoords += 2;
- break;
- case GL_QUADRATIC_CURVE_TO_CHROMIUM:
- expectedNumCoords += 4;
- break;
- case GL_CUBIC_CURVE_TO_CHROMIUM:
- expectedNumCoords += 6;
- break;
- case GL_CONIC_CURVE_TO_CHROMIUM:
- expectedNumCoords += 5;
- break;
- default:
- context->handleError(InvalidEnum() << "Invalid command.");
- return false;
- }
- }
- if (expectedNumCoords != numCoords)
- {
- context->handleError(InvalidValue() << "Invalid number of coordinates.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateSetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat value)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (!context->hasPath(path))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
- return false;
- }
-
- switch (pname)
- {
- case GL_PATH_STROKE_WIDTH_CHROMIUM:
- if (value < 0.0f)
- {
- context->handleError(InvalidValue() << "Invalid stroke width.");
- return false;
- }
- break;
- case GL_PATH_END_CAPS_CHROMIUM:
- switch (static_cast<GLenum>(value))
- {
- case GL_FLAT_CHROMIUM:
- case GL_SQUARE_CHROMIUM:
- case GL_ROUND_CHROMIUM:
- break;
- default:
- context->handleError(InvalidEnum() << "Invalid end caps.");
- return false;
- }
- break;
- case GL_PATH_JOIN_STYLE_CHROMIUM:
- switch (static_cast<GLenum>(value))
- {
- case GL_MITER_REVERT_CHROMIUM:
- case GL_BEVEL_CHROMIUM:
- case GL_ROUND_CHROMIUM:
- break;
- default:
- context->handleError(InvalidEnum() << "Invalid join style.");
- return false;
- }
- case GL_PATH_MITER_LIMIT_CHROMIUM:
- if (value < 0.0f)
- {
- context->handleError(InvalidValue() << "Invalid miter limit.");
- return false;
- }
- break;
-
- case GL_PATH_STROKE_BOUND_CHROMIUM:
- // no errors, only clamping.
- break;
-
- default:
- context->handleError(InvalidEnum() << "Invalid path parameter.");
- return false;
- }
- return true;
-}
-
-bool ValidateGetPathParameter(Context *context, GLuint path, GLenum pname, GLfloat *value)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- if (!context->hasPath(path))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
- return false;
- }
- if (!value)
- {
- context->handleError(InvalidValue() << "No value array.");
- return false;
- }
-
- switch (pname)
- {
- case GL_PATH_STROKE_WIDTH_CHROMIUM:
- case GL_PATH_END_CAPS_CHROMIUM:
- case GL_PATH_JOIN_STYLE_CHROMIUM:
- case GL_PATH_MITER_LIMIT_CHROMIUM:
- case GL_PATH_STROKE_BOUND_CHROMIUM:
- break;
-
- default:
- context->handleError(InvalidEnum() << "Invalid path parameter.");
- return false;
- }
-
- return true;
-}
-
-bool ValidatePathStencilFunc(Context *context, GLenum func, GLint ref, GLuint mask)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GEQUAL:
- case GL_GREATER:
- case GL_NOTEQUAL:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- return true;
-}
-
-// Note that the spec specifies that for the path drawing commands
-// if the path object is not an existing path object the command
-// does nothing and no error is generated.
-// However if the path object exists but has not been specified any
-// commands then an error is generated.
-
-bool ValidateStencilFillPath(Context *context, GLuint path, GLenum fillMode, GLuint mask)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (context->hasPath(path) && !context->hasPathData(path))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
- return false;
- }
-
- switch (fillMode)
- {
- case GL_COUNT_UP_CHROMIUM:
- case GL_COUNT_DOWN_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
- return false;
- }
-
- if (!isPow2(mask + 1))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilStrokePath(Context *context, GLuint path, GLint reference, GLuint mask)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (context->hasPath(path) && !context->hasPathData(path))
- {
- context->handleError(InvalidOperation() << "No such path or path has no data.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateCoverPath(Context *context, GLuint path, GLenum coverMode)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- if (context->hasPath(path) && !context->hasPathData(path))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NoSuchPath);
- return false;
- }
-
- switch (coverMode)
- {
- case GL_CONVEX_HULL_CHROMIUM:
- case GL_BOUNDING_BOX_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
- return false;
- }
- return true;
-}
-
-bool ValidateStencilThenCoverFillPath(Context *context,
- GLuint path,
- GLenum fillMode,
- GLuint mask,
- GLenum coverMode)
-{
- return ValidateStencilFillPath(context, path, fillMode, mask) &&
- ValidateCoverPath(context, path, coverMode);
-}
-
-bool ValidateStencilThenCoverStrokePath(Context *context,
- GLuint path,
- GLint reference,
- GLuint mask,
- GLenum coverMode)
-{
- return ValidateStencilStrokePath(context, path, reference, mask) &&
- ValidateCoverPath(context, path, coverMode);
-}
-
-bool ValidateIsPath(Context *context)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
- return true;
-}
-
-bool ValidateCoverFillPathInstanced(Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLenum coverMode,
- GLenum transformType,
- const GLfloat *transformValues)
-{
- if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
- transformType, transformValues))
- return false;
-
- switch (coverMode)
- {
- case GL_CONVEX_HULL_CHROMIUM:
- case GL_BOUNDING_BOX_CHROMIUM:
- case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
- return false;
- }
-
- return true;
-}
-
-bool ValidateCoverStrokePathInstanced(Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLenum coverMode,
- GLenum transformType,
- const GLfloat *transformValues)
-{
- if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
- transformType, transformValues))
- return false;
-
- switch (coverMode)
- {
- case GL_CONVEX_HULL_CHROMIUM:
- case GL_BOUNDING_BOX_CHROMIUM:
- case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilFillPathInstanced(Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLenum fillMode,
- GLuint mask,
- GLenum transformType,
- const GLfloat *transformValues)
-{
-
- if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
- transformType, transformValues))
- return false;
-
- switch (fillMode)
- {
- case GL_COUNT_UP_CHROMIUM:
- case GL_COUNT_DOWN_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
- return false;
- }
- if (!isPow2(mask + 1))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
- return false;
- }
- return true;
-}
-
-bool ValidateStencilStrokePathInstanced(Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLint reference,
- GLuint mask,
- GLenum transformType,
- const GLfloat *transformValues)
-{
- if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
- transformType, transformValues))
- return false;
-
- // no more validation here.
-
- return true;
-}
-
-bool ValidateStencilThenCoverFillPathInstanced(Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLenum fillMode,
- GLuint mask,
- GLenum coverMode,
- GLenum transformType,
- const GLfloat *transformValues)
-{
- if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
- transformType, transformValues))
- return false;
-
- switch (coverMode)
- {
- case GL_CONVEX_HULL_CHROMIUM:
- case GL_BOUNDING_BOX_CHROMIUM:
- case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
- return false;
- }
-
- switch (fillMode)
- {
- case GL_COUNT_UP_CHROMIUM:
- case GL_COUNT_DOWN_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFillMode);
- return false;
- }
- if (!isPow2(mask + 1))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidStencilBitMask);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilThenCoverStrokePathInstanced(Context *context,
- GLsizei numPaths,
- GLenum pathNameType,
- const void *paths,
- GLuint pathBase,
- GLint reference,
- GLuint mask,
- GLenum coverMode,
- GLenum transformType,
- const GLfloat *transformValues)
-{
- if (!ValidateInstancedPathParameters(context, numPaths, pathNameType, paths, pathBase,
- transformType, transformValues))
- return false;
-
- switch (coverMode)
- {
- case GL_CONVEX_HULL_CHROMIUM:
- case GL_BOUNDING_BOX_CHROMIUM:
- case GL_BOUNDING_BOX_OF_BOUNDING_BOXES_CHROMIUM:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCoverMode);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBindFragmentInputLocation(Context *context,
- GLuint program,
- GLint location,
- const GLchar *name)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- const GLint MaxLocation = context->getCaps().maxVaryingVectors * 4;
- if (location >= MaxLocation)
- {
- context->handleError(InvalidValue() << "Location exceeds max varying.");
- return false;
- }
-
- const auto *programObject = context->getProgram(program);
- if (!programObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
- return false;
- }
-
- if (!name)
- {
- context->handleError(InvalidValue() << "No name given.");
- return false;
- }
-
- if (angle::BeginsWith(name, "gl_"))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
- return false;
- }
-
- return true;
-}
-
-bool ValidateProgramPathFragmentInputGen(Context *context,
- GLuint program,
- GLint location,
- GLenum genMode,
- GLint components,
- const GLfloat *coeffs)
-{
- if (!context->getExtensions().pathRendering)
- {
- context->handleError(InvalidOperation() << "GL_CHROMIUM_path_rendering is not available.");
- return false;
- }
-
- const auto *programObject = context->getProgram(program);
- if (!programObject || programObject->isFlaggedForDeletion())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramDoesNotExist);
- return false;
- }
-
- if (!programObject->isLinked())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
- return false;
- }
-
- switch (genMode)
- {
- case GL_NONE:
- if (components != 0)
- {
- context->handleError(InvalidValue() << "Invalid components.");
- return false;
- }
- break;
-
- case GL_OBJECT_LINEAR_CHROMIUM:
- case GL_EYE_LINEAR_CHROMIUM:
- case GL_CONSTANT_CHROMIUM:
- if (components < 1 || components > 4)
- {
- context->handleError(InvalidValue() << "Invalid components.");
- return false;
- }
- if (!coeffs)
- {
- context->handleError(InvalidValue() << "No coefficients array given.");
- return false;
- }
- break;
-
- default:
- context->handleError(InvalidEnum() << "Invalid gen mode.");
- return false;
- }
-
- // If the location is -1 then the command is silently ignored
- // and no further validation is needed.
- if (location == -1)
- return true;
-
- const auto &binding = programObject->getFragmentInputBindingInfo(context, location);
-
- if (!binding.valid)
- {
- context->handleError(InvalidOperation() << "No such binding.");
- return false;
- }
-
- if (binding.type != GL_NONE)
- {
- GLint expectedComponents = 0;
- switch (binding.type)
- {
- case GL_FLOAT:
- expectedComponents = 1;
- break;
- case GL_FLOAT_VEC2:
- expectedComponents = 2;
- break;
- case GL_FLOAT_VEC3:
- expectedComponents = 3;
- break;
- case GL_FLOAT_VEC4:
- expectedComponents = 4;
- break;
- default:
- context->handleError(
- InvalidOperation()
- << "Fragment input type is not a floating point scalar or vector.");
- return false;
- }
- if (expectedComponents != components && genMode != GL_NONE)
- {
- context->handleError(InvalidOperation() << "Unexpected number of components");
- return false;
- }
- }
- return true;
-}
-
-bool ValidateCopyTextureCHROMIUM(Context *context,
- GLuint sourceId,
- GLint sourceLevel,
- GLenum destTarget,
- GLuint destId,
- GLint destLevel,
- GLint internalFormat,
- GLenum destType,
- GLboolean unpackFlipY,
- GLboolean unpackPremultiplyAlpha,
- GLboolean unpackUnmultiplyAlpha)
-{
- if (!context->getExtensions().copyTexture)
- {
- context->handleError(InvalidOperation()
- << "GL_CHROMIUM_copy_texture extension not available.");
- return false;
- }
-
- const Texture *source = context->getTexture(sourceId);
- if (source == nullptr)
- {
- context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
- return false;
- }
-
- if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
- {
- context->handleError(InvalidValue() << "Source texture a valid texture type.");
- return false;
- }
-
- GLenum sourceTarget = source->getTarget();
- ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
-
- if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
- {
- context->handleError(InvalidValue() << "Source texture level is not valid.");
- return false;
- }
-
- GLsizei sourceWidth = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
- GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
- if (sourceWidth == 0 || sourceHeight == 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
- return false;
- }
-
- const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
- if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
- {
- context->handleError(InvalidOperation() << "Source texture internal format is invalid.");
- return false;
- }
-
- if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- const Texture *dest = context->getTexture(destId);
- if (dest == nullptr)
- {
- context->handleError(InvalidValue()
- << "Destination texture is not a valid texture object.");
- return false;
- }
-
- if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
- {
- context->handleError(InvalidValue() << "Destination texture a valid texture type.");
- return false;
- }
-
- if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, sourceWidth,
- sourceHeight))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
- return false;
- }
-
- if (!IsValidCopyTextureDestinationFormatType(context, internalFormat, destType))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), MismatchedTypeAndFormat);
- return false;
- }
-
- if (IsCubeMapTextureTarget(destTarget) && sourceWidth != sourceHeight)
- {
- context->handleError(
- InvalidValue() << "Destination width and height must be equal for cube map textures.");
- return false;
- }
-
- if (dest->getImmutableFormat())
- {
- context->handleError(InvalidOperation() << "Destination texture is immutable.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateCopySubTextureCHROMIUM(Context *context,
- GLuint sourceId,
- GLint sourceLevel,
- GLenum destTarget,
- GLuint destId,
- GLint destLevel,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLboolean unpackFlipY,
- GLboolean unpackPremultiplyAlpha,
- GLboolean unpackUnmultiplyAlpha)
-{
- if (!context->getExtensions().copyTexture)
- {
- context->handleError(InvalidOperation()
- << "GL_CHROMIUM_copy_texture extension not available.");
- return false;
- }
-
- const Texture *source = context->getTexture(sourceId);
- if (source == nullptr)
- {
- context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
- return false;
- }
-
- if (!IsValidCopyTextureSourceTarget(context, source->getTarget()))
- {
- context->handleError(InvalidValue() << "Source texture a valid texture type.");
- return false;
- }
-
- GLenum sourceTarget = source->getTarget();
- ASSERT(sourceTarget != GL_TEXTURE_CUBE_MAP);
-
- if (!IsValidCopyTextureSourceLevel(context, source->getTarget(), sourceLevel))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidMipLevel);
- return false;
- }
-
- if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
- source->getHeight(sourceTarget, sourceLevel) == 0)
- {
- context->handleError(InvalidValue()
- << "The source level of the source texture must be defined.");
- return false;
- }
-
- if (x < 0 || y < 0)
- {
- context->handleError(InvalidValue() << "x and y cannot be negative.");
- return false;
- }
-
- if (width < 0 || height < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
- return false;
- }
-
- if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
- static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), SourceTextureTooSmall);
- return false;
- }
-
- const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
- if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidInternalFormat);
- return false;
- }
-
- if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- const Texture *dest = context->getTexture(destId);
- if (dest == nullptr)
- {
- context->handleError(InvalidValue()
- << "Destination texture is not a valid texture object.");
- return false;
- }
-
- if (!IsValidCopyTextureDestinationTarget(context, dest->getTarget(), destTarget))
- {
- context->handleError(InvalidValue() << "Destination texture a valid texture type.");
- return false;
- }
-
- if (!IsValidCopyTextureDestinationLevel(context, destTarget, destLevel, width, height))
- {
- context->handleError(InvalidValue() << "Destination texture level is not valid.");
- return false;
- }
-
- if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
- {
- context
- ->handleError(InvalidOperation()
- << "The destination level of the destination texture must be defined.");
- return false;
- }
-
- const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
- if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
- {
- context->handleError(InvalidOperation()
- << "Destination internal format and type combination is not valid.");
- return false;
- }
-
- if (xoffset < 0 || yoffset < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
- return false;
- }
-
- if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
- static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
- {
- context->handleError(InvalidValue() << "Destination texture not large enough to copy to.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateCompressedCopyTextureCHROMIUM(Context *context, GLuint sourceId, GLuint destId)
-{
- if (!context->getExtensions().copyCompressedTexture)
- {
- context->handleError(InvalidOperation()
- << "GL_CHROMIUM_copy_compressed_texture extension not available.");
- return false;
- }
-
- const gl::Texture *source = context->getTexture(sourceId);
- if (source == nullptr)
- {
- context->handleError(InvalidValue() << "Source texture is not a valid texture object.");
- return false;
- }
-
- if (source->getTarget() != GL_TEXTURE_2D)
- {
- context->handleError(InvalidValue() << "Source texture must be of type GL_TEXTURE_2D.");
- return false;
- }
-
- if (source->getWidth(GL_TEXTURE_2D, 0) == 0 || source->getHeight(GL_TEXTURE_2D, 0) == 0)
- {
- context->handleError(InvalidValue() << "Source texture must level 0 defined.");
- return false;
- }
-
- const gl::Format &sourceFormat = source->getFormat(GL_TEXTURE_2D, 0);
- if (!sourceFormat.info->compressed)
- {
- context->handleError(InvalidOperation()
- << "Source texture must have a compressed internal format.");
- return false;
- }
-
- const gl::Texture *dest = context->getTexture(destId);
- if (dest == nullptr)
- {
- context->handleError(InvalidValue()
- << "Destination texture is not a valid texture object.");
- return false;
- }
-
- if (dest->getTarget() != GL_TEXTURE_2D)
- {
- context->handleError(InvalidValue()
- << "Destination texture must be of type GL_TEXTURE_2D.");
- return false;
- }
-
- if (dest->getImmutableFormat())
- {
- context->handleError(InvalidOperation() << "Destination cannot be immutable.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateCreateShader(Context *context, GLenum type)
-{
- switch (type)
- {
- case GL_VERTEX_SHADER:
- case GL_FRAGMENT_SHADER:
- break;
-
- case GL_COMPUTE_SHADER:
- if (context->getClientVersion() < Version(3, 1))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), ES31Required);
- return false;
- }
- break;
-
- case GL_GEOMETRY_SHADER_EXT:
- if (!context->getExtensions().geometryShader)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
- return false;
- }
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBufferData(ValidationContext *context,
- BufferBinding target,
- GLsizeiptr size,
- const void *data,
- BufferUsage usage)
-{
- if (size < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
- return false;
- }
-
- switch (usage)
- {
- case BufferUsage::StreamDraw:
- case BufferUsage::StaticDraw:
- case BufferUsage::DynamicDraw:
- break;
-
- case BufferUsage::StreamRead:
- case BufferUsage::StaticRead:
- case BufferUsage::DynamicRead:
- case BufferUsage::StreamCopy:
- case BufferUsage::StaticCopy:
- case BufferUsage::DynamicCopy:
- if (context->getClientMajorVersion() < 3)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
- return false;
- }
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferUsage);
- return false;
- }
-
- if (!ValidBufferType(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
- return false;
- }
-
- Buffer *buffer = context->getGLState().getTargetBuffer(target);
-
- if (!buffer)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBufferSubData(ValidationContext *context,
- BufferBinding target,
- GLintptr offset,
- GLsizeiptr size,
- const void *data)
-{
- if (size < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
- return false;
- }
-
- if (offset < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeOffset);
- return false;
- }
-
- if (!ValidBufferType(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
- return false;
- }
-
- Buffer *buffer = context->getGLState().getTargetBuffer(target);
-
- if (!buffer)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), BufferNotBound);
- return false;
- }
-
- if (buffer->isMapped())
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- // Check for possible overflow of size + offset
- angle::CheckedNumeric<size_t> checkedSize(size);
- checkedSize += offset;
- if (!checkedSize.IsValid())
- {
- context->handleError(OutOfMemory());
- return false;
- }
-
- if (size + offset > buffer->getSize())
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InsufficientBufferSize);
- return false;
- }
-
- return true;
-}
-
-bool ValidateRequestExtensionANGLE(Context *context, const GLchar *name)
-{
- if (!context->getExtensions().requestExtension)
- {
- context->handleError(InvalidOperation() << "GL_ANGLE_request_extension is not available.");
- return false;
- }
-
- if (!context->isExtensionRequestable(name))
- {
- context->handleError(InvalidOperation() << "Extension " << name << " is not requestable.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateActiveTexture(ValidationContext *context, GLenum texture)
-{
- if (texture < GL_TEXTURE0 ||
- texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
- {
- context->handleError(InvalidEnum());
- return false;
- }
-
- return true;
-}
-
-bool ValidateAttachShader(ValidationContext *context, GLuint program, GLuint shader)
-{
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return false;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return false;
- }
-
- switch (shaderObject->getType())
- {
- case GL_VERTEX_SHADER:
- {
- if (programObject->getAttachedVertexShader())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
- return false;
- }
- break;
- }
- case GL_FRAGMENT_SHADER:
- {
- if (programObject->getAttachedFragmentShader())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
- return false;
- }
- break;
- }
- case GL_COMPUTE_SHADER:
- {
- if (programObject->getAttachedComputeShader())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
- return false;
- }
- break;
- }
- case GL_GEOMETRY_SHADER_EXT:
- {
- if (programObject->getAttachedGeometryShader())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderAttachmentHasShader);
- return false;
- }
- break;
- }
- default:
- UNREACHABLE();
- break;
- }
-
- return true;
-}
-
-bool ValidateBindAttribLocation(ValidationContext *context,
- GLuint program,
- GLuint index,
- const GLchar *name)
-{
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
- return false;
- }
-
- if (strncmp(name, "gl_", 3) == 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), NameBeginsWithGL);
- return false;
- }
-
- if (context->isWebGL())
- {
- const size_t length = strlen(name);
-
- if (!IsValidESSLString(name, length))
- {
- // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
- // for shader-related entry points
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
- return false;
- }
-
- if (!ValidateWebGLNameLength(context, length) || !ValidateWebGLNamePrefix(context, name))
- {
- return false;
- }
- }
-
- return GetValidProgram(context, program) != nullptr;
-}
-
-bool ValidateBindBuffer(ValidationContext *context, BufferBinding target, GLuint buffer)
-{
- if (!ValidBufferType(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBufferTypes);
- return false;
- }
-
- if (!context->getGLState().isBindGeneratesResourceEnabled() &&
- !context->isBufferGenerated(buffer))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBindFramebuffer(ValidationContext *context, GLenum target, GLuint framebuffer)
-{
- if (!ValidFramebufferTarget(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
- return false;
- }
-
- if (!context->getGLState().isBindGeneratesResourceEnabled() &&
- !context->isFramebufferGenerated(framebuffer))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBindRenderbuffer(ValidationContext *context, GLenum target, GLuint renderbuffer)
-{
- if (target != GL_RENDERBUFFER)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
- return false;
- }
-
- if (!context->getGLState().isBindGeneratesResourceEnabled() &&
- !context->isRenderbufferGenerated(renderbuffer))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ObjectNotGenerated);
- return false;
- }
-
- return true;
-}
-
-static bool ValidBlendEquationMode(const ValidationContext *context, GLenum mode)
-{
- switch (mode)
- {
- case GL_FUNC_ADD:
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- return true;
-
- case GL_MIN:
- case GL_MAX:
- return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinMax;
-
- default:
- return false;
- }
-}
-
-bool ValidateBlendColor(ValidationContext *context,
- GLfloat red,
- GLfloat green,
- GLfloat blue,
- GLfloat alpha)
-{
- return true;
-}
-
-bool ValidateBlendEquation(ValidationContext *context, GLenum mode)
-{
- if (!ValidBlendEquationMode(context, mode))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBlendEquationSeparate(ValidationContext *context, GLenum modeRGB, GLenum modeAlpha)
-{
- if (!ValidBlendEquationMode(context, modeRGB))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
- return false;
- }
-
- if (!ValidBlendEquationMode(context, modeAlpha))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendEquation);
- return false;
- }
-
- return true;
-}
-
-bool ValidateBlendFunc(ValidationContext *context, GLenum sfactor, GLenum dfactor)
-{
- return ValidateBlendFuncSeparate(context, sfactor, dfactor, sfactor, dfactor);
-}
-
-static bool ValidSrcBlendFunc(GLenum srcBlend)
-{
- switch (srcBlend)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- return true;
-
- default:
- return false;
- }
-}
-
-static bool ValidDstBlendFunc(GLenum dstBlend, GLint contextMajorVersion)
-{
- switch (dstBlend)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- return true;
-
- case GL_SRC_ALPHA_SATURATE:
- return (contextMajorVersion >= 3);
-
- default:
- return false;
- }
-}
-
-bool ValidateBlendFuncSeparate(ValidationContext *context,
- GLenum srcRGB,
- GLenum dstRGB,
- GLenum srcAlpha,
- GLenum dstAlpha)
-{
- if (!ValidSrcBlendFunc(srcRGB))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
- return false;
- }
-
- if (!ValidDstBlendFunc(dstRGB, context->getClientMajorVersion()))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
- return false;
- }
-
- if (!ValidSrcBlendFunc(srcAlpha))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
- return false;
- }
-
- if (!ValidDstBlendFunc(dstAlpha, context->getClientMajorVersion()))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidBlendFunction);
- return false;
- }
-
- if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
- context->getExtensions().webglCompatibility)
- {
- bool constantColorUsed =
- (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
- dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
-
- bool constantAlphaUsed =
- (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
- dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
-
- if (constantColorUsed && constantAlphaUsed)
- {
- const char *msg;
- if (context->getExtensions().webglCompatibility)
- {
- msg = kErrorInvalidConstantColor;
- }
- else
- {
- msg =
- "Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and "
- "GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR not supported by this "
- "implementation.";
- ERR() << msg;
- }
- context->handleError(InvalidOperation() << msg);
- return false;
- }
- }
-
- return true;
-}
-
-bool ValidateGetString(Context *context, GLenum name)
-{
- switch (name)
- {
- case GL_VENDOR:
- case GL_RENDERER:
- case GL_VERSION:
- case GL_SHADING_LANGUAGE_VERSION:
- case GL_EXTENSIONS:
- break;
-
- case GL_REQUESTABLE_EXTENSIONS_ANGLE:
- if (!context->getExtensions().requestExtension)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
- return false;
- }
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidName);
- return false;
- }
-
- return true;
-}
-
-bool ValidateLineWidth(ValidationContext *context, GLfloat width)
-{
- if (width <= 0.0f || isNaN(width))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidWidth);
- return false;
- }
-
- return true;
-}
-
-bool ValidateVertexAttribPointer(ValidationContext *context,
- GLuint index,
- GLint size,
- GLenum type,
- GLboolean normalized,
- GLsizei stride,
- const void *ptr)
-{
- if (!ValidateVertexFormatBase(context, index, size, type, false))
- {
- return false;
- }
-
- if (stride < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeStride);
- return false;
- }
-
- const Caps &caps = context->getCaps();
- if (context->getClientVersion() >= ES_3_1)
- {
- if (stride > caps.maxVertexAttribStride)
- {
- context->handleError(InvalidValue()
- << "stride cannot be greater than MAX_VERTEX_ATTRIB_STRIDE.");
- return false;
- }
-
- if (index >= caps.maxVertexAttribBindings)
- {
- context->handleError(InvalidValue()
- << "index must be smaller than MAX_VERTEX_ATTRIB_BINDINGS.");
- return false;
- }
- }
-
- // [OpenGL ES 3.0.2] Section 2.8 page 24:
- // An INVALID_OPERATION error is generated when a non-zero vertex array object
- // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
- // and the pointer argument is not NULL.
- bool nullBufferAllowed = context->getGLState().areClientArraysEnabled() &&
- context->getGLState().getVertexArray()->id() == 0;
- if (!nullBufferAllowed && context->getGLState().getTargetBuffer(BufferBinding::Array) == 0 &&
- ptr != nullptr)
- {
- context
- ->handleError(InvalidOperation()
- << "Client data cannot be used with a non-default vertex array object.");
- return false;
- }
-
- if (context->getExtensions().webglCompatibility)
- {
- // WebGL 1.0 [Section 6.14] Fixed point support
- // The WebGL API does not support the GL_FIXED data type.
- if (type == GL_FIXED)
- {
- context->handleError(InvalidEnum() << "GL_FIXED is not supported in WebGL.");
- return false;
- }
-
- if (!ValidateWebGLVertexAttribPointer(context, type, normalized, stride, ptr, false))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool ValidateDepthRangef(ValidationContext *context, GLfloat zNear, GLfloat zFar)
-{
- if (context->getExtensions().webglCompatibility && zNear > zFar)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidDepthRange);
- return false;
- }
-
- return true;
-}
-
-bool ValidateRenderbufferStorage(ValidationContext *context,
- GLenum target,
- GLenum internalformat,
- GLsizei width,
- GLsizei height)
-{
- return ValidateRenderbufferStorageParametersBase(context, target, 0, internalformat, width,
- height);
-}
-
-bool ValidateRenderbufferStorageMultisampleANGLE(ValidationContext *context,
- GLenum target,
- GLsizei samples,
- GLenum internalformat,
- GLsizei width,
- GLsizei height)
-{
- if (!context->getExtensions().framebufferMultisample)
- {
- context->handleError(InvalidOperation()
- << "GL_ANGLE_framebuffer_multisample not available");
- return false;
- }
-
- // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
- // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_OPERATION is
- // generated.
- if (static_cast<GLuint>(samples) > context->getCaps().maxSamples)
- {
- context->handleError(InvalidValue());
- return false;
- }
-
- // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
- // the specified storage. This is different than ES 3.0 in which a sample number higher
- // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
- // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
- if (context->getClientMajorVersion() >= 3)
- {
- const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
- if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
- {
- context->handleError(OutOfMemory());
- return false;
- }
- }
-
- return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat,
- width, height);
-}
-
-bool ValidateCheckFramebufferStatus(ValidationContext *context, GLenum target)
-{
- if (!ValidFramebufferTarget(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
- return false;
- }
-
- return true;
-}
-
-bool ValidateClearColor(ValidationContext *context,
- GLfloat red,
- GLfloat green,
- GLfloat blue,
- GLfloat alpha)
-{
- return true;
-}
-
-bool ValidateClearDepthf(ValidationContext *context, GLfloat depth)
-{
- return true;
-}
-
-bool ValidateClearStencil(ValidationContext *context, GLint s)
-{
- return true;
-}
-
-bool ValidateColorMask(ValidationContext *context,
- GLboolean red,
- GLboolean green,
- GLboolean blue,
- GLboolean alpha)
-{
- return true;
-}
-
-bool ValidateCompileShader(ValidationContext *context, GLuint shader)
-{
- return true;
-}
-
-bool ValidateCreateProgram(ValidationContext *context)
-{
- return true;
-}
-
-bool ValidateCullFace(ValidationContext *context, CullFaceMode mode)
-{
- switch (mode)
- {
- case CullFaceMode::Front:
- case CullFaceMode::Back:
- case CullFaceMode::FrontAndBack:
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidCullMode);
- return false;
- }
-
- return true;
-}
-
-bool ValidateDeleteProgram(ValidationContext *context, GLuint program)
-{
- if (program == 0)
- {
- return false;
- }
-
- if (!context->getProgram(program))
- {
- if (context->getShader(program))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
- return false;
- }
- else
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
- return false;
- }
- }
-
- return true;
-}
-
-bool ValidateDeleteShader(ValidationContext *context, GLuint shader)
-{
- if (shader == 0)
- {
- return false;
- }
-
- if (!context->getShader(shader))
- {
- if (context->getProgram(shader))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidShaderName);
- return false;
- }
- else
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), ExpectedShaderName);
- return false;
- }
- }
-
- return true;
-}
-
-bool ValidateDepthFunc(ValidationContext *context, GLenum func)
-{
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GREATER:
- case GL_GEQUAL:
- case GL_NOTEQUAL:
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidateDepthMask(ValidationContext *context, GLboolean flag)
-{
- return true;
-}
-
-bool ValidateDetachShader(ValidationContext *context, GLuint program, GLuint shader)
-{
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return false;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return false;
- }
-
- const Shader *attachedShader = nullptr;
-
- switch (shaderObject->getType())
- {
- case GL_VERTEX_SHADER:
- {
- attachedShader = programObject->getAttachedVertexShader();
- break;
- }
- case GL_FRAGMENT_SHADER:
- {
- attachedShader = programObject->getAttachedFragmentShader();
- break;
- }
- case GL_COMPUTE_SHADER:
- {
- attachedShader = programObject->getAttachedComputeShader();
- break;
- }
- case GL_GEOMETRY_SHADER_EXT:
- {
- attachedShader = programObject->getAttachedGeometryShader();
- break;
- }
- default:
- UNREACHABLE();
- return false;
- }
-
- if (attachedShader != shaderObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ShaderToDetachMustBeAttached);
- return false;
- }
-
- return true;
-}
-
-bool ValidateDisableVertexAttribArray(ValidationContext *context, GLuint index)
-{
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
- return false;
- }
-
- return true;
-}
-
-bool ValidateEnableVertexAttribArray(ValidationContext *context, GLuint index)
-{
- if (index >= MAX_VERTEX_ATTRIBS)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxVertexAttribute);
- return false;
- }
-
- return true;
-}
-
-bool ValidateFinish(ValidationContext *context)
-{
- return true;
-}
-
-bool ValidateFlush(ValidationContext *context)
-{
- return true;
-}
-
-bool ValidateFrontFace(ValidationContext *context, GLenum mode)
-{
- switch (mode)
- {
- case GL_CW:
- case GL_CCW:
- break;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetActiveAttrib(ValidationContext *context,
- GLuint program,
- GLuint index,
- GLsizei bufsize,
- GLsizei *length,
- GLint *size,
- GLenum *type,
- GLchar *name)
-{
- if (bufsize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return false;
- }
-
- if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetActiveUniform(ValidationContext *context,
- GLuint program,
- GLuint index,
- GLsizei bufsize,
- GLsizei *length,
- GLint *size,
- GLenum *type,
- GLchar *name)
-{
- if (bufsize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return false;
- }
-
- if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), IndexExceedsMaxActiveUniform);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetAttachedShaders(ValidationContext *context,
- GLuint program,
- GLsizei maxcount,
- GLsizei *count,
- GLuint *shaders)
-{
- if (maxcount < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeMaxCount);
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetAttribLocation(ValidationContext *context, GLuint program, const GLchar *name)
-{
- // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
- // shader-related entry points
- if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotBound);
- return false;
- }
-
- if (!programObject->isLinked())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetBooleanv(ValidationContext *context, GLenum pname, GLboolean *params)
-{
- GLenum nativeType;
- unsigned int numParams = 0;
- return ValidateStateQuery(context, pname, &nativeType, &numParams);
-}
-
-bool ValidateGetError(ValidationContext *context)
-{
- return true;
-}
-
-bool ValidateGetFloatv(ValidationContext *context, GLenum pname, GLfloat *params)
-{
- GLenum nativeType;
- unsigned int numParams = 0;
- return ValidateStateQuery(context, pname, &nativeType, &numParams);
-}
-
-bool ValidateGetIntegerv(ValidationContext *context, GLenum pname, GLint *params)
-{
- GLenum nativeType;
- unsigned int numParams = 0;
- return ValidateStateQuery(context, pname, &nativeType, &numParams);
-}
-
-bool ValidateGetProgramInfoLog(ValidationContext *context,
- GLuint program,
- GLsizei bufsize,
- GLsizei *length,
- GLchar *infolog)
-{
- if (bufsize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetShaderInfoLog(ValidationContext *context,
- GLuint shader,
- GLsizei bufsize,
- GLsizei *length,
- GLchar *infolog)
-{
- if (bufsize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetShaderPrecisionFormat(ValidationContext *context,
- GLenum shadertype,
- GLenum precisiontype,
- GLint *range,
- GLint *precision)
-{
- switch (shadertype)
- {
- case GL_VERTEX_SHADER:
- case GL_FRAGMENT_SHADER:
- break;
- case GL_COMPUTE_SHADER:
- context->handleError(InvalidOperation()
- << "compute shader precision not yet implemented.");
- return false;
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidShaderType);
- return false;
- }
-
- switch (precisiontype)
- {
- case GL_LOW_FLOAT:
- case GL_MEDIUM_FLOAT:
- case GL_HIGH_FLOAT:
- case GL_LOW_INT:
- case GL_MEDIUM_INT:
- case GL_HIGH_INT:
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidPrecision);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetShaderSource(ValidationContext *context,
- GLuint shader,
- GLsizei bufsize,
- GLsizei *length,
- GLchar *source)
-{
- if (bufsize < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeBufferSize);
- return false;
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetUniformLocation(ValidationContext *context, GLuint program, const GLchar *name)
-{
- if (strstr(name, "gl_") == name)
- {
- return false;
- }
-
- // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
- // shader-related entry points
- if (context->getExtensions().webglCompatibility && !IsValidESSLString(name, strlen(name)))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidNameCharacters);
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return false;
- }
-
- if (!programObject->isLinked())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
- return false;
- }
-
- return true;
-}
-
-bool ValidateHint(ValidationContext *context, GLenum target, GLenum mode)
-{
- switch (mode)
- {
- case GL_FASTEST:
- case GL_NICEST:
- case GL_DONT_CARE:
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- switch (target)
- {
- case GL_GENERATE_MIPMAP_HINT:
- break;
-
- case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
- if (context->getClientVersion() < ES_3_0 &&
- !context->getExtensions().standardDerivatives)
- {
- context->handleError(InvalidEnum() << "hint requires OES_standard_derivatives.");
- return false;
- }
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidateIsBuffer(ValidationContext *context, GLuint buffer)
-{
- return true;
-}
-
-bool ValidateIsFramebuffer(ValidationContext *context, GLuint framebuffer)
-{
- return true;
-}
-
-bool ValidateIsProgram(ValidationContext *context, GLuint program)
-{
- return true;
-}
-
-bool ValidateIsRenderbuffer(ValidationContext *context, GLuint renderbuffer)
-{
- return true;
-}
-
-bool ValidateIsShader(ValidationContext *context, GLuint shader)
-{
- return true;
-}
-
-bool ValidateIsTexture(ValidationContext *context, GLuint texture)
-{
- return true;
-}
-
-bool ValidatePixelStorei(ValidationContext *context, GLenum pname, GLint param)
-{
- if (context->getClientMajorVersion() < 3)
- {
- switch (pname)
- {
- case GL_UNPACK_IMAGE_HEIGHT:
- case GL_UNPACK_SKIP_IMAGES:
- context->handleError(InvalidEnum());
- return false;
-
- case GL_UNPACK_ROW_LENGTH:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
- if (!context->getExtensions().unpackSubimage)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
-
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- if (!context->getExtensions().packSubimage)
- {
- context->handleError(InvalidEnum());
- return false;
- }
- break;
- }
- }
-
- if (param < 0)
- {
- context->handleError(InvalidValue() << "Cannot use negative values in PixelStorei");
- return false;
- }
-
- switch (pname)
- {
- case GL_UNPACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
- return false;
- }
- break;
-
- case GL_PACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidUnpackAlignment);
- return false;
- }
- break;
-
- case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
- if (!context->getExtensions().packReverseRowOrder)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- }
- break;
-
- case GL_UNPACK_ROW_LENGTH:
- case GL_UNPACK_IMAGE_HEIGHT:
- case GL_UNPACK_SKIP_IMAGES:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidatePolygonOffset(ValidationContext *context, GLfloat factor, GLfloat units)
-{
- return true;
-}
-
-bool ValidateReleaseShaderCompiler(ValidationContext *context)
-{
- return true;
-}
-
-bool ValidateSampleCoverage(ValidationContext *context, GLfloat value, GLboolean invert)
-{
- return true;
-}
-
-bool ValidateScissor(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
-{
- if (width < 0 || height < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeSize);
- return false;
- }
-
- return true;
-}
-
-bool ValidateShaderBinary(ValidationContext *context,
- GLsizei n,
- const GLuint *shaders,
- GLenum binaryformat,
- const void *binary,
- GLsizei length)
-{
- const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
- if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
- shaderBinaryFormats.end())
- {
- context->handleError(InvalidEnum() << "Invalid shader binary format.");
- return false;
- }
-
- return true;
-}
-
-bool ValidateShaderSource(ValidationContext *context,
- GLuint shader,
- GLsizei count,
- const GLchar *const *string,
- const GLint *length)
-{
- if (count < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), NegativeCount);
- return false;
- }
-
- // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
- // shader-related entry points
- if (context->getExtensions().webglCompatibility)
- {
- for (GLsizei i = 0; i < count; i++)
- {
- size_t len =
- (length && length[i] >= 0) ? static_cast<size_t>(length[i]) : strlen(string[i]);
-
- // Backslash as line-continuation is allowed in WebGL 2.0.
- if (!IsValidESSLShaderSourceString(string[i], len,
- context->getClientVersion() >= ES_3_0))
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), ShaderSourceInvalidCharacters);
- return false;
- }
- }
- }
-
- Shader *shaderObject = GetValidShader(context, shader);
- if (!shaderObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilFunc(ValidationContext *context, GLenum func, GLint ref, GLuint mask)
-{
- if (!IsValidStencilFunc(func))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilFuncSeparate(ValidationContext *context,
- GLenum face,
- GLenum func,
- GLint ref,
- GLuint mask)
-{
- if (!IsValidStencilFace(face))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- if (!IsValidStencilFunc(func))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilMask(ValidationContext *context, GLuint mask)
-{
- return true;
-}
-
-bool ValidateStencilMaskSeparate(ValidationContext *context, GLenum face, GLuint mask)
-{
- if (!IsValidStencilFace(face))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilOp(ValidationContext *context, GLenum fail, GLenum zfail, GLenum zpass)
-{
- if (!IsValidStencilOp(fail))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- if (!IsValidStencilOp(zfail))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- if (!IsValidStencilOp(zpass))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- return true;
-}
-
-bool ValidateStencilOpSeparate(ValidationContext *context,
- GLenum face,
- GLenum fail,
- GLenum zfail,
- GLenum zpass)
-{
- if (!IsValidStencilFace(face))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidStencil);
- return false;
- }
-
- return ValidateStencilOp(context, fail, zfail, zpass);
-}
-
-bool ValidateUniform1f(ValidationContext *context, GLint location, GLfloat x)
-{
- return ValidateUniform(context, GL_FLOAT, location, 1);
-}
-
-bool ValidateUniform1fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
-{
- return ValidateUniform(context, GL_FLOAT, location, count);
-}
-
-bool ValidateUniform1i(ValidationContext *context, GLint location, GLint x)
-{
- return ValidateUniform1iv(context, location, 1, &x);
-}
-
-bool ValidateUniform2f(ValidationContext *context, GLint location, GLfloat x, GLfloat y)
-{
- return ValidateUniform(context, GL_FLOAT_VEC2, location, 1);
-}
-
-bool ValidateUniform2fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
-{
- return ValidateUniform(context, GL_FLOAT_VEC2, location, count);
-}
-
-bool ValidateUniform2i(ValidationContext *context, GLint location, GLint x, GLint y)
-{
- return ValidateUniform(context, GL_INT_VEC2, location, 1);
-}
-
-bool ValidateUniform2iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
-{
- return ValidateUniform(context, GL_INT_VEC2, location, count);
-}
-
-bool ValidateUniform3f(ValidationContext *context, GLint location, GLfloat x, GLfloat y, GLfloat z)
-{
- return ValidateUniform(context, GL_FLOAT_VEC3, location, 1);
-}
-
-bool ValidateUniform3fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
-{
- return ValidateUniform(context, GL_FLOAT_VEC3, location, count);
-}
-
-bool ValidateUniform3i(ValidationContext *context, GLint location, GLint x, GLint y, GLint z)
-{
- return ValidateUniform(context, GL_INT_VEC3, location, 1);
-}
-
-bool ValidateUniform3iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
-{
- return ValidateUniform(context, GL_INT_VEC3, location, count);
-}
-
-bool ValidateUniform4f(ValidationContext *context,
- GLint location,
- GLfloat x,
- GLfloat y,
- GLfloat z,
- GLfloat w)
-{
- return ValidateUniform(context, GL_FLOAT_VEC4, location, 1);
-}
-
-bool ValidateUniform4fv(ValidationContext *context, GLint location, GLsizei count, const GLfloat *v)
-{
- return ValidateUniform(context, GL_FLOAT_VEC4, location, count);
-}
-
-bool ValidateUniform4i(ValidationContext *context,
- GLint location,
- GLint x,
- GLint y,
- GLint z,
- GLint w)
-{
- return ValidateUniform(context, GL_INT_VEC4, location, 1);
-}
-
-bool ValidateUniform4iv(ValidationContext *context, GLint location, GLsizei count, const GLint *v)
-{
- return ValidateUniform(context, GL_INT_VEC4, location, count);
-}
-
-bool ValidateUniformMatrix2fv(ValidationContext *context,
- GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value)
-{
- return ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose);
-}
-
-bool ValidateUniformMatrix3fv(ValidationContext *context,
- GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value)
-{
- return ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose);
-}
-
-bool ValidateUniformMatrix4fv(ValidationContext *context,
- GLint location,
- GLsizei count,
- GLboolean transpose,
- const GLfloat *value)
-{
- return ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose);
-}
-
-bool ValidateValidateProgram(ValidationContext *context, GLuint program)
-{
- Program *programObject = GetValidProgram(context, program);
-
- if (!programObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateVertexAttrib1f(ValidationContext *context, GLuint index, GLfloat x)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib1fv(ValidationContext *context, GLuint index, const GLfloat *values)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib2f(ValidationContext *context, GLuint index, GLfloat x, GLfloat y)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib2fv(ValidationContext *context, GLuint index, const GLfloat *values)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib3f(ValidationContext *context,
- GLuint index,
- GLfloat x,
- GLfloat y,
- GLfloat z)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib3fv(ValidationContext *context, GLuint index, const GLfloat *values)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib4f(ValidationContext *context,
- GLuint index,
- GLfloat x,
- GLfloat y,
- GLfloat z,
- GLfloat w)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateVertexAttrib4fv(ValidationContext *context, GLuint index, const GLfloat *values)
-{
- return ValidateVertexAttribIndex(context, index);
-}
-
-bool ValidateViewport(ValidationContext *context, GLint x, GLint y, GLsizei width, GLsizei height)
-{
- if (width < 0 || height < 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), ViewportNegativeSize);
- return false;
- }
-
- return true;
-}
-
-bool ValidateDrawArrays(ValidationContext *context, GLenum mode, GLint first, GLsizei count)
-{
- return ValidateDrawArraysCommon(context, mode, first, count, 1);
-}
-
-bool ValidateDrawElements(ValidationContext *context,
- GLenum mode,
- GLsizei count,
- GLenum type,
- const void *indices)
-{
- return ValidateDrawElementsCommon(context, mode, count, type, indices, 1);
-}
-
-bool ValidateGetFramebufferAttachmentParameteriv(ValidationContext *context,
- GLenum target,
- GLenum attachment,
- GLenum pname,
- GLint *params)
-{
- return ValidateGetFramebufferAttachmentParameterivBase(context, target, attachment, pname,
- nullptr);
-}
-
-bool ValidateGetProgramiv(ValidationContext *context, GLuint program, GLenum pname, GLint *params)
-{
- return ValidateGetProgramivBase(context, program, pname, nullptr);
-}
-
-bool ValidateCopyTexImage2D(ValidationContext *context,
- GLenum target,
- GLint level,
- GLenum internalformat,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLint border)
-{
- if (context->getClientMajorVersion() < 3)
- {
- return ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, 0,
- 0, x, y, width, height, border);
- }
-
- ASSERT(context->getClientMajorVersion() == 3);
- return ValidateES3CopyTexImage2DParameters(context, target, level, internalformat, false, 0, 0,
- 0, x, y, width, height, border);
-}
-
-bool ValidateCopyTexSubImage2D(Context *context,
- GLenum target,
- GLint level,
- GLint xoffset,
- GLint yoffset,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height)
-{
- if (context->getClientMajorVersion() < 3)
- {
- return ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset,
- yoffset, x, y, width, height, 0);
- }
-
- return ValidateES3CopyTexImage2DParameters(context, target, level, GL_NONE, true, xoffset,
- yoffset, 0, x, y, width, height, 0);
-}
-
-bool ValidateDeleteBuffers(Context *context, GLint n, const GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateDeleteFramebuffers(Context *context, GLint n, const GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateDeleteRenderbuffers(Context *context, GLint n, const GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateDeleteTextures(Context *context, GLint n, const GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateDisable(Context *context, GLenum cap)
-{
- if (!ValidCap(context, cap, false))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidateEnable(Context *context, GLenum cap)
-{
- if (!ValidCap(context, cap, false))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- if (context->getLimitations().noSampleAlphaToCoverageSupport &&
- cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
- {
- const char *errorMessage = "Current renderer doesn't support alpha-to-coverage";
- context->handleError(InvalidOperation() << errorMessage);
-
- // We also output an error message to the debugger window if tracing is active, so that
- // developers can see the error message.
- ERR() << errorMessage;
- return false;
- }
-
- return true;
-}
-
-bool ValidateFramebufferRenderbuffer(Context *context,
- GLenum target,
- GLenum attachment,
- GLenum renderbuffertarget,
- GLuint renderbuffer)
-{
- if (!ValidFramebufferTarget(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidFramebufferTarget);
- return false;
- }
-
- if (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidRenderbufferTarget);
- return false;
- }
-
- return ValidateFramebufferRenderbufferParameters(context, target, attachment,
- renderbuffertarget, renderbuffer);
-}
-
-bool ValidateFramebufferTexture2D(Context *context,
- GLenum target,
- GLenum attachment,
- GLenum textarget,
- GLuint texture,
- GLint level)
-{
- // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
- // extension
- if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmap &&
- level != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidFramebufferTextureLevel);
- return false;
- }
-
- if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level))
- {
- return false;
- }
-
- if (texture != 0)
- {
- gl::Texture *tex = context->getTexture(texture);
- ASSERT(tex);
-
- const gl::Caps &caps = context->getCaps();
-
- switch (textarget)
- {
- case GL_TEXTURE_2D:
- {
- if (level > gl::log2(caps.max2DTextureSize))
- {
- context->handleError(InvalidValue());
- return false;
- }
- if (tex->getTarget() != GL_TEXTURE_2D)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), InvalidTextureTarget);
- return false;
- }
- }
- break;
-
- case GL_TEXTURE_RECTANGLE_ANGLE:
- {
- if (level != 0)
- {
- context->handleError(InvalidValue());
- return false;
- }
- if (tex->getTarget() != GL_TEXTURE_RECTANGLE_ANGLE)
- {
- context->handleError(InvalidOperation()
- << "Textarget must match the texture target type.");
- return false;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- if (level > gl::log2(caps.maxCubeMapTextureSize))
- {
- context->handleError(InvalidValue());
- return false;
- }
- if (tex->getTarget() != GL_TEXTURE_CUBE_MAP)
- {
- context->handleError(InvalidOperation()
- << "Textarget must match the texture target type.");
- return false;
- }
- }
- break;
-
- case GL_TEXTURE_2D_MULTISAMPLE:
- {
- if (context->getClientVersion() < ES_3_1)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ES31Required);
- return false;
- }
-
- if (level != 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), LevelNotZero);
- return false;
- }
- if (tex->getTarget() != GL_TEXTURE_2D_MULTISAMPLE)
- {
- context->handleError(InvalidOperation()
- << "Textarget must match the texture target type.");
- return false;
- }
- }
- break;
-
- default:
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- const Format &format = tex->getFormat(textarget, level);
- if (format.info->compressed)
- {
- context->handleError(InvalidOperation());
- return false;
- }
- }
-
- return true;
-}
-
-bool ValidateGenBuffers(Context *context, GLint n, GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateGenFramebuffers(Context *context, GLint n, GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateGenRenderbuffers(Context *context, GLint n, GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateGenTextures(Context *context, GLint n, GLuint *)
-{
- return ValidateGenOrDelete(context, n);
-}
-
-bool ValidateGenerateMipmap(Context *context, GLenum target)
-{
- if (!ValidTextureTarget(context, target))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), InvalidTextureTarget);
- return false;
- }
-
- Texture *texture = context->getTargetTexture(target);
-
- if (texture == nullptr)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotBound);
- return false;
- }
-
- const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
-
- // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
- // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
- if (effectiveBaseLevel >= gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- {
- context->handleError(InvalidOperation());
- return false;
- }
-
- GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
- const auto &format = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
- if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
- format.stencilBits > 0)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
- return false;
- }
-
- // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
- bool formatUnsized = !format.sized;
- bool formatColorRenderableAndFilterable =
- format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
- format.renderSupport(context->getClientVersion(), context->getExtensions());
- if (!formatUnsized && !formatColorRenderableAndFilterable)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
- return false;
- }
-
- // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
- // generation
- if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
- return false;
- }
-
- // ES3 and WebGL grant mipmap generation for sRGBA (with alpha) textures but GL_EXT_sRGB does
- // not.
- bool supportsSRGBMipmapGeneration =
- context->getClientVersion() >= ES_3_0 || context->getExtensions().webglCompatibility;
- if (!supportsSRGBMipmapGeneration && format.colorEncoding == GL_SRGB)
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), GenerateMipmapNotAllowed);
- return false;
- }
-
- // Non-power of 2 ES2 check
- if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNPOT &&
- (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
- !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
- {
- ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_RECTANGLE_ANGLE ||
- target == GL_TEXTURE_CUBE_MAP);
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), TextureNotPow2);
- return false;
- }
-
- // Cube completeness check
- if (target == GL_TEXTURE_CUBE_MAP && !texture->getTextureState().isCubeComplete())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), CubemapIncomplete);
- return false;
- }
-
- return true;
-}
-
-bool ValidateGetBufferParameteriv(ValidationContext *context,
- BufferBinding target,
- GLenum pname,
- GLint *params)
-{
- return ValidateGetBufferParameterBase(context, target, pname, false, nullptr);
-}
-
-bool ValidateGetRenderbufferParameteriv(Context *context,
- GLenum target,
- GLenum pname,
- GLint *params)
-{
- return ValidateGetRenderbufferParameterivBase(context, target, pname, nullptr);
-}
-
-bool ValidateGetShaderiv(Context *context, GLuint shader, GLenum pname, GLint *params)
-{
- return ValidateGetShaderivBase(context, shader, pname, nullptr);
-}
-
-bool ValidateGetTexParameterfv(Context *context, GLenum target, GLenum pname, GLfloat *params)
-{
- return ValidateGetTexParameterBase(context, target, pname, nullptr);
-}
-
-bool ValidateGetTexParameteriv(Context *context, GLenum target, GLenum pname, GLint *params)
-{
- return ValidateGetTexParameterBase(context, target, pname, nullptr);
-}
-
-bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat *params)
-{
- return ValidateGetUniformBase(context, program, location);
-}
-
-bool ValidateGetUniformiv(Context *context, GLuint program, GLint location, GLint *params)
-{
- return ValidateGetUniformBase(context, program, location);
-}
-
-bool ValidateGetVertexAttribfv(Context *context, GLuint index, GLenum pname, GLfloat *params)
-{
- return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
-}
-
-bool ValidateGetVertexAttribiv(Context *context, GLuint index, GLenum pname, GLint *params)
-{
- return ValidateGetVertexAttribBase(context, index, pname, nullptr, false, false);
-}
-
-bool ValidateGetVertexAttribPointerv(Context *context, GLuint index, GLenum pname, void **pointer)
-{
- return ValidateGetVertexAttribBase(context, index, pname, nullptr, true, false);
-}
-
-bool ValidateIsEnabled(Context *context, GLenum cap)
-{
- if (!ValidCap(context, cap, true))
- {
- ANGLE_VALIDATION_ERR(context, InvalidEnum(), EnumNotSupported);
- return false;
- }
-
- return true;
-}
-
-bool ValidateLinkProgram(Context *context, GLuint program)
-{
- if (context->hasActiveTransformFeedback(program))
- {
- // ES 3.0.4 section 2.15 page 91
- context->handleError(InvalidOperation() << "Cannot link program while program is "
- "associated with an active transform "
- "feedback object.");
- return false;
- }
-
- Program *programObject = GetValidProgram(context, program);
- if (!programObject)
- {
- return false;
- }
-
- return true;
-}
-
-bool ValidateReadPixels(Context *context,
- GLint x,
- GLint y,
- GLsizei width,
- GLsizei height,
- GLenum format,
- GLenum type,
- void *pixels)
-{
- return ValidateReadPixelsBase(context, x, y, width, height, format, type, -1, nullptr, nullptr,
- nullptr, pixels);
-}
-
-bool ValidateTexParameterf(Context *context, GLenum target, GLenum pname, GLfloat param)
-{
- return ValidateTexParameterBase(context, target, pname, -1, &param);
-}
-
-bool ValidateTexParameterfv(Context *context, GLenum target, GLenum pname, const GLfloat *params)
-{
- return ValidateTexParameterBase(context, target, pname, -1, params);
-}
-
-bool ValidateTexParameteri(Context *context, GLenum target, GLenum pname, GLint param)
-{
- return ValidateTexParameterBase(context, target, pname, -1, &param);
-}
-
-bool ValidateTexParameteriv(Context *context, GLenum target, GLenum pname, const GLint *params)
-{
- return ValidateTexParameterBase(context, target, pname, -1, params);
-}
-
-bool ValidateUseProgram(Context *context, GLuint program)
-{
- if (program != 0)
- {
- Program *programObject = context->getProgram(program);
- if (!programObject)
- {
- // ES 3.1.0 section 7.3 page 72
- if (context->getShader(program))
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExpectedProgramName);
- return false;
- }
- else
- {
- ANGLE_VALIDATION_ERR(context, InvalidValue(), InvalidProgramName);
- return false;
- }
- }
- if (!programObject->isLinked())
- {
- ANGLE_VALIDATION_ERR(context, InvalidOperation(), ProgramNotLinked);
- return false;
- }
- }
- if (context->getGLState().isTransformFeedbackActiveUnpaused())
- {
- // ES 3.0.4 section 2.15 page 91
- context
- ->handleError(InvalidOperation()
- << "Cannot change active program while transform feedback is unpaused.");
- return false;
- }
-
- return true;
-}
-
-} // namespace gl