//
// Copyright 2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/validationES2_autogen.h"

#include <cstdint>

#include "common/BinaryStream.h"
#include "common/angle_version_info.h"
#include "common/mathutil.h"
#include "common/span.h"
#include "common/string_utils.h"
#include "common/utilities.h"
#include "libANGLE/Context.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Fence.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/MemoryObject.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/validationES2.h"
#include "libANGLE/validationES32.h"
#include "libANGLE/validationES3_autogen.h"

using namespace angle;

namespace gl
{
using namespace err;

void RecordVersionErrorES20(const Context *context, angle::EntryPoint entryPoint)
{
    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointRequiresES20);
}

namespace
{

bool IsPartialBlit(const 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->getState().isScissorTestEnabled())
    {
        const Rectangle &scissor = context->getState().getScissor();
        return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
               scissor.height < writeSize.height;
    }

    return false;
}

bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
{
    // Table 1.1 from the CHROMIUM_copy_texture spec
    // No extension checks for the source formats because the texture has already been created and
    // passed validation.
    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:
        case GL_SRGB_ALPHA_EXT:
        case GL_G8_B8R8_2PLANE_420_UNORM_ANGLE:
        case GL_G8_B8_R8_3PLANE_420_UNORM_ANGLE:
        case GL_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16_ANGLE:
        case GL_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16_ANGLE:
        case GL_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16_ANGLE:
        case GL_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16_ANGLE:
        case GL_G16_B16R16_2PLANE_420_UNORM_ANGLE:
        case GL_G16_B16_R16_3PLANE_420_UNORM_ANGLE:
            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_ALPHA:
        case GL_BGRA_EXT:
        case GL_BGRA8_EXT:
        case GL_LUMINANCE:
        case GL_LUMINANCE_ALPHA:
        case GL_R11F_G11F_B10F:
        case GL_R16F:
        case GL_R32F:
        case GL_R8:
        case GL_R8UI:
        case GL_RG16F:
        case GL_RG32F:
        case GL_RG8:
        case GL_RG8UI:
        case GL_RGB:
        case GL_RGB10_A2:
        case GL_RGB16F:
        case GL_RGB32F:
        case GL_RGB565:
        case GL_RGB5_A1:
        case GL_RGB8:
        case GL_RGB8UI:
        case GL_RGB9_E5:
        case GL_RGBA:
        case GL_RGBA16F:
        case GL_RGBA32F:
        case GL_RGBA4:
        case GL_RGBA8:
        case GL_RGBA8UI:
        case GL_RGBX8_ANGLE:
        case GL_SRGB8:
        case GL_SRGB8_ALPHA8:
        case GL_SRGB_ALPHA_EXT:
        case GL_SRGB_EXT:
            return true;

        default:
            return false;
    }
}

bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
{
    return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
}

bool IsValidCopyTextureDestinationFormatType(const Context *context,
                                             angle::EntryPoint entryPoint,
                                             GLint internalFormat,
                                             GLenum type)
{
    if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
        return false;
    }

    if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
        return false;
    }

    const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
    if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
        return false;
    }

    return true;
}

bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target)
{
    switch (target)
    {
        case TextureTarget::_2D:
        case TextureTarget::CubeMapNegativeX:
        case TextureTarget::CubeMapNegativeY:
        case TextureTarget::CubeMapNegativeZ:
        case TextureTarget::CubeMapPositiveX:
        case TextureTarget::CubeMapPositiveY:
        case TextureTarget::CubeMapPositiveZ:
            return true;

        case TextureTarget::Rectangle:
            return context->getExtensions().textureRectangleANGLE;

        default:
            return false;
    }
}

bool IsValidCopyTextureDestinationTarget(const Context *context,
                                         TextureType textureType,
                                         TextureTarget target)
{
    return TextureTargetToType(target) == textureType;
}

bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type)
{
    switch (type)
    {
        case TextureType::_2D:
            return true;
        case TextureType::Rectangle:
            return context->getExtensions().textureRectangleANGLE;
        case TextureType::External:
            return context->getExtensions().EGLImageExternalOES;
        default:
            return false;
    }
}

bool IsValidCopyTextureSourceLevel(const Context *context,
                                   TextureType type,
                                   GLint level)
{
    return level == 0 || context->getClientVersion() >= ES_3_0;
}

bool IsValidCopyTextureDestinationLevel(const Context *context,
                                        TextureType type,
                                        GLint level,
                                        GLsizei width,
                                        GLsizei height)
{
    const Caps &caps = context->getCaps();
    switch (type)
    {
        case TextureType::_2D:
            return width <= (caps.max2DTextureSize >> level) &&
                   height <= (caps.max2DTextureSize >> level);
        case TextureType::Rectangle:
            ASSERT(level == 0);
            return width <= (caps.max2DTextureSize >> level) &&
                   height <= (caps.max2DTextureSize >> level);

        case TextureType::CubeMap:
            return width <= (caps.maxCubeMapTextureSize >> level) &&
                   height <= (caps.maxCubeMapTextureSize >> level);
        default:
            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;
    }
}

static inline bool Valid1to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
{
    return (context->getExtensions().textureFloatOES &&
            (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F ||
             format == GL_R32F)) ||
           (context->getExtensions().textureHalfFloatOES &&
            (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F ||
             format == GL_R16F));
}

static inline bool Valid2to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
{
    return (context->getExtensions().textureFloatOES &&
            (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F)) ||
           (context->getExtensions().textureHalfFloatOES &&
            (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F));
}

static inline bool Valid3to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
{
    return (context->getExtensions().textureFloatOES &&
            (format == GL_RGBA32F || format == GL_RGB32F)) ||
           (context->getExtensions().textureHalfFloatOES &&
            (format == GL_RGBA16F || format == GL_RGB16F));
}

static inline bool Valid4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
{
    return (context->getExtensions().textureFloatOES && format == GL_RGBA32F) ||
           (context->getExtensions().textureHalfFloatOES && format == GL_RGBA16F);
}

bool ValidateES2CopyTexImageParameters(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       TextureTarget 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_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    TextureType texType = TextureTargetToType(target);
    if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1,
                                  isSubImage))
    {
        // Error is already handled.
        return false;
    }

    Format textureFormat = Format::Invalid();
    if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
                                            isSubImage, xoffset, yoffset, 0, x, y, width, height,
                                            border, &textureFormat))
    {
        return false;
    }

    ASSERT(textureFormat.valid() || !isSubImage);

    const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
    GLenum colorbufferFormat =
        framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat;
    const auto &formatInfo = *textureFormat.info;

    // ValidateCopyTexImageParametersBase rejects compressed formats with GL_INVALID_OPERATION.
    ASSERT(!formatInfo.compressed);
    ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).compressed);

    // ValidateCopyTexImageParametersBase rejects depth formats with GL_INVALID_OPERATION.
    ASSERT(!formatInfo.depthBits);
    ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).depthBits);

    // [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_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT &&
                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    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_BGRA_EXT &&
                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    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_BGRA_EXT &&
                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    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_BGRA_EXT &&
                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    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_BGRA_EXT &&
                    colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT &&
                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    return false;
                }
                break;
            case GL_LUMINANCE_ALPHA:
            case GL_RGBA:
            case GL_BGRA_EXT:
                if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
                    colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT &&
                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    return false;
                }
                break;
            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                return false;
        }

        if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
            return false;
        }
    }
    else
    {
        switch (internalformat)
        {
            case GL_ALPHA:
            case GL_ALPHA8_OES:
                if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA_EXT &&
                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    return false;
                }
                break;
            case GL_LUMINANCE:
            case GL_LUMINANCE8_OES:
            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_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT &&
                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    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_BGRA_EXT &&
                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    return false;
                }
                break;
            case GL_RGB:
            case GL_RGB565_OES:
            case GL_RGB8_OES:
                if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
                    colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT &&
                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
                    !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    return false;
                }
                break;
            case GL_LUMINANCE_ALPHA:
            case GL_LUMINANCE4_ALPHA4_OES:
            case GL_LUMINANCE8_ALPHA8_OES:
            case GL_RGBA:
            case GL_BGRA_EXT:
            case GL_RGBA4_OES:
            case GL_RGB5_A1_OES:
            case GL_RGBA8_OES:
                if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
                    colorbufferFormat != GL_BGRA_EXT && colorbufferFormat != GL_BGRA8_EXT &&
                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
                    colorbufferFormat != GL_RGBA16F &&
                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
                    return false;
                }
                break;
            default:
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, internalformat);
                return false;
        }
    }

    return true;
}

// ANGLE_shader_pixel_local_storage: INVALID_OPERATION is generated by Enable(), Disable() if <cap>
// is not one of: CULL_FACE, DEBUG_OUTPUT, DEBUG_OUTPUT_SYNCHRONOUS, DEPTH_CLAMP_EXT, DEPTH_TEST,
// POLYGON_OFFSET_FILL, PRIMITIVE_RESTART_FIXED_INDEX, SCISSOR_TEST, SCISSOR_TEST_EXCLUSIVE_NV,
// STENCIL_TEST, CLIP_DISTANCE[0..7]_EXT
static bool IsCapBannedWithActivePLS(GLenum cap)
{
    switch (cap)
    {
        case GL_BLEND:
        case GL_CULL_FACE:
        case GL_DEBUG_OUTPUT:
        case GL_DEBUG_OUTPUT_SYNCHRONOUS:
        case GL_DEPTH_CLAMP_EXT:
        case GL_DEPTH_TEST:
        case GL_POLYGON_OFFSET_POINT_NV:
        case GL_POLYGON_OFFSET_LINE_NV:  // = GL_POLYGON_OFFSET_LINE_ANGLE
        case GL_POLYGON_OFFSET_FILL:
        case GL_PRIMITIVE_RESTART_FIXED_INDEX:
        case GL_RASTERIZER_DISCARD:
        case GL_SCISSOR_TEST:
        case GL_SCISSOR_TEST_EXCLUSIVE_NV:
        case GL_STENCIL_TEST:
        case GL_CLIP_DISTANCE0_EXT:
        case GL_CLIP_DISTANCE1_EXT:
        case GL_CLIP_DISTANCE2_EXT:
        case GL_CLIP_DISTANCE3_EXT:
        case GL_CLIP_DISTANCE4_EXT:
        case GL_CLIP_DISTANCE5_EXT:
        case GL_CLIP_DISTANCE6_EXT:
        case GL_CLIP_DISTANCE7_EXT:
            return false;
        default:
            return true;
    }
}

bool ValidCapUncommon(const PrivateState &state, ErrorSet *errors, GLenum cap, bool queryOnly)
{
    switch (cap)
    {
        // EXT_multisample_compatibility
        case GL_MULTISAMPLE_EXT:
        case GL_SAMPLE_ALPHA_TO_ONE_EXT:
            return state.getExtensions().multisampleCompatibilityEXT;

        case GL_SAMPLE_ALPHA_TO_COVERAGE:
        case GL_SAMPLE_COVERAGE:
        case GL_DITHER:
            return true;

        case GL_POLYGON_OFFSET_POINT_NV:
            return state.getExtensions().polygonModeNV;
        case GL_POLYGON_OFFSET_LINE_NV:  // = GL_POLYGON_OFFSET_LINE_ANGLE
            return state.getExtensions().polygonModeAny();

        case GL_DEPTH_CLAMP_EXT:
            return state.getExtensions().depthClampEXT;

        case GL_PRIMITIVE_RESTART_FIXED_INDEX:
        case GL_RASTERIZER_DISCARD:
            return state.getClientVersion() >= ES_3_0;

        case GL_DEBUG_OUTPUT_SYNCHRONOUS:
        case GL_DEBUG_OUTPUT:
            return state.getExtensions().debugKHR;

        case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
            return queryOnly && state.getExtensions().bindGeneratesResourceCHROMIUM;

        case GL_CLIENT_ARRAYS_ANGLE:
            return queryOnly && state.getExtensions().clientArraysANGLE;

        case GL_FRAMEBUFFER_SRGB_EXT:
            return state.getExtensions().sRGBWriteControlEXT;

        case GL_SAMPLE_MASK:
            return state.getClientVersion() >= Version(3, 1) ||
                   state.getExtensions().textureMultisampleANGLE;

        case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
            return queryOnly && state.getExtensions().robustResourceInitializationANGLE;

        case GL_TEXTURE_RECTANGLE_ANGLE:
            return state.isWebGL();

        // GL_APPLE_clip_distance / GL_EXT_clip_cull_distance / GL_ANGLE_clip_cull_distance
        case GL_CLIP_DISTANCE0_EXT:
        case GL_CLIP_DISTANCE1_EXT:
        case GL_CLIP_DISTANCE2_EXT:
        case GL_CLIP_DISTANCE3_EXT:
        case GL_CLIP_DISTANCE4_EXT:
        case GL_CLIP_DISTANCE5_EXT:
        case GL_CLIP_DISTANCE6_EXT:
        case GL_CLIP_DISTANCE7_EXT:
            if (state.getExtensions().clipDistanceAPPLE ||
                state.getExtensions().clipCullDistanceAny())
            {
                return true;
            }
            break;
        case GL_SAMPLE_SHADING:
            return state.getExtensions().sampleShadingOES;
        case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
            return state.getExtensions().shadingRateQCOM;

        // COLOR_LOGIC_OP is in GLES1, but exposed through an ANGLE extension.
        case GL_COLOR_LOGIC_OP:
            return state.getClientVersion() < Version(2, 0) || state.getExtensions().logicOpANGLE;

        case GL_FETCH_PER_SAMPLE_ARM:
            return state.getExtensions().shaderFramebufferFetchARM;

        case GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM:
            return queryOnly && state.getExtensions().shaderFramebufferFetchARM;

        case GL_BLEND_ADVANCED_COHERENT_KHR:
            return state.getExtensions().blendEquationAdvancedCoherentKHR;

        default:
            break;
    }

    // GLES1 emulation: GLES1-specific caps after this point
    if (state.getClientVersion() >= ES_2_0)
    {
        return false;
    }

    switch (cap)
    {
        case GL_ALPHA_TEST:
        case GL_VERTEX_ARRAY:
        case GL_NORMAL_ARRAY:
        case GL_COLOR_ARRAY:
        case GL_TEXTURE_COORD_ARRAY:
        case GL_TEXTURE_2D:
        case GL_LIGHTING:
        case GL_LIGHT0:
        case GL_LIGHT1:
        case GL_LIGHT2:
        case GL_LIGHT3:
        case GL_LIGHT4:
        case GL_LIGHT5:
        case GL_LIGHT6:
        case GL_LIGHT7:
        case GL_NORMALIZE:
        case GL_RESCALE_NORMAL:
        case GL_COLOR_MATERIAL:
        case GL_CLIP_PLANE0:
        case GL_CLIP_PLANE1:
        case GL_CLIP_PLANE2:
        case GL_CLIP_PLANE3:
        case GL_CLIP_PLANE4:
        case GL_CLIP_PLANE5:
        case GL_FOG:
        case GL_POINT_SMOOTH:
        case GL_LINE_SMOOTH:
            return state.getClientVersion() < Version(2, 0);
        case GL_POINT_SIZE_ARRAY_OES:
            return state.getClientVersion() < Version(2, 0) &&
                   state.getExtensions().pointSizeArrayOES;
        case GL_TEXTURE_CUBE_MAP:
            return state.getClientVersion() < Version(2, 0) &&
                   state.getExtensions().textureCubeMapOES;
        case GL_POINT_SPRITE_OES:
            return state.getClientVersion() < Version(2, 0) && state.getExtensions().pointSpriteOES;
        default:
            return false;
    }
}

ANGLE_INLINE bool ValidCap(const PrivateState &state, ErrorSet *errors, GLenum cap, bool queryOnly)
{
    // Most frequent cases inline.
    if (ANGLE_LIKELY(cap == GL_BLEND || cap == GL_DEPTH_TEST || cap == GL_SCISSOR_TEST ||
                     cap == GL_STENCIL_TEST || cap == GL_CULL_FACE ||
                     cap == GL_POLYGON_OFFSET_FILL))
    {
        return true;
    }
    // Other less common cases are a function call.
    return ValidCapUncommon(state, errors, cap, queryOnly);
}

// 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 ValidateWebGLName(const Context *context, angle::EntryPoint entryPoint, const char *name)
{
    ASSERT(context->isWebGL());
    const bool isWebGL1 = context->getClientVersion() < ES_3_0;

    // WebGL imposes a limit on the lengths of uniform and attribute locations.
    const size_t maxLength = isWebGL1 ? 256 : 1024;
    const size_t length    = strlen(name);

    // Do not validate uniform name length because Chromium may pass longer
    // strings than allowed in WebGL during its internal operations.
    if (entryPoint != angle::EntryPoint::GLBindUniformLocationCHROMIUM &&
        entryPoint != angle::EntryPoint::GLGetUniformLocation && length > maxLength)
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kWebGLNameLengthLimitExceeded,
                                static_cast<int>(maxLength));
        return false;
    }

    // WebGL disallows strings containing invalid ESSL characters.
    if (!IsValidESSLString(name, length))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidNameCharacters);
        return false;
    }

    return true;
}

bool ValidateSrcBlendFunc(const PrivateState &state,
                          ErrorSet *errors,
                          angle::EntryPoint entryPoint,
                          GLenum val)
{
    switch (val)
    {
        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;

        // EXT_blend_func_extended, excluding GL_SRC_ALPHA_SATURATE_EXT, which equals
        // GL_SRC_ALPHA_SATURATE and is handled above.
        case GL_SRC1_COLOR_EXT:
        case GL_SRC1_ALPHA_EXT:
        case GL_ONE_MINUS_SRC1_COLOR_EXT:
        case GL_ONE_MINUS_SRC1_ALPHA_EXT:
            if (!state.getExtensions().blendFuncExtendedEXT)
            {
                break;
            }
            if (state.getPixelLocalStorageActivePlanes() != 0)
            {
                // INVALID_OPERATION is generated by BlendFunc*() if <srcRGB>, <dstRGB>, <srcAlpha>,
                // or <dstAlpha> is a blend function requiring the secondary color input, as
                // specified in EXT_blend_func_extended (SRC1_COLOR_EXT, ONE_MINUS_SRC1_COLOR_EXT,
                // SRC1_ALPHA_EXT, ONE_MINUS_SRC1_ALPHA_EXT).
                errors->validationError(entryPoint, GL_INVALID_OPERATION,
                                        kPLSSecondaryBlendNotSupported);
                return false;
            }
            return true;
    }

    errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
    return false;
}

bool ValidateDstBlendFunc(const PrivateState &state,
                          ErrorSet *errors,
                          angle::EntryPoint entryPoint,
                          GLenum val)
{
    if (val == GL_SRC_ALPHA_SATURATE)
    {
        // Unextended ES2 does not allow GL_SRC_ALPHA_SATURATE as a dst blend func.
        if (state.getClientVersion() < ES_3_0 && !state.getExtensions().blendFuncExtendedEXT)
        {
            errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
            return false;
        }
    }

    return ValidateSrcBlendFunc(state, errors, entryPoint, val);
}

bool ValidateES2TexImageParameters(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   TextureTarget target,
                                   GLint level,
                                   GLenum internalformat,
                                   bool isSubImage,
                                   GLint xoffset,
                                   GLint yoffset,
                                   GLsizei width,
                                   GLsizei height,
                                   GLint border,
                                   GLenum format,
                                   GLenum type,
                                   const void *pixels,
                                   GLuint *outImageSize)
{
    if (!ValidTexture2DDestinationTarget(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    TextureType texType = TextureTargetToType(target);
    if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1,
                                  isSubImage))
    {
        // Error already handled.
        return false;
    }

    if ((xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width) ||
        (yoffset < 0 || std::numeric_limits<GLsizei>::max() - yoffset < height))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
        return false;
    }

    const Caps &caps = context->getCaps();

    switch (texType)
    {
        case TextureType::_2D:
            if (width > (caps.max2DTextureSize >> level) ||
                height > (caps.max2DTextureSize >> level))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
                return false;
            }
            break;

        case TextureType::Rectangle:
            ASSERT(level == 0);
            if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
                return false;
            }
            break;

        case TextureType::CubeMap:
            if (!isSubImage && width != height)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
                return false;
            }

            if (width > (caps.maxCubeMapTextureSize >> level) ||
                height > (caps.maxCubeMapTextureSize >> level))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
            return false;
    }

    Texture *texture = context->getTextureByType(texType);
    if (!texture)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
        return false;
    }

    // Pixel local storage isn't supported on ES2.
    ASSERT(!context->getState().isTextureBoundToActivePLS(texture->id()));

    // Verify zero border
    if (border != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBorder);
        return false;
    }

    bool nonEqualFormatsAllowed = false;

    {
        // 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:
                break;
            case GL_HALF_FLOAT_OES:
                if (!context->getExtensions().textureHalfFloatOES)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, type);
                    return false;
                }
                break;
            case GL_FLOAT:
                if (!context->getExtensions().textureFloatOES)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, type);
                    return false;
                }
                break;
            case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
                if (!context->getExtensions().textureType2101010REVEXT)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, type);
                    return false;
                }
                break;
            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
                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_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            case GL_RED:
            case GL_RG:
                if (!context->getExtensions().textureRgEXT)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, format);
                    return false;
                }
                switch (type)
                {
                    case GL_UNSIGNED_BYTE:
                        break;
                    case GL_FLOAT:
                        if (!context->getExtensions().textureFloatOES)
                        {
                            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, type);
                            return false;
                        }
                        break;
                    case GL_HALF_FLOAT_OES:
                        if (!context->getExtensions().textureFloatOES &&
                            !context->getExtensions().textureHalfFloatOES)
                        {
                            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, type);
                            return false;
                        }
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            case GL_RGB:
                switch (type)
                {
                    case GL_UNSIGNED_BYTE:
                    case GL_UNSIGNED_SHORT_5_6_5:
                    case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
                    case GL_FLOAT:
                    case GL_HALF_FLOAT_OES:
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        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:
                    case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            case GL_BGRA_EXT:
                if (!context->getExtensions().textureFormatBGRA8888EXT)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, format);
                    return false;
                }
                switch (type)
                {
                    case GL_UNSIGNED_BYTE:
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            case GL_SRGB_EXT:
            case GL_SRGB_ALPHA_EXT:
                if (!context->getExtensions().sRGBEXT)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, format);
                    return false;
                }
                switch (type)
                {
                    case GL_UNSIGNED_BYTE:
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            case GL_DEPTH_COMPONENT:
                switch (type)
                {
                    case GL_UNSIGNED_SHORT:
                    case GL_UNSIGNED_INT:
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            case GL_DEPTH_STENCIL_OES:
                switch (type)
                {
                    case GL_UNSIGNED_INT_24_8_OES:
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                }
                break;
            default:
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, format);
                return false;
        }

        switch (format)
        {
            case GL_DEPTH_COMPONENT:
            case GL_DEPTH_STENCIL_OES:
                if (!context->getExtensions().depthTextureANGLE &&
                    !((context->getExtensions().packedDepthStencilOES ||
                       context->getExtensions().depthTextureCubeMapOES) &&
                      context->getExtensions().depthTextureOES))
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, format);
                    return false;
                }

                switch (target)
                {
                    case TextureTarget::_2D:
                        break;
                    case TextureTarget::CubeMapNegativeX:
                    case TextureTarget::CubeMapNegativeY:
                    case TextureTarget::CubeMapNegativeZ:
                    case TextureTarget::CubeMapPositiveX:
                    case TextureTarget::CubeMapPositiveY:
                    case TextureTarget::CubeMapPositiveZ:
                        if (!context->getExtensions().depthTextureCubeMapOES)
                        {
                            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                                   kMismatchedTargetAndFormat);
                            return false;
                        }
                        break;
                    default:
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTargetAndFormat);
                        return false;
                }

                // OES_depth_texture supports loading depth data and multiple levels,
                // but ANGLE_depth_texture does not
                if (!context->getExtensions().depthTextureOES)
                {
                    if (pixels != nullptr)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPixelDataNotNull);
                        return false;
                    }
                    if (level != 0)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kLevelNotZero);
                        return false;
                    }
                }
                break;
            default:
                break;
        }

        if (!isSubImage)
        {
            switch (internalformat)
            {
                // Core ES 2.0 formats
                case GL_ALPHA:
                case GL_LUMINANCE:
                case GL_LUMINANCE_ALPHA:
                case GL_RGB:
                case GL_RGBA:
                    break;

                case GL_RGBA32F:
                    if (!context->getExtensions().colorBufferFloatRgbaCHROMIUM)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
                        return false;
                    }

                    nonEqualFormatsAllowed = true;

                    if (type != GL_FLOAT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                    }
                    if (format != GL_RGBA)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                    }
                    break;

                case GL_RGB32F:
                    if (!context->getExtensions().colorBufferFloatRgbCHROMIUM)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
                        return false;
                    }

                    nonEqualFormatsAllowed = true;

                    if (type != GL_FLOAT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                    }
                    if (format != GL_RGB)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                    }
                    break;

                case GL_BGRA_EXT:
                    if (!context->getExtensions().textureFormatBGRA8888EXT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
                        return false;
                    }
                    break;

                case GL_DEPTH_COMPONENT:
                    if (!(context->getExtensions().depthTextureAny()))
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
                        return false;
                    }
                    break;

                case GL_DEPTH_STENCIL:
                    if (!(context->getExtensions().depthTextureANGLE ||
                          context->getExtensions().packedDepthStencilOES ||
                          context->getExtensions().depthTextureCubeMapOES))
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
                        return false;
                    }
                    break;
                // Valid sized internal format for GL_OES_required_internalformat.
                case GL_ALPHA8_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        type == GL_UNSIGNED_BYTE && format == GL_ALPHA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_LUMINANCE8_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        type == GL_UNSIGNED_BYTE && format == GL_LUMINANCE)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_LUMINANCE4_ALPHA4_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        type == GL_UNSIGNED_BYTE && format == GL_LUMINANCE_ALPHA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_LUMINANCE8_ALPHA8_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        type == GL_UNSIGNED_BYTE && format == GL_LUMINANCE_ALPHA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_RGB565_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_6_5) &&
                        format == GL_RGB)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    if (context->getExtensions().requiredInternalformatOES &&
                        context->getExtensions().textureType2101010REVEXT &&
                        type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGB)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_RGB8_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        type == GL_UNSIGNED_BYTE && format == GL_RGB)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    if (context->getExtensions().requiredInternalformatOES &&
                        context->getExtensions().textureType2101010REVEXT &&
                        type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGB)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_RGBA4_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_4_4_4_4) &&
                        format == GL_RGBA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_RGB5_A1:
                    if (context->getExtensions().requiredInternalformatOES &&
                        (type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_5_5_1) &&
                        format == GL_RGBA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    if (context->getExtensions().requiredInternalformatOES &&
                        context->getExtensions().textureType2101010REVEXT &&
                        type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_RGBA8_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        type == GL_UNSIGNED_BYTE && format == GL_RGBA)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_DEPTH_COMPONENT16_OES:
                    if (context->getExtensions().requiredInternalformatOES &&
                        (type == GL_UNSIGNED_SHORT || type == GL_UNSIGNED_INT) &&
                        format == GL_DEPTH_COMPONENT)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_DEPTH_COMPONENT24_OES:
                    if ((context->getExtensions().requiredInternalformatOES &&
                         context->getExtensions().depth24OES) &&
                        type == GL_UNSIGNED_INT && format == GL_DEPTH_COMPONENT)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_DEPTH_COMPONENT32_OES:
                    if ((context->getExtensions().requiredInternalformatOES &&
                         context->getExtensions().depth32OES) &&
                        type == GL_UNSIGNED_INT && format == GL_DEPTH_COMPONENT)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_DEPTH24_STENCIL8_OES:
                    if ((context->getExtensions().requiredInternalformatOES &&
                         context->getExtensions().packedDepthStencilOES) &&
                        type == GL_UNSIGNED_INT_24_8_OES && format == GL_DEPTH_STENCIL_OES)
                    {
                        nonEqualFormatsAllowed = true;
                    }
                    break;

                case GL_RED:
                case GL_RG:
                    if (!context->getExtensions().textureRgEXT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
                        return false;
                    }
                    break;

                case GL_SRGB_EXT:
                case GL_SRGB_ALPHA_EXT:
                    if (!context->getExtensions().sRGBEXT)
                    {
                        ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, internalformat);
                        return false;
                    }
                    break;

                case GL_RGB10_A2_EXT:
                    if (!context->getExtensions().textureType2101010REVEXT)
                    {
                        ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, internalformat);
                        return false;
                    }

                    if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
                        return false;
                    }

                    nonEqualFormatsAllowed = true;

                    break;

                case GL_RGBX8_ANGLE:
                    if (context->getExtensions().rgbxInternalFormatANGLE &&
                        type == GL_UNSIGNED_BYTE && format == GL_RGB)
                    {
                        nonEqualFormatsAllowed = true;
                    }

                    break;

                default:
                    // Compressed formats are not valid internal formats for glTexImage*D
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_VALUE, kInvalidInternalFormat,
                                            internalformat);
                    return false;
            }
        }
        else
        {
            // Checking format combination also applies to TexSubImage commands, albeit with the
            // existing texture's internalformat arg instead of an input.
            // From the ES 2.0 spec:
            // The same constraints and errors apply to the TexSubImage commands' argument format
            // and the internalformat of the texture array being respecified as apply to the format
            // and internalformat arguments of its TexImage counterparts.
            //
            // The original valid combinations for ES 2.0 come from Table 3.4 in the spec, where the
            // internal format is expected to match the base format. However, some extensions allow
            // additional internal formats which do not necessarily match the base format, and more
            // valid combinations. Some such extensions are as follows:
            // - GL_ANGLE_rgbx_internal_format
            // - GL_OES_required_internalformat
            // - GL_EXT_sRGB
            // - GL_EXT_texture_format_BGRA8888
            // - GL_EXT_texture_storage
            // - GL_EXT_texture_type_2_10_10_10_REV
            const GLenum textureInternalFormat =
                texture->getFormat(target, level).info->sizedInternalFormat;
            bool isValidCombination;
            switch (textureInternalFormat)
            {
                case GL_RGB8:
                {
                    isValidCombination =
                        (format == GL_RGB && (type == GL_UNSIGNED_BYTE ||
                                              (type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT &&
                                               context->getExtensions().requiredInternalformatOES &&
                                               context->getExtensions().textureType2101010REVEXT)));
                    break;
                }
                case GL_RGB565:
                {
                    isValidCombination = (format == GL_RGB &&
                                          (type == GL_UNSIGNED_SHORT_5_6_5 ||
                                           (type == GL_UNSIGNED_BYTE &&
                                            context->getExtensions().requiredInternalformatOES) ||
                                           (type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT &&
                                            context->getExtensions().requiredInternalformatOES &&
                                            context->getExtensions().textureType2101010REVEXT)));
                    break;
                }
                case GL_RGB5_A1:
                {
                    isValidCombination = (format == GL_RGBA &&
                                          (type == GL_UNSIGNED_SHORT_5_5_5_1 ||
                                           (type == GL_UNSIGNED_BYTE &&
                                            context->getExtensions().requiredInternalformatOES) ||
                                           (type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT &&
                                            context->getExtensions().requiredInternalformatOES &&
                                            context->getExtensions().textureType2101010REVEXT)));
                    break;
                }
                case GL_RGBA4:
                {
                    isValidCombination = (format == GL_RGBA &&
                                          (type == GL_UNSIGNED_SHORT_4_4_4_4 ||
                                           (type == GL_UNSIGNED_BYTE &&
                                            context->getExtensions().requiredInternalformatOES)));
                    break;
                }
                default:
                {
                    // If the internal format does not correspond to a core ES 2.0 format
                    // combination, the extension checks for it are expected to have been performed
                    // during the texture definition. Therefore, their respective combinations,
                    // along with the core internal format with no new combinations, can be simply
                    // checked via the lookup table in ValidES3FormatCombination().
                    isValidCombination =
                        ValidES3FormatCombination(format, type, textureInternalFormat);
                    break;
                }
            }

            if (!isValidCombination)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
                return false;
            }
        }
    }

    if (isSubImage)
    {
        const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
        if (textureInternalFormat.internalFormat == GL_NONE)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureLevel);
            return false;
        }

        // ANGLE_rgbx_internal_format allows GL_RGBA to be uploaded to GL_RGBX8_ANGLE textures
        // even if the base format is GL_RGB.
        const GLenum textureSizedInternalFormat = textureInternalFormat.sizedInternalFormat;
        bool isFormatSpecialCase                = textureSizedInternalFormat == GL_RGBX8_ANGLE;
        if (!isFormatSpecialCase && format != textureInternalFormat.format)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureFormatMismatch);
            return false;
        }

        if (context->isWebGL())
        {
            // For valid GL_RGBX8_ANGLE combinations, GetInternalFormatInfo returns as either
            // GL_RGB8 or GL_RGBA8.
            // GL_BGRA_EXT is registered as a sized format in ANGLE, which can
            // cause GetInternalFormatInfo to return it as an alias for GL_BGRA8_EXT. We check both
            // GetSizedFormatInternal (which resolves to the canonical sized format) and
            // GetInternalFormatInfo (which might return GL_BGRA_EXT itself) to handle all cases.
            bool isSizedFormatSpecialCase = textureSizedInternalFormat == GL_RGBX8_ANGLE ||
                                            textureSizedInternalFormat == GL_BGRA8_EXT;
            if (!isSizedFormatSpecialCase &&
                textureSizedInternalFormat !=
                    GetInternalFormatInfo(format, type).sizedInternalFormat)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureTypeMismatch);
                return false;
            }
        }

        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
            return false;
        }

        if (width > 0 && height > 0 && pixels == nullptr &&
            context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPixelDataNull);
            return false;
        }
    }
    else
    {
        if (texture->getImmutableFormat())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
            return false;
        }

        const gl::InternalFormat &internalFormatInfo =
            gl::GetInternalFormatInfo(internalformat, type);
        if (!ValidImageAllocationSize(context, entryPoint, width, height, 1, 0,
                                      internalFormatInfo.sizedInternalFormat))
        {
            // Error already generated
            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.
    if (!isSubImage && internalformat != format && !nonEqualFormatsAllowed)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
        return false;
    }

    GLenum sizeCheckFormat = isSubImage ? format : internalformat;
    return ValidImageDataSize(context, entryPoint, texType, width, height, 1, sizeCheckFormat, type,
                              pixels, outImageSize);
}

bool ValidateCompressedTexImage(const Context *context,
                                angle::EntryPoint entryPoint,
                                TextureTarget targetPacked,
                                GLint level,
                                GLenum internalformat,
                                GLsizei width,
                                GLsizei height,
                                GLsizei depth,
                                GLint border,
                                GLsizei imageSize,
                                const void *data,
                                TexImageDimension texImageDimension)
{
    const Version &clientVersion = context->getClientVersion();
    const Extensions &extensions = context->getExtensions();
    const Caps &caps             = context->getCaps();

    const TextureType texType = TextureTargetToType(targetPacked);
    GLsizei maxDimension      = 0;

    // Target is valid for the command and in the current context.
    {
        bool validForCommand = false;
        bool validForContext = false;
        switch (texType)
        {
            case TextureType::_2D:
                validForCommand = (texImageDimension == TexImageDimension::_2D);
                validForContext = true;
                maxDimension    = caps.max2DTextureSize;
                break;
            case TextureType::CubeMap:
                validForCommand = (texImageDimension == TexImageDimension::_2D);
                validForContext = (clientVersion >= ES_2_0 || extensions.textureCubeMapOES);
                maxDimension    = caps.maxCubeMapTextureSize;
                break;
            case TextureType::_2DArray:
                validForCommand = (texImageDimension == TexImageDimension::_3D);
                validForContext = (clientVersion >= ES_3_0);
                maxDimension    = caps.max2DTextureSize;
                break;
            case TextureType::_3D:
                validForCommand = (texImageDimension == TexImageDimension::_3D);
                validForContext = (clientVersion >= ES_3_0 || extensions.texture3DOES);
                maxDimension    = caps.max3DTextureSize;
                break;
            case TextureType::CubeMapArray:
                validForCommand = (texImageDimension == TexImageDimension::_3D);
                validForContext = (clientVersion >= ES_3_2 || extensions.textureCubeMapArrayAny());
                maxDimension    = caps.maxCubeMapTextureSize;
                break;
            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTargetUnknown);
                return false;
        }

        if (ANGLE_UNLIKELY(!validForCommand || !validForContext))
        {
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kTextureTargetInvalid, ToGLenum(targetPacked));
            return false;
        }

        ASSERT(maxDimension > 0);
    }

    // Texture bound to target can be redefined.
    {
        Texture *texture = context->getTextureByType(texType);
        ASSERT(texture != nullptr);

        if (ANGLE_UNLIKELY(!ValidateNoActivePLSConflict(context, entryPoint, texture->id())))
        {
            return false;
        }

        if (ANGLE_UNLIKELY(texture->getImmutableFormat()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureIsImmutable);
            return false;
        }
    }

    const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(internalformat);

    // Format is known and supported in the current context.
    {
        const bool validForContext = internalFormatInfo.textureSupport(clientVersion, extensions);
        const bool validForCommand = internalFormatInfo.compressed || internalFormatInfo.paletted;
        if (ANGLE_UNLIKELY(!validForContext || !validForCommand))
        {
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kInvalidCompressedInternalFormat,
                                    internalformat);
            return false;
        }
    }

    // Format is valid for target; level is valid for target or format.
    {
        if (ANGLE_LIKELY(internalFormatInfo.compressed))
        {
            // If the format does not support 2D arrays, disallow it for cube map arrays too.
            if (texType == TextureType::_2DArray || texType == TextureType::CubeMapArray)
            {
                if (ANGLE_UNLIKELY(
                        !ValidCompressedFormatForTexture2DArray(internalformat, extensions)))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture2D);
                    return false;
                }
            }
            else if (texType == TextureType::_3D)
            {
                if (ANGLE_UNLIKELY(!ValidCompressedFormatForTexture3D(internalformat, extensions)))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                           kInternalFormatNotSupportedTexture3D);
                    return false;
                }
            }

            // Compressed formats with 3D blocks support only 3D textures.
            if (ANGLE_UNLIKELY(internalFormatInfo.compressedBlockDepth > 1 &&
                               texType != TextureType::_3D))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatRequiresTexture3D);
                return false;
            }

            if (ANGLE_UNLIKELY(level > log2(maxDimension) || level < 0))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevelForTarget);
                return false;
            }
        }
        else
        {
            ASSERT(internalFormatInfo.paletted);

            if (ANGLE_UNLIKELY(texType != TextureType::_2D))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalFormatPalettedTarget);
                return false;
            }

            // Paletted formats redefine level semantics and allow only non-positive values.
            if (ANGLE_UNLIKELY(level > 0))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevelPalettePositive);
                return false;
            }
        }
    }

    // Dimensions are not negative.
    if (ANGLE_UNLIKELY(width < 0 || height < 0 || depth < 0))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDimensions);
        return false;
    }

    // NPOT validation. Relevant only for low context versions without the NPOT extension.
    if (ANGLE_UNLIKELY(clientVersion < ES_3_0 && !extensions.textureNpotOES))
    {
        // OpenGL ES 1.x: NPOT textures are not allowed.
        // OpenGL ES 2.0: NPOT textures are allowed only for level 0.
        // If any dimension is zero, NPOT values are ignored.
        const bool npotDisallowed = clientVersion < ES_2_0 || level != 0;
        const bool zeroSize       = (width == 0) || (height == 0) || (depth == 0);
        const bool npotDimensions = !zeroSize && (!isPow2(width) || !isPow2(height) ||
                                                  (texType == TextureType::_3D && !isPow2(depth)));
        if (ANGLE_UNLIKELY(npotDisallowed && npotDimensions))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureNotPow2);
            return false;
        }
    }

    // Dimensions do not exceed target-specific maximums.
    {
        ASSERT((texType != TextureType::_2D && texType != TextureType::CubeMap) || depth == 1);
        ASSERT(maxDimension > 0 && level < 32);

        // Negative level values are clamped because they have a special use for paletted formats.
        const GLsizei maxDimForLevel = maxDimension >> std::max(0, level);
        const bool isArray =
            texType == TextureType::_2DArray || texType == TextureType::CubeMapArray;
        const GLsizei maxDepth =
            isArray ? context->getCaps().maxArrayTextureLayers : maxDimForLevel;
        const bool areDimsInRange =
            (width <= maxDimForLevel) && (height <= maxDimForLevel) && (depth <= maxDepth);
        if (ANGLE_UNLIKELY(!areDimsInRange))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
            return false;
        }
    }

    // Dimensions are valid for cube maps.
    if (texType == TextureType::CubeMap || texType == TextureType::CubeMapArray)
    {
        if (ANGLE_UNLIKELY(width != height))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFaceNotSquare);
            return false;
        }

        if (ANGLE_UNLIKELY(texType == TextureType::CubeMapArray && (depth % 6 != 0)))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapInvalidDepth);
            return false;
        }
    }

    // Dimensions are valid for the format.
    if (ANGLE_LIKELY(internalFormatInfo.compressed))
    {
        if (IsPVRTC1Format(internalformat))
        {
            // PVRTC1 requires dimensions to be powers of two by design.
            // Supported platforms (Apple silicon) accept only square PVRTC1 textures.
            if (ANGLE_UNLIKELY(!isPow2(width) || !isPow2(height) || (width != height)))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureDimensionsPVRTC1);
                return false;
            }
        }
        else if (IsS3TCFormat(internalformat) || IsRGTCFormat(internalformat) ||
                 IsBPTCFormat(internalformat))
        {
            // D3D11 requires the implied level 0 dimensions of BCn textures to be
            // multiples of four. WebGL has the same limitation for these formats.
            if (context->isWebGL() ||
                context->getLimitations().compressedBaseMipLevelMultipleOfFour)
            {
                ASSERT(level >= 0 && level < 32);
                ASSERT(width >= 0 && height >= 0);
                if (ANGLE_UNLIKELY(((width << level) % 4) != 0 || ((height << level) % 4) != 0))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureDimensionsBCn);
                    return false;
                }
            }
        }
    }
    else
    {
        ASSERT(internalFormatInfo.paletted);
        // Paletted formats use negative level values to redefine multiple levels at once.
        if (ANGLE_UNLIKELY(level < -log2(std::max(width, height))))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMipLevelPaletteCount);
            return false;
        }
    }

    if (ANGLE_UNLIKELY(border != 0))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBorder);
        return false;
    }

    // TODO(http://anglebug.com/42266155)
    // The computeCompressedImageSize helper does not support multi-level paletted images.
    if (ANGLE_UNLIKELY(internalFormatInfo.paletted && level != 0))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUnimplementedPaletteLevels);
        return false;
    }

    // Make sure computeCompressedImageSize sets expectedImageSize.
    GLuint expectedImageSize = std::numeric_limits<GLuint>::max();
    {
        // Integer overflow during imageSize computation is not explicitly defined
        // in specs but the values cannot be equal in case of an overflow.
        const bool isSizeValid = internalFormatInfo.computeCompressedImageSize(
            Extents(width, height, depth), &expectedImageSize);
        if (ANGLE_UNLIKELY(!isSizeValid ||
                           (imageSize < 0 || static_cast<GLuint>(imageSize) != expectedImageSize)))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCompressedTextureImageSizeMismatch);
            return false;
        }
    }

    // Allocated memory does not exceed an internal limit.
    if (ANGLE_UNLIKELY(expectedImageSize > context->getLimitations().maxTextureBytes))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureSizeLimitation);
        return false;
    }

    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
    if (pixelUnpackBuffer != nullptr)
    {
        // ...the buffer object's data store is currently mapped but not persistently.
        if (ANGLE_UNLIKELY(pixelUnpackBuffer->isMapped() &&
                           !pixelUnpackBuffer->isPersistentlyMapped()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
            return false;
        }

        if (context->isWebGL() || context->isHardenedContext())
        {
            if (ANGLE_UNLIKELY(pixelUnpackBuffer->hasTFBBindingConflict()))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       kPixelUnpackBufferBoundForTransformFeedback);
                return false;
            }
        }

        CheckedNumeric<size_t> checkedEndByte(expectedImageSize);
        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(data));
        checkedEndByte += checkedOffset;

        const size_t bufferSize = static_cast<size_t>(pixelUnpackBuffer->getSize());
        if (ANGLE_UNLIKELY(!checkedEndByte.IsValid() || (checkedEndByte.ValueOrDie() > bufferSize)))
        {
            // Overflow past the end of the buffer
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kParamOverflow);
            return false;
        }
    }

    return true;
}

bool ValidateCompressedTexSubImage(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   TextureTarget targetPacked,
                                   GLint level,
                                   GLint xoffset,
                                   GLint yoffset,
                                   GLint zoffset,
                                   GLsizei width,
                                   GLsizei height,
                                   GLsizei depth,
                                   GLenum format,
                                   GLsizei imageSize,
                                   const void *data,
                                   TexImageDimension texImageDimension)
{
    const Version &clientVersion = context->getClientVersion();
    const Extensions &extensions = context->getExtensions();
    const Caps &caps             = context->getCaps();

    GLsizei maxDimension = 0;

    // Target is valid for the command and in the current context.
    {
        bool validForCommand = false;
        bool validForContext = false;
        switch (targetPacked)
        {
            case TextureTarget::_2D:
                validForCommand = (texImageDimension == TexImageDimension::_2D);
                validForContext = true;
                maxDimension    = caps.max2DTextureSize;
                break;
            case TextureTarget::CubeMapPositiveX:
            case TextureTarget::CubeMapNegativeX:
            case TextureTarget::CubeMapPositiveY:
            case TextureTarget::CubeMapNegativeY:
            case TextureTarget::CubeMapPositiveZ:
            case TextureTarget::CubeMapNegativeZ:
                validForCommand = (texImageDimension == TexImageDimension::_2D);
                validForContext = (clientVersion >= ES_2_0 || extensions.textureCubeMapOES);
                maxDimension    = caps.maxCubeMapTextureSize;
                break;
            case TextureTarget::_2DArray:
                validForCommand = (texImageDimension == TexImageDimension::_3D);
                validForContext = (clientVersion >= ES_3_0);
                maxDimension    = caps.max2DTextureSize;
                break;
            case TextureTarget::_3D:
                validForCommand = (texImageDimension == TexImageDimension::_3D);
                validForContext = (clientVersion >= ES_3_0 || extensions.texture3DOES);
                maxDimension    = caps.max3DTextureSize;
                break;
            case TextureTarget::CubeMapArray:
                validForCommand = (texImageDimension == TexImageDimension::_3D);
                validForContext = (clientVersion >= ES_3_2 || extensions.textureCubeMapArrayAny());
                maxDimension    = caps.maxCubeMapTextureSize;
                break;
            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTargetUnknown);
                return false;
        }

        if (ANGLE_UNLIKELY(!validForCommand || !validForContext))
        {
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kTextureTargetInvalid, ToGLenum(targetPacked));
            return false;
        }

        ASSERT(maxDimension > 0);
    }

    // Level is not negative and not greater than the maximum possible level for the target.
    if (ANGLE_UNLIKELY(level > log2(maxDimension) || level < 0))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevelForTarget);
        return false;
    }

    const Texture *texture = context->getTextureByTarget(targetPacked);
    ASSERT(texture != nullptr);

    const InternalFormat &imageFormatInfo = *texture->getFormat(targetPacked, level).info;
    const GLenum imageFormat              = imageFormatInfo.internalFormat;

    // Image exists for the target and level.
    if (ANGLE_UNLIKELY(imageFormat == GL_NONE))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureLevel);
        return false;
    }

    // Image uses a compressed format.
    if (ANGLE_UNLIKELY(!imageFormatInfo.compressed))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedMismatch);
        return false;
    }
    ASSERT(!imageFormatInfo.paletted);  // The check above must reject paletted images.

    // If the image format is ETC1, subregion updates must be enabled explicitly.
    if (IsETC1Format(imageFormat))
    {
        if (ANGLE_UNLIKELY(!extensions.compressedETC1RGB8SubTextureEXT))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSubregionUpdateETC1);
            return false;
        }
    }

    const size_t imageWidth  = texture->getWidth(targetPacked, level);
    const size_t imageHeight = texture->getHeight(targetPacked, level);
    const size_t imageDepth  = texture->getDepth(targetPacked, level);

    // Subregion offsets and dimensions are not negative and fit the image.
    {
        if (ANGLE_UNLIKELY(xoffset < 0 || yoffset < 0 || zoffset < 0))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSubregionOffsetsNegative);
            return false;
        }

        if (ANGLE_UNLIKELY(width < 0 || height < 0 || depth < 0))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSubregionDimensionsNegative);
            return false;
        }

        if (ANGLE_UNLIKELY(static_cast<size_t>(xoffset) > imageWidth ||
                           static_cast<size_t>(yoffset) > imageHeight ||
                           static_cast<size_t>(zoffset) > imageDepth))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSubregionOffsetsOutOfBounds);
            return false;
        }

        // Cannot overflow due to the checks above.
        if (ANGLE_UNLIKELY(
                (imageWidth - static_cast<size_t>(xoffset) < static_cast<size_t>(width)) ||
                (imageHeight - static_cast<size_t>(yoffset) < static_cast<size_t>(height)) ||
                (imageDepth - static_cast<size_t>(zoffset) < static_cast<size_t>(depth))))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSubregionDimensionsOutOfBounds);
            return false;
        }
    }

    // Subregion is compatible with the internal format.
    {
        // Ensure that the internal format's block dimensions are set.
        ASSERT(imageFormatInfo.compressedBlockWidth > 0 &&
               imageFormatInfo.compressedBlockHeight > 0 &&
               imageFormatInfo.compressedBlockDepth > 0);

        // Check if the whole image is being replaced. For 2D texture blocks, zoffset and depth
        // do not affect whether the replaced region fills the entire image.
        const bool fullImageReplacement =
            (xoffset == 0 && static_cast<size_t>(width) == imageWidth) &&
            (yoffset == 0 && static_cast<size_t>(height) == imageHeight) &&
            ((zoffset == 0 && static_cast<size_t>(depth) == imageDepth) ||
             imageFormatInfo.compressedBlockDepth == 1);

        // If the subregion is not equal to the whole image, format-specific validation is needed.
        if (!fullImageReplacement)
        {
            // PVRTC1 images do not support partial updates.
            if (ANGLE_UNLIKELY(IsPVRTC1Format(imageFormat)))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSubregionUpdatePVRTC1);
                return false;
            }

            // Offsets are multiples of the block dimensions.
            const bool offsetsAligned = xoffset % imageFormatInfo.compressedBlockWidth == 0 &&
                                        yoffset % imageFormatInfo.compressedBlockHeight == 0 &&
                                        zoffset % imageFormatInfo.compressedBlockDepth == 0;
            if (ANGLE_UNLIKELY(!offsetsAligned))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSubregionOffsetsBlockSize);
                return false;
            }

            // Subregion dimensions are either multiples of the block dimensions
            // or exactly reach the image bounds.
            const bool validWidth  = static_cast<size_t>(xoffset + width) == imageWidth ||
                                     width % imageFormatInfo.compressedBlockWidth == 0;
            const bool validHeight = static_cast<size_t>(yoffset + height) == imageHeight ||
                                     height % imageFormatInfo.compressedBlockHeight == 0;
            const bool validDepth  = static_cast<size_t>(zoffset + depth) == imageDepth ||
                                     depth % imageFormatInfo.compressedBlockDepth == 0;
            if (ANGLE_UNLIKELY(!validWidth || !validHeight || !validDepth))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSubregionDimensionsBlockSize);
                return false;
            }
        }
    }

    // Specified format exactly matches the image internal format.
    if (format != imageFormat)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSubregionFormat);
        return false;
    }

    // Make sure computeCompressedImageSize sets expectedImageSize.
    GLuint expectedImageSize = std::numeric_limits<GLuint>::max();
    {
        // Integer overflow during imageSize computation is not explicitly defined
        // in specs but the values cannot be equal in case of an overflow.
        const bool isSizeValid = imageFormatInfo.computeCompressedImageSize(
            Extents(width, height, depth), &expectedImageSize);
        if (ANGLE_UNLIKELY(!isSizeValid ||
                           (imageSize < 0 || static_cast<GLuint>(imageSize) != expectedImageSize)))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCompressedTextureImageSizeMismatch);
            return false;
        }
    }

    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
    if (pixelUnpackBuffer != nullptr)
    {
        // ...the buffer object's data store is currently mapped but not persistently.
        if (ANGLE_UNLIKELY(pixelUnpackBuffer->isMapped() &&
                           !pixelUnpackBuffer->isPersistentlyMapped()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
            return false;
        }

        if (context->isWebGL() || context->isHardenedContext())
        {
            if (ANGLE_UNLIKELY(pixelUnpackBuffer->hasTFBBindingConflict()))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       kPixelUnpackBufferBoundForTransformFeedback);
                return false;
            }
        }

        CheckedNumeric<size_t> checkedEndByte(expectedImageSize);
        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(data));
        checkedEndByte += checkedOffset;

        const size_t bufferSize = static_cast<size_t>(pixelUnpackBuffer->getSize());
        if (ANGLE_UNLIKELY(!checkedEndByte.IsValid() || (checkedEndByte.ValueOrDie() > bufferSize)))
        {
            // Overflow past the end of the buffer
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kParamOverflow);
            return false;
        }
    }
    else
    {
        if (ANGLE_UNLIKELY(width > 0 && height > 0 && depth > 0 && data == nullptr))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPixelDataNull);
            return false;
        }
    }

    return true;
}

}  // anonymous namespace

bool ValidateDiscardFramebufferEXT(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   GLenum target,
                                   GLsizei numAttachments,
                                   const GLenum *attachments)
{
    bool defaultFramebuffer = false;

    switch (target)
    {
        case GL_FRAMEBUFFER:
            defaultFramebuffer =
                (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault());
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
            return false;
    }

    return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
                                          defaultFramebuffer);
}

bool ValidateBindVertexArrayOES(const Context *context,
                                angle::EntryPoint entryPoint,
                                VertexArrayID array)
{
    return ValidateBindVertexArrayBase(context, entryPoint, array);
}

bool ValidateDeleteVertexArraysOES(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   GLsizei n,
                                   const VertexArrayID *arrays)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, arrays);
}

bool ValidateGenVertexArraysOES(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLsizei n,
                                const VertexArrayID *arrays)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, arrays);
}

bool ValidateProgramBinaryOES(const Context *context,
                              angle::EntryPoint entryPoint,
                              ShaderProgramID program,
                              GLenum binaryFormat,
                              const void *binary,
                              GLint length)
{
    return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
}

bool ValidateGetProgramBinaryOES(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 ShaderProgramID program,
                                 GLsizei bufSize,
                                 const GLsizei *length,
                                 const GLenum *binaryFormat,
                                 const void *binary)
{
    return ValidateGetProgramBinaryBase(context, entryPoint, 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 ValidateDebugMessageControlBase(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLenum source,
                                     GLenum type,
                                     GLenum severity,
                                     GLsizei count,
                                     const GLuint *ids)
{
    if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource);
        return false;
    }

    if (!ValidDebugType(type) && type != GL_DONT_CARE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugType);
        return false;
    }

    if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSeverity);
        return false;
    }

    if (count > 0)
    {
        if (source == GL_DONT_CARE || type == GL_DONT_CARE)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDebugSourceType);
            return false;
        }

        if (severity != GL_DONT_CARE)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDebugSeverity);
            return false;
        }

        if (ids == nullptr)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDebugMessageControlIdsNULL);
            return false;
        }
    }
    else if (count < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeParam);
        return false;
    }

    return true;
}

bool ValidateDebugMessageInsertBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum source,
                                    GLenum type,
                                    GLuint id,
                                    GLenum severity,
                                    GLsizei length,
                                    const GLchar *buf)
{
    if (!ValidDebugSource(source, true))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource);
        return false;
    }

    if (!ValidDebugType(type))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugType);
        return false;
    }

    if (!ValidDebugSeverity(severity))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSeverity);
        return false;
    }

    if (buf == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDebugMessageNULL);
        return false;
    }

    const GLuint maxMessageLength = context->getCaps().maxDebugMessageLength;
    const size_t messageLength    = (length < 0) ? strnlen(buf, maxMessageLength) : length;
    if (messageLength >= maxMessageLength)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
        return false;
    }

    return true;
}

bool ValidateGetDebugMessageLogBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLuint count,
                                    GLsizei bufSize,
                                    const GLenum *sources,
                                    const GLenum *types,
                                    const GLuint *ids,
                                    const GLenum *severities,
                                    const GLsizei *lengths,
                                    const GLchar *messageLog)
{
    if (bufSize < 0 && messageLog != nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    return true;
}

bool ValidateDebugMessageControlKHR(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum source,
                                    GLenum type,
                                    GLenum severity,
                                    GLsizei count,
                                    const GLuint *ids,
                                    GLboolean enabled)
{
    return ValidateDebugMessageControlBase(context, entryPoint, source, type, severity, count, ids);
}

bool ValidateDebugMessageInsertKHR(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   GLenum source,
                                   GLenum type,
                                   GLuint id,
                                   GLenum severity,
                                   GLsizei length,
                                   const GLchar *buf)
{
    return ValidateDebugMessageInsertBase(context, entryPoint, source, type, id, severity, length,
                                          buf);
}

bool ValidateGetDebugMessageLogKHR(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   GLuint count,
                                   GLsizei bufSize,
                                   const GLenum *sources,
                                   const GLenum *types,
                                   const GLuint *ids,
                                   const GLenum *severities,
                                   const GLsizei *lengths,
                                   const GLchar *messageLog)
{
    return ValidateGetDebugMessageLogBase(context, entryPoint, count, bufSize, sources, types, ids,
                                          severities, lengths, messageLog);
}

bool ValidatePushDebugGroupBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLenum source,
                                GLuint id,
                                GLsizei length,
                                const GLchar *message)
{
    if (!ValidDebugSource(source, true))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDebugSource);
        return false;
    }

    if (message == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kDebugMessageNULL);
        return false;
    }

    const GLuint maxMessageLength = context->getCaps().maxDebugMessageLength;
    const size_t messageLength    = (length < 0) ? strnlen(message, maxMessageLength) : length;
    if (messageLength >= maxMessageLength)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
        return false;
    }

    size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
    if (currentStackSize >= context->getCaps().maxDebugGroupStackDepth)
    {
        ANGLE_VALIDATION_ERROR(GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth);
        return false;
    }

    return true;
}

bool ValidatePopDebugGroupBase(const Context *context, angle::EntryPoint entryPoint)
{
    size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
    if (currentStackSize <= 1)
    {
        ANGLE_VALIDATION_ERROR(GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup);
        return false;
    }

    return true;
}

bool ValidatePushDebugGroupKHR(const Context *context,
                               angle::EntryPoint entryPoint,
                               GLenum source,
                               GLuint id,
                               GLsizei length,
                               const GLchar *message)
{
    return ValidatePushDebugGroupBase(context, entryPoint, source, id, length, message);
}

bool ValidatePopDebugGroupKHR(const Context *context, angle::EntryPoint entryPoint)
{
    return ValidatePopDebugGroupBase(context, entryPoint);
}

static bool ValidateObjectIdentifierAndName(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            GLenum identifier,
                                            GLuint name)
{
    switch (identifier)
    {
        case GL_BUFFER:
            if (context->getBuffer({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBufferName);
                return false;
            }
            return true;

        case GL_SHADER:
            if (context->getShaderNoResolveCompile({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidShaderName);
                return false;
            }
            return true;

        case GL_PROGRAM:
            if (context->getProgramNoResolveLink({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramName);
                return false;
            }
            return true;

        case GL_VERTEX_ARRAY:
            if (context->getPrivateState().getVertexArray({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidVertexArrayName);
                return false;
            }
            return true;

        case GL_QUERY:
            if (context->getQuery({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidQueryName);
                return false;
            }
            return true;

        case GL_TRANSFORM_FEEDBACK:
            if (context->getTransformFeedback({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTransformFeedbackName);
                return false;
            }
            return true;

        case GL_SAMPLER:
            if (context->getSampler({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSamplerName);
                return false;
            }
            return true;

        case GL_TEXTURE:
            if (context->getTexture({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureName);
                return false;
            }
            return true;

        case GL_RENDERBUFFER:
            if (!context->isRenderbuffer({name}))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferName);
                return false;
            }
            return true;

        case GL_FRAMEBUFFER:
            if (context->getFramebuffer({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferName);
                return false;
            }
            return true;

        case GL_PROGRAM_PIPELINE:
            if (context->getProgramPipeline({name}) == nullptr)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramPipelineName);
                return false;
            }
            return true;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidIndentifier);
            return false;
    }
}

static bool ValidateLabelLength(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLsizei length,
                                const GLchar *label)
{
    const GLuint maxLabelLength = context->getCaps().maxLabelLength;
    size_t labelLength = 0;

    if (length < 0)
    {
        if (label != nullptr)
        {
            labelLength = strnlen(label, maxLabelLength);
        }
    }
    else
    {
        labelLength = static_cast<size_t>(length);
    }

    if (labelLength >= maxLabelLength)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsMaxLabelLength);
        return false;
    }

    return true;
}

bool ValidateObjectLabelBase(const Context *context,
                             angle::EntryPoint entryPoint,
                             GLenum identifier,
                             GLuint name,
                             GLsizei length,
                             const GLchar *label)
{
    if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name))
    {
        return false;
    }

    if (!ValidateLabelLength(context, entryPoint, length, label))
    {
        return false;
    }

    return true;
}

bool ValidateObjectLabelKHR(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLenum identifier,
                            GLuint name,
                            GLsizei length,
                            const GLchar *label)
{
    return ValidateObjectLabelBase(context, entryPoint, identifier, name, length, label);
}

bool ValidateGetObjectLabelBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLenum identifier,
                                GLuint name,
                                GLsizei bufSize,
                                const GLsizei *length,
                                const GLchar *label)
{
    if (bufSize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name))
    {
        return false;
    }

    return true;
}

bool ValidateGetObjectLabelKHR(const Context *context,
                               angle::EntryPoint entryPoint,
                               GLenum identifier,
                               GLuint name,
                               GLsizei bufSize,
                               const GLsizei *length,
                               const GLchar *label)
{
    return ValidateGetObjectLabelBase(context, entryPoint, identifier, name, bufSize, length,
                                      label);
}

static bool ValidateObjectPtrName(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  const void *ptr)
{
    if (!context->getSync({unsafe_pointer_to_int_cast<uint32_t>(ptr)}))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSyncPointer);
        return false;
    }

    return true;
}

bool ValidateObjectPtrLabelBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                const void *ptr,
                                GLsizei length,
                                const GLchar *label)
{
    if (!ValidateObjectPtrName(context, entryPoint, ptr))
    {
        return false;
    }

    if (!ValidateLabelLength(context, entryPoint, length, label))
    {
        return false;
    }

    return true;
}

bool ValidateObjectPtrLabelKHR(const Context *context,
                               angle::EntryPoint entryPoint,
                               const void *ptr,
                               GLsizei length,
                               const GLchar *label)
{
    return ValidateObjectPtrLabelBase(context, entryPoint, ptr, length, label);
}

bool ValidateGetObjectPtrLabelBase(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   const void *ptr,
                                   GLsizei bufSize,
                                   const GLsizei *length,
                                   const GLchar *label)
{
    if (bufSize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    if (!ValidateObjectPtrName(context, entryPoint, ptr))
    {
        return false;
    }

    return true;
}

bool ValidateGetObjectPtrLabelKHR(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  const void *ptr,
                                  GLsizei bufSize,
                                  const GLsizei *length,
                                  const GLchar *label)
{
    return ValidateGetObjectPtrLabelBase(context, entryPoint, ptr, bufSize, length, label);
}

bool ValidateGetPointervKHR(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLenum pname,
                            void *const *params)
{
    return ValidateGetPointerv(context, entryPoint, pname, params);
}

bool ValidateBlitFramebufferANGLE(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLint srcX0,
                                  GLint srcY0,
                                  GLint srcX1,
                                  GLint srcY1,
                                  GLint dstX0,
                                  GLint dstY0,
                                  GLint dstX1,
                                  GLint dstY1,
                                  GLbitfield mask,
                                  GLenum filter)
{
    if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
    {
        // TODO(jmadill): Determine if this should be available on other implementations.
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip);
        return false;
    }

    if (filter == GL_LINEAR)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kBlitExtensionLinear);
        return false;
    }

    Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
    Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();

    if (mask & GL_COLOR_BUFFER_BIT)
    {
        const FramebufferAttachment *readColorAttachment =
            readFramebuffer->getReadColorAttachment();
        const FramebufferAttachment *drawColorAttachment =
            drawFramebuffer->getFirstColorAttachment();

        if (readColorAttachment && drawColorAttachment)
        {
            if (!(readColorAttachment->type() == GL_TEXTURE &&
                  (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D ||
                   readColorAttachment->getTextureImageIndex().getType() ==
                       TextureType::Rectangle)) &&
                readColorAttachment->type() != GL_RENDERBUFFER &&
                readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       kBlitExtensionFromInvalidAttachmentType);
                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().getType() == TextureType::_2D ||
                           attachment->getTextureImageIndex().getType() ==
                               TextureType::Rectangle)) &&
                        attachment->type() != GL_RENDERBUFFER &&
                        attachment->type() != GL_FRAMEBUFFER_DEFAULT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                               kBlitExtensionToInvalidAttachmentType);
                        return false;
                    }

                    // Return an error if the destination formats do not match
                    if (!Format::EquivalentForBlit(attachment->getFormat(),
                                                   readColorAttachment->getFormat()))
                    {
                        ANGLE_VALIDATION_ERRORF(
                            GL_INVALID_OPERATION, kBlitExtensionFormatMismatch,
                            readColorAttachment->getFormat().info->sizedInternalFormat,
                            attachment->getFormat().info->sizedInternalFormat);
                        return false;
                    }
                }
            }

            GLint samples = readFramebuffer->getSamples(context);
            if (samples != 0)
            {
                if (readColorAttachment->ensureSizeResolved(context) == angle::Result::Stop ||
                    drawColorAttachment->ensureSizeResolved(context) == angle::Result::Stop)
                {
                    // Context error must be generated by the failed call itself.
                    return false;
                }
                if (IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
                                  srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                           kBlitExtensionMultisampledWholeBufferBlit);
                    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(context, attachments[i]);
            const FramebufferAttachment *drawBuffer =
                drawFramebuffer->getAttachment(context, attachments[i]);

            if (readBuffer && drawBuffer)
            {
                if (readBuffer->ensureSizeResolved(context) == angle::Result::Stop ||
                    drawBuffer->ensureSizeResolved(context) == angle::Result::Stop)
                {
                    // Context error must be generated by the failed call itself.
                    return false;
                }
                if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
                                  dstX0, dstY0, dstX1, dstY1))
                {
                    // only whole-buffer copies are permitted
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                           kBlitExtensionDepthStencilWholeBufferBlit);
                    return false;
                }

                if (readBuffer->getResourceSamples() != 0 || drawBuffer->getResourceSamples() != 0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                           kBlitExtensionMultisampledDepthOrStencil);
                    return false;
                }
            }
        }
    }

    return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
                                             dstY0, dstX1, dstY1, mask, filter);
}

bool ValidateBlitFramebufferNV(const Context *context,
                               angle::EntryPoint entryPoint,
                               GLint srcX0,
                               GLint srcY0,
                               GLint srcX1,
                               GLint srcY1,
                               GLint dstX0,
                               GLint dstY0,
                               GLint dstX1,
                               GLint dstY1,
                               GLbitfield mask,
                               GLenum filter)
{
    return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
                                             dstY0, dstX1, dstY1, mask, filter);
}

bool ValidateClear(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask)
{
    Framebuffer *fbo             = context->getState().getDrawFramebuffer();
    const Extensions &extensions = context->getExtensions();

    if (!ValidateFramebufferComplete(context, entryPoint, fbo))
    {
        return false;
    }

    // The QCOM_framebuffer_foveated spec:
    if (fbo->isFoveationEnabled())
    {
        // INVALID_OPERATION is generated by any API call which causes a framebuffer
        // attachment to be written to if the framebuffer attachments have changed for
        // a foveated fbo.
        if (fbo->hasAnyAttachmentChanged())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFramebufferFoveationAttachmentChanged);
            return false;
        }
    }

    if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidClearMask);
        return false;
    }

    if (extensions.webglCompatibilityANGLE && (mask & GL_COLOR_BUFFER_BIT) != 0)
    {
        if (GetIntOrUnsignedIntDrawBufferMask(fbo->getDrawBufferTypeMask()).any())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoDefinedClearConversion);
            return false;
        }
    }

    if (extensions.renderSharedExponentQCOM && (mask & GL_COLOR_BUFFER_BIT) != 0)
    {
        const State &state = context->getState();
        if (!ValidateColorMasksForSharedExponentColorBuffers(state.getBlendStateExt(),
                                                             state.getDrawFramebuffer()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                   kUnsupportedColorMaskForSharedExponentColorBuffer);
            return false;
        }
    }

    if (extensions.multiviewOVR && extensions.disjointTimerQueryEXT)
    {
        const State &state       = context->getState();
        Framebuffer *framebuffer = state.getDrawFramebuffer();
        if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMultiviewTimerQuery);
            return false;
        }
    }

    return true;
}

bool ValidateDrawBuffersEXT(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLsizei n,
                            const GLenum *bufs)
{
    return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
}

bool ValidateTexImage2D(const Context *context,
                        angle::EntryPoint entryPoint,
                        TextureTarget target,
                        GLint level,
                        GLint internalformat,
                        GLsizei width,
                        GLsizei height,
                        GLint border,
                        GLenum format,
                        GLenum type,
                        const void *pixels)
{
    if (context->getClientVersion() < ES_3_0)
    {
        return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat,
                                             false, 0, 0, width, height, border, format, type,
                                             pixels, nullptr);
    }

    return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
                                           false, 0, 0, 0, width, height, 1, border, format, type,
                                           pixels, nullptr);
}

bool ValidateTexImage2DRobustANGLE(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   TextureTarget target,
                                   GLint level,
                                   GLint internalformat,
                                   GLsizei width,
                                   GLsizei height,
                                   GLint border,
                                   GLenum format,
                                   GLenum type,
                                   GLsizei bufSize,
                                   const void *pixels)
{
    GLuint imageSize = std::numeric_limits<GLuint>::max();
    if (context->getClientVersion() < ES_3_0)
    {
        if (!ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat,
                                           false, 0, 0, width, height, border, format, type, pixels,
                                           &imageSize))
        {
            return false;
        }
    }
    else
    {
        if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
                                             false, 0, 0, 0, width, height, 1, border, format, type,
                                             pixels, &imageSize))
        {
            return false;
        }
    }

    return ValidateRobustTexImage(context, entryPoint, pixels, imageSize, bufSize);
}

bool ValidateTexSubImage2D(const Context *context,
                           angle::EntryPoint entryPoint,
                           TextureTarget target,
                           GLint level,
                           GLint xoffset,
                           GLint yoffset,
                           GLsizei width,
                           GLsizei height,
                           GLenum format,
                           GLenum type,
                           const void *pixels)
{

    if (context->getClientVersion() < ES_3_0)
    {
        return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, true,
                                             xoffset, yoffset, width, height, 0, format, type,
                                             pixels, nullptr);
    }

    return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
                                           xoffset, yoffset, 0, width, height, 1, 0, format, type,
                                           pixels, nullptr);
}

bool ValidateTexSubImage2DRobustANGLE(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      TextureTarget target,
                                      GLint level,
                                      GLint xoffset,
                                      GLint yoffset,
                                      GLsizei width,
                                      GLsizei height,
                                      GLenum format,
                                      GLenum type,
                                      GLsizei bufSize,
                                      const void *pixels)
{
    GLuint imageSize = std::numeric_limits<GLuint>::max();
    if (context->getClientVersion() < ES_3_0)
    {
        if (!ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, true,
                                           xoffset, yoffset, width, height, 0, format, type, pixels,
                                           &imageSize))
        {
            return false;
        }
    }
    else
    {
        if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
                                             xoffset, yoffset, 0, width, height, 1, 0, format, type,
                                             pixels, &imageSize))
        {
            return false;
        }
    }

    return ValidateRobustTexImage(context, entryPoint, pixels, imageSize, bufSize);
}

bool ValidateTexSubImage3DOES(const Context *context,
                              angle::EntryPoint entryPoint,
                              TextureTarget target,
                              GLint level,
                              GLint xoffset,
                              GLint yoffset,
                              GLint zoffset,
                              GLsizei width,
                              GLsizei height,
                              GLsizei depth,
                              GLenum format,
                              GLenum type,
                              const void *pixels)
{
    return ValidateTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset,
                                 width, height, depth, format, type, pixels);
}

bool ValidateCompressedTexImage2D(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  TextureTarget targetPacked,
                                  GLint level,
                                  GLenum internalformat,
                                  GLsizei width,
                                  GLsizei height,
                                  GLint border,
                                  GLsizei imageSize,
                                  const void *data)
{
    return ValidateCompressedTexImage(context, entryPoint, targetPacked, level, internalformat,
                                      width, height, 1, border, imageSize, data,
                                      TexImageDimension::_2D);
}

bool ValidateCompressedTexImage3D(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  TextureTarget targetPacked,
                                  GLint level,
                                  GLenum internalformat,
                                  GLsizei width,
                                  GLsizei height,
                                  GLsizei depth,
                                  GLint border,
                                  GLsizei imageSize,
                                  const void *data)
{
    return ValidateCompressedTexImage(context, entryPoint, targetPacked, level, internalformat,
                                      width, height, depth, border, imageSize, data,
                                      TexImageDimension::_3D);
}

bool ValidateCompressedTexImage3DOES(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     TextureTarget target,
                                     GLint level,
                                     GLenum internalformat,
                                     GLsizei width,
                                     GLsizei height,
                                     GLsizei depth,
                                     GLint border,
                                     GLsizei imageSize,
                                     const void *data)
{
    return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
                                        height, depth, border, imageSize, data);
}

bool ValidateCompressedTexSubImage2D(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     TextureTarget targetPacked,
                                     GLint level,
                                     GLint xoffset,
                                     GLint yoffset,
                                     GLsizei width,
                                     GLsizei height,
                                     GLenum format,
                                     GLsizei imageSize,
                                     const void *data)
{
    return ValidateCompressedTexSubImage(context, entryPoint, targetPacked, level, xoffset, yoffset,
                                         0, width, height, 1, format, imageSize, data,
                                         TexImageDimension::_2D);
}

bool ValidateCompressedTexSubImage3D(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     TextureTarget targetPacked,
                                     GLint level,
                                     GLint xoffset,
                                     GLint yoffset,
                                     GLint zoffset,
                                     GLsizei width,
                                     GLsizei height,
                                     GLsizei depth,
                                     GLenum format,
                                     GLsizei imageSize,
                                     const void *data)
{
    return ValidateCompressedTexSubImage(context, entryPoint, targetPacked, level, xoffset, yoffset,
                                         zoffset, width, height, depth, format, imageSize, data,
                                         TexImageDimension::_3D);
}

bool ValidateCompressedTexSubImage3DOES(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        TextureTarget target,
                                        GLint level,
                                        GLint xoffset,
                                        GLint yoffset,
                                        GLint zoffset,
                                        GLsizei width,
                                        GLsizei height,
                                        GLsizei depth,
                                        GLenum format,
                                        GLsizei imageSize,
                                        const void *data)
{
    return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
                                           zoffset, width, height, depth, format, imageSize, data);
}

bool ValidateGetBufferPointervOES(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  BufferBinding targetPacked,
                                  GLenum pname,
                                  void *const *params)
{
    return ValidateGetBufferPointervBase(context, entryPoint, targetPacked, pname, nullptr);
}

bool ValidateMapBufferOES(const Context *context,
                          angle::EntryPoint entryPoint,
                          BufferBinding target,
                          GLenum access)
{
    if (!context->isValidBufferBinding(target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTarget);
        return false;
    }

    Buffer *buffer = context->getState().getTargetBuffer(target);

    if (buffer == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMappable);
        return false;
    }

    if (access != GL_WRITE_ONLY_OES)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAccessBits);
        return false;
    }

    // Though there is no explicit mention of an interaction between GL_EXT_buffer_storage
    // and GL_OES_mapbuffer extension, allow it as long as the access type of glmapbufferOES
    // is compatible with the buffer's usage flags specified during glBufferStorageEXT
    if (buffer->isImmutable() && (buffer->getStorageExtUsageFlags() & GL_MAP_WRITE_BIT) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMappable);
        return false;
    }

    if (buffer->isMapped())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferAlreadyMapped);
        return false;
    }

    return ValidateMapBufferBase(context, entryPoint, target);
}

bool ValidateUnmapBufferOES(const Context *context,
                            angle::EntryPoint entryPoint,
                            BufferBinding target)
{
    return ValidateUnmapBufferBase(context, entryPoint, target);
}

bool ValidateMapBufferRangeEXT(const Context *context,
                               angle::EntryPoint entryPoint,
                               BufferBinding target,
                               GLintptr offset,
                               GLsizeiptr length,
                               GLbitfield access)
{
    return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
}

bool ValidateMapBufferBase(const Context *context,
                           angle::EntryPoint entryPoint,
                           BufferBinding target)
{
    Buffer *buffer = context->getState().getTargetBuffer(target);
    ASSERT(buffer != nullptr);

    // Check if this buffer is currently being used as a transform feedback output buffer
    if (context->getState().isTransformFeedbackActive())
    {
        TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
        for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
        {
            const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
            if (transformFeedbackBuffer.get() == buffer)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
                return false;
            }
        }
    }

    if (context->isWebGL() || context->isHardenedContext())
    {
        if (buffer->hasTFBBindingConflict())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
            return false;
        }
    }

    return true;
}

bool ValidateFlushMappedBufferRangeEXT(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       BufferBinding target,
                                       GLintptr offset,
                                       GLsizeiptr length)
{
    return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
}

bool ValidateBindUniformLocationCHROMIUM(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         ShaderProgramID program,
                                         UniformLocation location,
                                         const GLchar *name)
{
    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    if (location.value < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLocation);
        return false;
    }

    const Caps &caps = context->getCaps();
    if (static_cast<long>(location.value) >=
        (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidBindUniformLocation);
        return false;
    }

    if (name == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformNameNull);
        return false;
    }

    if (context->nameStartsWithReservedPrefix(name))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNameStartsWithReservedPrefix);
        return false;
    }

    if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name))
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateCoverageModulationCHROMIUM(const PrivateState &state,
                                        ErrorSet *errors,
                                        angle::EntryPoint entryPoint,
                                        GLenum components)
{
    switch (components)
    {
        case GL_RGB:
        case GL_RGBA:
        case GL_ALPHA:
        case GL_NONE:
            break;
        default:
            errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCoverageComponents);
            return false;
    }

    return true;
}

bool ValidateCopyTextureCHROMIUM(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 TextureID sourceId,
                                 GLint sourceLevel,
                                 TextureTarget destTarget,
                                 TextureID destId,
                                 GLint destLevel,
                                 GLint internalFormat,
                                 GLenum destType,
                                 GLboolean unpackFlipY,
                                 GLboolean unpackPremultiplyAlpha,
                                 GLboolean unpackUnmultiplyAlpha)
{
    const Texture *source = context->getTexture(sourceId);
    if (source == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
        return false;
    }

    if (!IsValidCopyTextureSourceTarget(context, source->getType()))
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
        return false;
    }
    const char *error = nullptr;
    if (!source->isFramebufferAttachmentComplete(sourceLevel, &error))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, error);
        return false;
    }

    TextureType sourceType = source->getType();
    ASSERT(sourceType != TextureType::CubeMap);
    TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);

    if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
        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_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat, internalFormat);
        return false;
    }

    const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
    if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSourceTextureInternalFormat);
        return false;
    }

    if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    const Texture *dest = context->getTexture(destId);
    if (dest == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
        return false;
    }

    const InternalFormat &destInternalFormatInfo = GetInternalFormatInfo(internalFormat, destType);
    if (sourceType == TextureType::External && destInternalFormatInfo.isInt() &&
        !context->getExtensions().EGLImageExternalEssl3OES)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kANGLECopyTextureMissingRequiredExtension);
        return false;
    }

    if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTextureType);
        return false;
    }

    if (!ValidImageSizeParameters(context, entryPoint, dest->getType(), destLevel, sourceWidth,
                                  sourceHeight, 1, false))
    {
        // Error already generated.
        return false;
    }

    if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, sourceWidth,
                                            sourceHeight))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return false;
    }

    if (!IsValidCopyTextureDestinationFormatType(context, entryPoint, internalFormat, destType))
    {
        return false;
    }

    if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
        return false;
    }

    if (!ValidImageAllocationSize(context, entryPoint, sourceWidth, sourceHeight, 1, 0,
                                  destInternalFormatInfo.sizedInternalFormat))
    {
        // Error already generated
        return false;
    }

    if (dest->getImmutableFormat())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDestinationImmutable);
        return false;
    }

    if (source == dest && sourceLevel == destLevel)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSourceTextureSameAsDestTexture);
        return false;
    }

    return true;
}

bool ValidateCopySubTextureCHROMIUM(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    TextureID sourceId,
                                    GLint sourceLevel,
                                    TextureTarget destTarget,
                                    TextureID destId,
                                    GLint destLevel,
                                    GLint xoffset,
                                    GLint yoffset,
                                    GLint x,
                                    GLint y,
                                    GLsizei width,
                                    GLsizei height,
                                    GLboolean unpackFlipY,
                                    GLboolean unpackPremultiplyAlpha,
                                    GLboolean unpackUnmultiplyAlpha)
{
    const Texture *source = context->getTexture(sourceId);
    if (source == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
        return false;
    }

    if (!IsValidCopyTextureSourceTarget(context, source->getType()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTextureType);
        return false;
    }
    const char *error = nullptr;
    if (!source->isFramebufferAttachmentComplete(sourceLevel, &error))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, error);
        return false;
    }

    TextureType sourceType = source->getType();
    ASSERT(sourceType != TextureType::CubeMap);
    TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);

    if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return false;
    }

    if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
        source->getHeight(sourceTarget, sourceLevel) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTextureLevel);
        return false;
    }

    if (x < 0 || y < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
        return false;
    }

    if (width < 0 || height < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
        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_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
        return false;
    }

    const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
    if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_OPERATION, kInvalidInternalFormat,
                                sourceFormat.info->internalFormat);
        return false;
    }

    if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    Texture *dest = context->getTexture(destId);
    if (dest == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
        return false;
    }

    if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTextureType);
        return false;
    }

    if (!ValidImageSizeParameters(context, entryPoint, dest->getType(), destLevel, width, height, 1,
                                  true))
    {
        // Error already generated.
        return false;
    }

    if (!IsValidCopyTextureDestinationLevel(context, dest->getType(), destLevel, width, height))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return false;
    }

    if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDestinationLevelNotDefined);
        return false;
    }

    const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
    if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormatCombination);
        return false;
    }

    if (sourceType == TextureType::External && destFormat.isInt() &&
        !context->getExtensions().EGLImageExternalEssl3OES)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kANGLECopyTextureMissingRequiredExtension);
        return false;
    }

    if (xoffset < 0 || yoffset < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
        return false;
    }

    if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
        static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
        return false;
    }

    if (source == dest && sourceLevel == destLevel)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSourceTextureSameAsDestTexture);
        return false;
    }

    return true;
}

bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           TextureID sourceId,
                                           TextureID destId)
{
    const Texture *source = context->getTexture(sourceId);
    if (source == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTexture);
        return false;
    }

    if (source->getType() != TextureType::_2D)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidSourceTextureType);
        return false;
    }

    if (source->getWidth(TextureTarget::_2D, 0) == 0 ||
        source->getHeight(TextureTarget::_2D, 0) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureLevelZeroDefined);
        return false;
    }

    const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0);
    if (!sourceFormat.info->compressed)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSourceTextureMustBeCompressed);
        return false;
    }

    const Texture *dest = context->getTexture(destId);
    if (dest == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTexture);
        return false;
    }

    if (dest->getType() != TextureType::_2D)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidDestinationTextureType);
        return false;
    }

    if (dest->getImmutableFormat())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDestinationImmutable);
        return false;
    }

    if (source == dest)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSourceTextureSameAsDestTexture);
        return false;
    }

    return true;
}

bool ValidateCreateShader(const Context *context, angle::EntryPoint entryPoint, ShaderType type)
{
    switch (type)
    {
        case ShaderType::Vertex:
        case ShaderType::Fragment:
            break;

        case ShaderType::Compute:
            if (context->getClientVersion() < ES_3_1)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES31Required);
                return false;
            }
            break;

        case ShaderType::Geometry:
            if (!context->getExtensions().geometryShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidShaderType);
                return false;
            }
            break;

        case ShaderType::TessControl:
            if (!context->getExtensions().tessellationShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidShaderType);
                return false;
            }
            break;

        case ShaderType::TessEvaluation:
            if (!context->getExtensions().tessellationShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidShaderType);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidShaderType);
            return false;
    }

    return true;
}

bool ValidateBufferData(const Context *context,
                        angle::EntryPoint entryPoint,
                        BufferBinding target,
                        GLsizeiptr size,
                        const void *data,
                        BufferUsage usage)
{
    if (size < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
        return false;
    }

    const Limitations &limitations = context->getLimitations();
    if (static_cast<size_t>(size) > limitations.maxBufferBytes)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferSizeLimitation);
        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->getClientVersion() < ES_3_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferUsage);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferUsage);
            return false;
    }

    if (!context->isValidBufferBinding(target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTarget);
        return false;
    }

    Buffer *buffer = context->getState().getTargetBuffer(target);

    if (!buffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
        return false;
    }

    // Do some additional WebGL-specific validation
    if (ANGLE_UNLIKELY(context->isWebGL() || context->isHardenedContext()))
    {
        if (buffer->hasTFBBindingConflict())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
            return false;
        }

        const TransformFeedback *transformFeedbackObject =
            context->getState().getCurrentTransformFeedback();
        if (transformFeedbackObject && transformFeedbackObject->isActive() &&
            !transformFeedbackObject->isPaused() &&
            transformFeedbackObject->isBufferBound(buffer->id()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
            return false;
        }
    }

    if (buffer->isImmutable())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferImmutable);
        return false;
    }

    return true;
}

bool ValidateBufferSubData(const Context *context,
                           angle::EntryPoint entryPoint,
                           BufferBinding target,
                           GLintptr offset,
                           GLsizeiptr size,
                           const void *data)
{
    if (size < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
        return false;
    }

    if (offset < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
        return false;
    }

    if (!context->isValidBufferBinding(target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTarget);
        return false;
    }

    Buffer *buffer = context->getState().getTargetBuffer(target);

    if (!buffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
        return false;
    }

    // EXT_buffer_storage allows persistently mapped buffers to be updated via glBufferSubData
    bool isPersistent = (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;

    // Verify that buffer is not currently mapped unless persistent
    if (buffer->isMapped() && !isPersistent)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
        return false;
    }

    // Do some additional WebGL-specific validation
    if (ANGLE_UNLIKELY(context->isWebGL() || context->isHardenedContext()))
    {
        if (buffer->hasTFBBindingConflict())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
            return false;
        }

        const TransformFeedback *transformFeedbackObject =
            context->getState().getCurrentTransformFeedback();
        if (transformFeedbackObject && transformFeedbackObject->isActive() &&
            !transformFeedbackObject->isPaused() &&
            transformFeedbackObject->isBufferBound(buffer->id()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferBoundForTransformFeedback);
            return false;
        }
    }

    if (buffer->isImmutable() &&
        (buffer->getStorageExtUsageFlags() & GL_DYNAMIC_STORAGE_BIT_EXT) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotUpdatable);
        return false;
    }

    // Check for possible overflow of size + offset
    angle::CheckedNumeric<decltype(size + offset)> checkedSize(size);
    checkedSize += offset;
    if (!checkedSize.IsValid())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kParamOverflow);
        return false;
    }

    if (size + offset > buffer->getSize())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInsufficientBufferSize);
        return false;
    }

    return true;
}

bool ValidateRequestExtensionANGLE(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   const GLchar *name)
{
    if (!context->isExtensionRequestable(name))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotRequestable);
        return false;
    }

    return true;
}

bool ValidateActiveTexture(const PrivateState &state,
                           ErrorSet *errors,
                           angle::EntryPoint entryPoint,
                           GLenum texture)
{
    if (state.getClientVersion() < ES_2_0)
    {
        return ValidateMultitextureUnit(state, errors, entryPoint, texture);
    }

    if (texture < GL_TEXTURE0 ||
        texture >
            GL_TEXTURE0 + static_cast<GLuint>(state.getCaps().maxCombinedTextureImageUnits) - 1)
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCombinedImageUnit);
        return false;
    }

    return true;
}

bool ValidateAttachShader(const Context *context,
                          angle::EntryPoint entryPoint,
                          ShaderProgramID program,
                          ShaderProgramID shader)
{
    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    if (programObject->getAttachedShader(shaderObject->getType()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kShaderAttachmentHasShader);
        return false;
    }

    return true;
}

bool ValidateBindAttribLocation(const Context *context,
                                angle::EntryPoint entryPoint,
                                ShaderProgramID program,
                                GLuint index,
                                const GLchar *name)
{
    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
        return false;
    }

    if (name == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kAttributeNameNull);
        return false;
    }

    if (context->nameStartsWithReservedPrefix(name))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNameStartsWithReservedPrefix);
        return false;
    }

    if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name))
    {
        // Error already generated.
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateBindFramebuffer(const Context *context,
                             angle::EntryPoint entryPoint,
                             GLenum target,
                             FramebufferID framebuffer)
{
    return ValidateBindFramebufferBase(context, entryPoint, target, framebuffer);
}

bool ValidateBindRenderbuffer(const Context *context,
                              angle::EntryPoint entryPoint,
                              GLenum target,
                              RenderbufferID renderbuffer)
{
    return ValidateBindRenderbufferBase(context, entryPoint, target, renderbuffer);
}

static bool ValidBlendEquationMode(const PrivateState &state, ErrorSet *errors, 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 state.getClientVersion() >= ES_3_0 || state.getExtensions().blendMinmaxEXT;

        default:
            return false;
    }
}

static bool ValidAdvancedBlendEquationMode(const PrivateState &state, GLenum mode)
{
    switch (mode)
    {
        case GL_MULTIPLY_KHR:
        case GL_SCREEN_KHR:
        case GL_OVERLAY_KHR:
        case GL_DARKEN_KHR:
        case GL_LIGHTEN_KHR:
        case GL_COLORDODGE_KHR:
        case GL_COLORBURN_KHR:
        case GL_HARDLIGHT_KHR:
        case GL_SOFTLIGHT_KHR:
        case GL_DIFFERENCE_KHR:
        case GL_EXCLUSION_KHR:
        case GL_HSL_HUE_KHR:
        case GL_HSL_SATURATION_KHR:
        case GL_HSL_COLOR_KHR:
        case GL_HSL_LUMINOSITY_KHR:
            return state.getClientVersion() >= ES_3_2 ||
                   state.getExtensions().blendEquationAdvancedKHR;

        default:
            return false;
    }
}

bool ValidateBlendEquation(const PrivateState &state,
                           ErrorSet *errors,
                           angle::EntryPoint entryPoint,
                           GLenum mode)
{
    if (ValidBlendEquationMode(state, errors, mode))
    {
        return true;
    }

    if (ValidAdvancedBlendEquationMode(state, mode))
    {
        if (state.getPixelLocalStorageActivePlanes() != 0)
        {
            // INVALID_OPERATION is generated by BlendEquation*() if <mode> is one of the advanced
            // blend equations defined in KHR_blend_equation_advanced.
            errors->validationError(entryPoint, GL_INVALID_OPERATION,
                                    kPLSAdvancedBlendNotSupported);
            return false;
        }
        return true;
    }

    errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
    return false;
}

bool ValidateBlendEquationSeparate(const PrivateState &state,
                                   ErrorSet *errors,
                                   angle::EntryPoint entryPoint,
                                   GLenum modeRGB,
                                   GLenum modeAlpha)
{
    if (!ValidBlendEquationMode(state, errors, modeRGB))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
        return false;
    }

    if (!ValidBlendEquationMode(state, errors, modeAlpha))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
        return false;
    }

    return true;
}

bool ValidateBlendFunc(const PrivateState &state,
                       ErrorSet *errors,
                       angle::EntryPoint entryPoint,
                       GLenum sfactor,
                       GLenum dfactor)
{
    return ValidateBlendFuncSeparate(state, errors, entryPoint, sfactor, dfactor, sfactor, dfactor);
}

bool ValidateBlendFuncSeparate(const PrivateState &state,
                               ErrorSet *errors,
                               angle::EntryPoint entryPoint,
                               GLenum srcRGB,
                               GLenum dstRGB,
                               GLenum srcAlpha,
                               GLenum dstAlpha)
{
    if (!ValidateSrcBlendFunc(state, errors, entryPoint, srcRGB) ||
        !ValidateDstBlendFunc(state, errors, entryPoint, dstRGB) ||
        !ValidateSrcBlendFunc(state, errors, entryPoint, srcAlpha) ||
        !ValidateDstBlendFunc(state, errors, entryPoint, dstAlpha))
    {
        return false;
    }

    if (state.getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc || state.isWebGL())
    {
        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)
        {
            if (state.isWebGL())
            {
                errors->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidConstantColor);
                return false;
            }

            WARN() << kConstantColorAlphaLimitation;
            errors->validationError(entryPoint, GL_INVALID_OPERATION,
                                    kConstantColorAlphaLimitation);
            return false;
        }
    }

    return true;
}

bool ValidateGetString(const Context *context, angle::EntryPoint entryPoint, 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().requestExtensionANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
                return false;
            }
            break;

        case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
            if (!context->getExtensions().getSerializedContextStringANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidName);
            return false;
    }

    return true;
}

bool ValidateLineWidth(const PrivateState &state,
                       ErrorSet *errors,
                       angle::EntryPoint entryPoint,
                       GLfloat width)
{
    if (width <= 0.0f || isNaN(width))
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidWidth);
        return false;
    }

    return true;
}

bool ValidateDepthRangef(const PrivateState &state,
                         ErrorSet *errors,
                         angle::EntryPoint entryPoint,
                         GLfloat zNear,
                         GLfloat zFar)
{
    if (state.isWebGL() && zNear > zFar)
    {
        errors->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDepthRange);
        return false;
    }

    return true;
}

bool ValidateRenderbufferStorage(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 GLenum target,
                                 GLenum internalformat,
                                 GLsizei width,
                                 GLsizei height)
{
    return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, 0, internalformat,
                                                     width, height);
}

bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
                                                 angle::EntryPoint entryPoint,
                                                 GLenum target,
                                                 GLsizei samples,
                                                 GLenum internalformat,
                                                 GLsizei width,
                                                 GLsizei height)
{
    // 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_VALUE is
    // generated.
    if (samples > context->getCaps().maxSamples)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesOutOfRange);
        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 getMaxSamples method is only guaranteed to be valid when the context is ES3.
    if (context->getClientVersion() >= ES_3_0)
    {
        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
        if (static_cast<GLuint>(samples) > formatCaps.sampleCounts.getMaxSamples())
        {
            ANGLE_VALIDATION_ERROR(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
            return false;
        }
    }

    return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
                                                     internalformat, width, height);
}

bool ValidateCheckFramebufferStatus(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum target)
{
    if (!ValidFramebufferTarget(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
        return false;
    }

    return true;
}

bool ValidateCompileShader(const Context *context,
                           angle::EntryPoint entryPoint,
                           ShaderProgramID shader)
{
    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateCullFace(const PrivateState &state,
                      ErrorSet *errors,
                      angle::EntryPoint entryPoint,
                      CullFaceMode mode)
{
    switch (mode)
    {
        case CullFaceMode::Front:
        case CullFaceMode::Back:
        case CullFaceMode::FrontAndBack:
            break;

        default:
            errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCullMode);
            return false;
    }

    return true;
}

bool ValidateDeleteProgram(const Context *context,
                           angle::EntryPoint entryPoint,
                           ShaderProgramID program)
{
    if (program.value == 0)
    {
        return true;  // no-op
    }

    if (!context->getProgramResolveLink(program))
    {
        if (context->getShaderNoResolveCompile(program))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedProgramName);
            return false;
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramName);
            return false;
        }
    }

    return true;
}

bool ValidateDeleteShader(const Context *context,
                          angle::EntryPoint entryPoint,
                          ShaderProgramID shader)
{
    if (shader.value == 0)
    {
        return true;  // no-op
    }

    if (!context->getShaderNoResolveCompile(shader))
    {
        if (context->getProgramResolveLink(shader))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidShaderName);
            return false;
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExpectedShaderName);
            return false;
        }
    }

    return true;
}

bool ValidateDepthFunc(const PrivateState &state,
                       ErrorSet *errors,
                       angle::EntryPoint entryPoint,
                       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:
            errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, func);
            return false;
    }

    return true;
}

bool ValidateDetachShader(const Context *context,
                          angle::EntryPoint entryPoint,
                          ShaderProgramID program,
                          ShaderProgramID shader)
{
    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType());
    if (attachedShader != shaderObject)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kShaderToDetachMustBeAttached);
        return false;
    }

    return true;
}

bool ValidateDisableVertexAttribArray(const PrivateState &state,
                                      ErrorSet *errors,
                                      angle::EntryPoint entryPoint,
                                      GLuint index)
{
    if (index >= static_cast<GLuint>(state.getCaps().maxVertexAttributes))
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
        return false;
    }

    return true;
}

bool ValidateEnableVertexAttribArray(const PrivateState &state,
                                     ErrorSet *errors,
                                     angle::EntryPoint entryPoint,
                                     GLuint index)
{
    if (index >= static_cast<GLuint>(state.getCaps().maxVertexAttributes))
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
        return false;
    }

    return true;
}

bool ValidateFrontFace(const PrivateState &state,
                       ErrorSet *errors,
                       angle::EntryPoint entryPoint,
                       GLenum mode)
{
    switch (mode)
    {
        case GL_CW:
        case GL_CCW:
            break;
        default:
            errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode);
            return false;
    }

    return true;
}

bool ValidateGetActiveAttrib(const Context *context,
                             angle::EntryPoint entryPoint,
                             ShaderProgramID program,
                             GLuint index,
                             GLsizei bufsize,
                             const GLsizei *length,
                             const GLint *size,
                             const GLenum *type,
                             const GLchar *name)
{
    if (bufsize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    if (index >= static_cast<GLuint>(programObject->getExecutable().getProgramInputs().size()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
        return false;
    }

    return true;
}

bool ValidateGetActiveUniform(const Context *context,
                              angle::EntryPoint entryPoint,
                              ShaderProgramID program,
                              GLuint index,
                              GLsizei bufsize,
                              const GLsizei *length,
                              const GLint *size,
                              const GLenum *type,
                              const GLchar *name)
{
    if (bufsize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    if (index >= programObject->getExecutable().getUniforms().size())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
        return false;
    }

    if (bufsize > 0 && name == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidName);
        return false;
    }

    return true;
}

bool ValidateGetAttachedShaders(const Context *context,
                                angle::EntryPoint entryPoint,
                                ShaderProgramID program,
                                GLsizei maxcount,
                                const GLsizei *count,
                                const ShaderProgramID *shaders)
{
    if (shaders == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL);
        return false;
    }

    if (maxcount < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeMaxCount);
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateGetAttribLocation(const Context *context,
                               angle::EntryPoint entryPoint,
                               ShaderProgramID program,
                               const GLchar *name)
{
    if (name == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kAttributeNameNull);
        return false;
    }

    if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name))
    {
        // Error already generated.
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    if (!programObject->isLinked())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
        return false;
    }

    return true;
}

bool ValidateGetBooleanv(const Context *context,
                         angle::EntryPoint entryPoint,
                         GLenum pname,
                         const GLboolean *data)
{
    return ValidateStateQuery(context, entryPoint, pname, data, nullptr);
}

bool ValidateGetFloatv(const Context *context,
                       angle::EntryPoint entryPoint,
                       GLenum pname,
                       const GLfloat *data)
{
    return ValidateStateQuery(context, entryPoint, pname, data, nullptr);
}

bool ValidateGetIntegerv(const Context *context,
                         angle::EntryPoint entryPoint,
                         GLenum pname,
                         const GLint *data)
{
    return ValidateStateQuery(context, entryPoint, pname, data, nullptr);
}

bool ValidateGetProgramInfoLog(const Context *context,
                               angle::EntryPoint entryPoint,
                               ShaderProgramID program,
                               GLsizei bufsize,
                               const GLsizei *length,
                               const GLchar *infolog)
{
    if (bufsize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateGetShaderInfoLog(const Context *context,
                              angle::EntryPoint entryPoint,
                              ShaderProgramID shader,
                              GLsizei bufsize,
                              const GLsizei *length,
                              const GLchar *infolog)
{
    if (bufsize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateGetShaderPrecisionFormat(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      GLenum shadertype,
                                      GLenum precisiontype,
                                      const GLint *range,
                                      const GLint *precision)
{
    if (range == nullptr || precision == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL);
        return false;
    }

    switch (shadertype)
    {
        case GL_VERTEX_SHADER:
        case GL_FRAGMENT_SHADER:
            break;
        case GL_COMPUTE_SHADER:
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUnimplementedComputeShaderPrecision);
            return false;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidShaderType);
            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_ERROR(GL_INVALID_ENUM, kInvalidPrecision);
            return false;
    }

    return true;
}

bool ValidateGetShaderSource(const Context *context,
                             angle::EntryPoint entryPoint,
                             ShaderProgramID shader,
                             GLsizei bufsize,
                             const GLsizei *length,
                             const GLchar *source)
{
    if (bufsize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateGetUniformLocation(const Context *context,
                                angle::EntryPoint entryPoint,
                                ShaderProgramID program,
                                const GLchar *name)
{
    if (name == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kUniformNameNull);
        return false;
    }

    if (context->isWebGL() && !ValidateWebGLName(context, entryPoint, name))
    {
        // Error already generated.
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    if (!programObject->isLinked())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
        return false;
    }

    return true;
}

bool ValidateHint(const PrivateState &state,
                  ErrorSet *errors,
                  angle::EntryPoint entryPoint,
                  GLenum target,
                  GLenum mode)
{
    switch (mode)
    {
        case GL_FASTEST:
        case GL_NICEST:
        case GL_DONT_CARE:
            break;

        default:
            errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode);
            return false;
    }

    switch (target)
    {
        case GL_GENERATE_MIPMAP_HINT:
            break;

        case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
            if (state.getClientVersion() < ES_3_0 && !state.getExtensions().standardDerivativesOES)
            {
                errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
                return false;
            }
            break;

        case GL_PERSPECTIVE_CORRECTION_HINT:
        case GL_POINT_SMOOTH_HINT:
        case GL_LINE_SMOOTH_HINT:
        case GL_FOG_HINT:
            if (state.getClientVersion() >= ES_2_0)
            {
                errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
                return false;
            }
            break;

        default:
            errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
            return false;
    }

    return true;
}

bool ValidatePixelStorei(const PrivateState &state,
                         ErrorSet *errors,
                         angle::EntryPoint entryPoint,
                         PackUnpackParameter pnamePacked,
                         GLint param)
{
    const Version &clientVersion = state.getClientVersion();
    const Extensions &extensions = state.getExtensions();

    bool isPnameSupported = false;
    switch (pnamePacked)
    {
        case PackUnpackParameter::UnpackAlignment:
        case PackUnpackParameter::PackAlignment:
            if (ANGLE_UNLIKELY(param != 1 && param != 2 && param != 4 && param != 8))
            {
                errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPackUnpackAlignment);
                return false;
            }
            return true;
        case PackUnpackParameter::UnpackRowLength:
        case PackUnpackParameter::UnpackSkipRows:
        case PackUnpackParameter::UnpackSkipPixels:
            isPnameSupported = clientVersion >= ES_3_0 || extensions.unpackSubimageEXT;
            break;
        case PackUnpackParameter::PackRowLength:
        case PackUnpackParameter::PackSkipRows:
        case PackUnpackParameter::PackSkipPixels:
            isPnameSupported = clientVersion >= ES_3_0 || extensions.packSubimageNV;
            break;
        case PackUnpackParameter::UnpackSkipImages:
        case PackUnpackParameter::UnpackImageHeight:
            isPnameSupported = clientVersion >= ES_3_0;
            break;
        case PackUnpackParameter::PackReverseRowOrder:
            if (extensions.packReverseRowOrderANGLE)
            {
                // Any value is valid for this parameter.
                return true;
            }
            break;
        default:
            errors->validationError(entryPoint, GL_INVALID_ENUM, kParameterNameUnknown);
            return false;
    }

    if (ANGLE_UNLIKELY(!isPnameSupported))
    {
        errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kParameterNameUnsupported,
                                 ToGLenum(pnamePacked));
        return false;
    }

    if (ANGLE_UNLIKELY(param < 0))
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kNegativeParam);
        return false;
    }

    return true;
}

bool ValidateScissor(const PrivateState &state,
                     ErrorSet *errors,
                     angle::EntryPoint entryPoint,
                     GLint x,
                     GLint y,
                     GLsizei width,
                     GLsizei height)
{
    if (width < 0 || height < 0)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
        return false;
    }

    return true;
}

bool ValidateShaderBinary(const Context *context,
                          angle::EntryPoint entryPoint,
                          GLsizei n,
                          const ShaderProgramID *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())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidShaderBinaryFormat);
        return false;
    }

    ASSERT(binaryformat == GL_SHADER_BINARY_ANGLE);

    if (n <= 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidShaderCount);
        return false;
    }

    if (length < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeLength);
        return false;
    }

    // GL_SHADER_BINARY_ANGLE shader binaries contain a single shader.
    if (n > 1)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidShaderCount);
        return false;
    }

    Shader *shaderObject = GetValidShader(context, entryPoint, shaders[0]);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    // Check ANGLE version used to generate binary matches the current version.
    BinaryInputStream stream(angle::Span(static_cast<const uint8_t *>(binary), length));
    std::vector<uint8_t> versionString(angle::GetANGLEShaderProgramVersionHashSize());
    stream.readBytes(versionString);
    if (memcmp(versionString.data(), angle::GetANGLEShaderProgramVersion(), versionString.size()) !=
        0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidShaderBinary);
        return false;
    }

    // Check that the shader type of the binary matches the type of target shader.
    gl::ShaderType shaderType;
    stream.readEnum(&shaderType);
    if (shaderObject->getType() != shaderType)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedShaderBinaryType);
        return false;
    }

    return true;
}

bool ValidateShaderSource(const Context *context,
                          angle::EntryPoint entryPoint,
                          ShaderProgramID shader,
                          GLsizei count,
                          const GLchar *const *string,
                          const GLint *length)
{
    if (count < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
        return false;
    }

    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
    if (shaderObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateStencilFunc(const PrivateState &state,
                         ErrorSet *errors,
                         angle::EntryPoint entryPoint,
                         GLenum func,
                         GLint ref,
                         GLuint mask)
{
    if (!IsValidStencilFunc(func))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    return true;
}

bool ValidateStencilFuncSeparate(const PrivateState &state,
                                 ErrorSet *errors,
                                 angle::EntryPoint entryPoint,
                                 GLenum face,
                                 GLenum func,
                                 GLint ref,
                                 GLuint mask)
{
    if (!IsValidStencilFace(face))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    if (!IsValidStencilFunc(func))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    return true;
}

bool ValidateStencilMaskSeparate(const PrivateState &state,
                                 ErrorSet *errors,
                                 angle::EntryPoint entryPoint,
                                 GLenum face,
                                 GLuint mask)
{
    if (!IsValidStencilFace(face))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    return true;
}

bool ValidateStencilOp(const PrivateState &state,
                       ErrorSet *errors,
                       angle::EntryPoint entryPoint,
                       GLenum fail,
                       GLenum zfail,
                       GLenum zpass)
{
    if (!IsValidStencilOp(fail))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    if (!IsValidStencilOp(zfail))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    if (!IsValidStencilOp(zpass))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    return true;
}

bool ValidateStencilOpSeparate(const PrivateState &state,
                               ErrorSet *errors,
                               angle::EntryPoint entryPoint,
                               GLenum face,
                               GLenum fail,
                               GLenum zfail,
                               GLenum zpass)
{
    if (!IsValidStencilFace(face))
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
        return false;
    }

    return ValidateStencilOp(state, errors, entryPoint, fail, zfail, zpass);
}

bool ValidateValidateProgram(const Context *context,
                             angle::EntryPoint entryPoint,
                             ShaderProgramID program)
{
    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateViewport(const PrivateState &state,
                      ErrorSet *errors,
                      angle::EntryPoint entryPoint,
                      GLint x,
                      GLint y,
                      GLsizei width,
                      GLsizei height)
{
    if (width < 0 || height < 0)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kViewportNegativeSize);
        return false;
    }

    return true;
}

bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
                                                 angle::EntryPoint entryPoint,
                                                 GLenum target,
                                                 GLenum attachment,
                                                 GLenum pname,
                                                 const GLint *params)
{
    return ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
                                                           pname, nullptr);
}

bool ValidateGetProgramiv(const Context *context,
                          angle::EntryPoint entryPoint,
                          ShaderProgramID programPacked,
                          GLenum pname,
                          const GLint *params)
{
    return ValidateGetProgramivBase(context, entryPoint, programPacked, pname, nullptr);
}

bool ValidateCopyTexImage2D(const Context *context,
                            angle::EntryPoint entryPoint,
                            TextureTarget target,
                            GLint level,
                            GLenum internalformat,
                            GLint x,
                            GLint y,
                            GLsizei width,
                            GLsizei height,
                            GLint border)
{
    if (context->getClientVersion() < ES_3_0)
    {
        return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, internalformat,
                                                 false, 0, 0, x, y, width, height, border);
    }

    return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, internalformat,
                                               false, 0, 0, 0, x, y, width, height, border);
}

bool ValidateCopyTexSubImage2D(const Context *context,
                               angle::EntryPoint entryPoint,
                               TextureTarget target,
                               GLint level,
                               GLint xoffset,
                               GLint yoffset,
                               GLint x,
                               GLint y,
                               GLsizei width,
                               GLsizei height)
{
    if (context->getClientVersion() < ES_3_0)
    {
        return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, GL_NONE, true,
                                                 xoffset, yoffset, x, y, width, height, 0);
    }

    return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
                                               xoffset, yoffset, 0, x, y, width, height, 0);
}

bool ValidateCopyTexSubImage3DOES(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  TextureTarget target,
                                  GLint level,
                                  GLint xoffset,
                                  GLint yoffset,
                                  GLint zoffset,
                                  GLint x,
                                  GLint y,
                                  GLsizei width,
                                  GLsizei height)
{
    return ValidateCopyTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset,
                                     x, y, width, height);
}

bool ValidateDeleteBuffers(const Context *context,
                           angle::EntryPoint entryPoint,
                           GLint n,
                           const BufferID *buffers)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, buffers);
}

bool ValidateDeleteFramebuffers(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLint n,
                                const FramebufferID *framebuffers)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n,
                               framebuffers);
}

bool ValidateDeleteRenderbuffers(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 GLint n,
                                 const RenderbufferID *renderbuffers)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n,
                               renderbuffers);
}

bool ValidateDeleteTextures(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLint n,
                            const TextureID *textures)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, textures);
}

bool ValidateDisable(const PrivateState &state,
                     ErrorSet *errors,
                     angle::EntryPoint entryPoint,
                     GLenum cap)
{
    if (!ValidCap(state, errors, cap, false))
    {
        errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
        return false;
    }

    if (state.getPixelLocalStorageActivePlanes() != 0)
    {
        if (IsCapBannedWithActivePLS(cap))
        {
            errors->validationErrorF(entryPoint, GL_INVALID_OPERATION, kPLSCapNotAllowed, cap);
            return false;
        }
    }

    return true;
}

bool ValidateEnable(const PrivateState &state,
                    ErrorSet *errors,
                    angle::EntryPoint entryPoint,
                    GLenum cap)
{
    if (!ValidCap(state, errors, cap, false))
    {
        errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
        return false;
    }

    if (state.getPixelLocalStorageActivePlanes() != 0)
    {
        if (IsCapBannedWithActivePLS(cap))
        {
            errors->validationErrorF(entryPoint, GL_INVALID_OPERATION, kPLSCapNotAllowed, cap);
            return false;
        }
    }

    return true;
}

bool ValidateFramebufferRenderbuffer(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLenum target,
                                     GLenum attachment,
                                     GLenum renderbuffertarget,
                                     RenderbufferID renderbuffer)
{
    return ValidateFramebufferRenderbufferBase(context, entryPoint, target, attachment,
                                               renderbuffertarget, renderbuffer);
}

bool ValidateFramebufferTexture2D(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLenum target,
                                  GLenum attachment,
                                  TextureTarget textarget,
                                  TextureID texture,
                                  GLint level)
{
    // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
    // extension
    if (context->getClientVersion() < ES_3_0 && !context->getExtensions().fboRenderMipmapOES &&
        level != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
        return false;
    }

    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
    {
        return false;
    }

    if (texture.value != 0)
    {
        Texture *tex = context->getTexture(texture);
        ASSERT(tex);

        const Caps &caps = context->getCaps();

        switch (textarget)
        {
            case TextureTarget::_2D:
            {
                if (level > log2(caps.max2DTextureSize))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
                    return false;
                }
                if (tex->getType() != TextureType::_2D)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
                    return false;
                }
            }
            break;

            case TextureTarget::Rectangle:
            {
                if (level != 0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
                    return false;
                }
                if (tex->getType() != TextureType::Rectangle)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureTargetMismatch);
                    return false;
                }
            }
            break;

            case TextureTarget::CubeMapNegativeX:
            case TextureTarget::CubeMapNegativeY:
            case TextureTarget::CubeMapNegativeZ:
            case TextureTarget::CubeMapPositiveX:
            case TextureTarget::CubeMapPositiveY:
            case TextureTarget::CubeMapPositiveZ:
            {
                if (level > log2(caps.maxCubeMapTextureSize))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
                    return false;
                }
                if (tex->getType() != TextureType::CubeMap)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureTargetMismatch);
                    return false;
                }
            }
            break;

            case TextureTarget::_2DMultisample:
            {
                if (context->getClientVersion() < ES_3_1 &&
                    !context->getExtensions().textureMultisampleANGLE)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                           kMultisampleTextureExtensionOrES31Required);
                    return false;
                }

                if (level != 0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kLevelNotZero);
                    return false;
                }
                if (tex->getType() != TextureType::_2DMultisample)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureTargetMismatch);
                    return false;
                }
            }
            break;

            case TextureTarget::External:
            {
                if (!context->getExtensions().YUVTargetEXT)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kYUVTargetExtensionRequired);
                    return false;
                }

                if (attachment != GL_COLOR_ATTACHMENT0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
                    return false;
                }

                if (tex->getType() != TextureType::External)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureTargetMismatch);
                    return false;
                }
            }
            break;

            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
                return false;
        }
    }

    return true;
}

bool ValidateFramebufferTexture3DOES(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLenum target,
                                     GLenum attachment,
                                     TextureTarget textargetPacked,
                                     TextureID texture,
                                     GLint level,
                                     GLint zoffset)
{
    // We don't call into a base ValidateFramebufferTexture3D here because
    // it doesn't exist for OpenGL ES. This function is replaced by
    // FramebufferTextureLayer in ES 3.x, which has broader support.

    // Attachments are required to be bound to level 0 without ES3 or the
    // GL_OES_fbo_render_mipmap extension
    if (context->getClientVersion() < ES_3_0 && !context->getExtensions().fboRenderMipmapOES &&
        level != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
        return false;
    }

    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
    {
        return false;
    }

    if (texture.value != 0)
    {
        Texture *tex = context->getTexture(texture);
        ASSERT(tex);

        const Caps &caps = context->getCaps();

        switch (textargetPacked)
        {
            case TextureTarget::_3D:
            {
                if (level > log2(caps.max3DTextureSize))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
                    return false;
                }
                if (zoffset >= caps.max3DTextureSize)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidZOffset);
                    return false;
                }
                if (tex->getType() != TextureType::_3D)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureType);
                    return false;
                }
            }
            break;

            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
                return false;
        }
    }

    return true;
}

bool ValidateIsEnabled(const PrivateState &state,
                       ErrorSet *errors,
                       angle::EntryPoint entryPoint,
                       GLenum cap)
{
    if (!ValidCap(state, errors, cap, true))
    {
        errors->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
        return false;
    }

    return true;
}

bool ValidateLinkProgram(const Context *context,
                         angle::EntryPoint entryPoint,
                         ShaderProgramID program)
{
    if (context->hasActiveTransformFeedback(program))
    {
        // ES 3.0.4 section 2.15 page 91
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackActiveDuringLink);
        return false;
    }

    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    return true;
}

bool ValidateUseProgram(const Context *context,
                        angle::EntryPoint entryPoint,
                        ShaderProgramID program)
{
    if (program.value != 0)
    {
        Program *programObject = context->getProgramResolveLink(program);
        if (!programObject)
        {
            // ES 3.1.0 section 7.3 page 72
            if (context->getShaderNoResolveCompile(program))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedProgramName);
                return false;
            }
            else
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramName);
                return false;
            }
        }
        if (!programObject->isLinked())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
            return false;
        }
    }
    if (context->getState().isTransformFeedbackActiveUnpaused())
    {
        // ES 3.0.4 section 2.15 page 91
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackUseProgram);
        return false;
    }

    return true;
}

bool ValidateDeleteFencesNV(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLsizei n,
                            const FenceNVID *fences)
{
    if (n < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
        return false;
    }

    return true;
}

bool ValidateFinishFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
{
    FenceNV *fenceObject = context->getFenceNV(fence);

    if (fenceObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFence);
        return false;
    }

    if (!fenceObject->isSet())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFenceState);
        return false;
    }

    return true;
}

bool ValidateGenFencesNV(const Context *context,
                         angle::EntryPoint entryPoint,
                         GLsizei n,
                         const FenceNVID *fences)
{
    if (n < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
        return false;
    }

    return true;
}

bool ValidateGetFenceivNV(const Context *context,
                          angle::EntryPoint entryPoint,
                          FenceNVID fence,
                          GLenum pname,
                          const GLint *params)
{
    FenceNV *fenceObject = context->getFenceNV(fence);

    if (fenceObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFence);
        return false;
    }

    if (!fenceObject->isSet())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFenceState);
        return false;
    }

    switch (pname)
    {
        case GL_FENCE_STATUS_NV:
        case GL_FENCE_CONDITION_NV:
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
            return false;
    }

    return true;
}

bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            ShaderProgramID shader,
                                            GLsizei bufsize,
                                            const GLsizei *length,
                                            const GLchar *source)
{
    if (bufsize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    Shader *shaderObject = context->getShaderNoResolveCompile(shader);

    if (!shaderObject)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidShaderName);
        return false;
    }

    return true;
}

bool ValidateSetFenceNV(const Context *context,
                        angle::EntryPoint entryPoint,
                        FenceNVID fence,
                        GLenum condition)
{
    if (condition != GL_ALL_COMPLETED_NV)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFenceCondition);
        return false;
    }

    FenceNV *fenceObject = context->getFenceNV(fence);

    if (fenceObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFence);
        return false;
    }

    return true;
}

bool ValidateTestFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
{
    FenceNV *fenceObject = context->getFenceNV(fence);

    if (fenceObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFence);
        return false;
    }

    if (fenceObject->isSet() != GL_TRUE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFenceState);
        return false;
    }

    return true;
}

bool ValidateTexStorage2D(const Context *context,
                          angle::EntryPoint entryPoint,
                          TextureType targetPacked,
                          GLsizei levels,
                          GLenum internalformat,
                          GLsizei width,
                          GLsizei height)
{
    return ValidateTexStorage(context, entryPoint, targetPacked, levels, internalformat, width,
                              height, 1, TexImageDimension::_2D);
}

bool ValidateTexStorage3D(const Context *context,
                          angle::EntryPoint entryPoint,
                          TextureType targetPacked,
                          GLsizei levels,
                          GLenum internalformat,
                          GLsizei width,
                          GLsizei height,
                          GLsizei depth)
{
    return ValidateTexStorage(context, entryPoint, targetPacked, levels, internalformat, width,
                              height, depth, TexImageDimension::_3D);
}

bool ValidateTexStorage2DEXT(const Context *context,
                             angle::EntryPoint entryPoint,
                             TextureType type,
                             GLsizei levels,
                             GLenum internalformat,
                             GLsizei width,
                             GLsizei height)
{
    return ValidateTexStorage2D(context, entryPoint, type, levels, internalformat, width, height);
}

bool ValidateTexStorage3DEXT(const Context *context,
                             angle::EntryPoint entryPoint,
                             TextureType type,
                             GLsizei levels,
                             GLenum internalformat,
                             GLsizei width,
                             GLsizei height,
                             GLsizei depth)
{
    if (context->getClientVersion() < ES_3_0 && !context->getExtensions().texture3DOES)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    return ValidateTexStorage3D(context, entryPoint, type, levels, internalformat, width, height,
                                depth);
}

bool ValidateVertexAttribDivisorANGLE(const PrivateState &privateState,
                                      ErrorSet *errors,
                                      angle::EntryPoint entryPoint,
                                      GLuint index,
                                      GLuint divisor)
{
    return ValidateVertexAttribDivisor(privateState, errors, entryPoint, index, divisor);
}

bool ValidateVertexAttribDivisorEXT(const PrivateState &privateState,
                                    ErrorSet *errors,
                                    angle::EntryPoint entryPoint,
                                    GLuint index,
                                    GLuint divisor)
{
    return ValidateVertexAttribDivisor(privateState, errors, entryPoint, index, divisor);
}

bool ValidateTexImage3DOES(const Context *context,
                           angle::EntryPoint entryPoint,
                           TextureTarget target,
                           GLint level,
                           GLenum internalformat,
                           GLsizei width,
                           GLsizei height,
                           GLsizei depth,
                           GLint border,
                           GLenum format,
                           GLenum type,
                           const void *pixels)
{
    return ValidateTexImage3D(context, entryPoint, target, level, internalformat, width, height,
                              depth, border, format, type, pixels);
}

bool ValidateMultiDrawArraysANGLE(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  PrimitiveMode mode,
                                  const GLint *firsts,
                                  const GLsizei *counts,
                                  GLsizei drawcount)
{
    if (drawcount < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount);
        return false;
    }
    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
    {
        if (!ValidateDrawArraysCommon(context, entryPoint, mode, firsts[drawID], counts[drawID], 1))
        {
            return false;
        }
    }

    if (!ValidateDrawArraysTransformFeedbackBufferSize(context, entryPoint, counts, nullptr,
                                                       drawcount))
    {
        return false;
    }

    return true;
}

bool ValidateMultiDrawElementsANGLE(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    PrimitiveMode mode,
                                    const GLsizei *counts,
                                    DrawElementsType type,
                                    const GLvoid *const *indices,
                                    GLsizei drawcount)
{
    if (drawcount < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeDrawcount);
        return false;
    }
    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
    {
        if (!ValidateDrawElements(context, entryPoint, mode, counts[drawID], type, indices[drawID]))
        {
            return false;
        }
    }
    return true;
}

bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
                                                angle::EntryPoint entryPoint,
                                                GLenum target,
                                                GLenum attachment,
                                                TextureTarget textarget,
                                                TextureID texture,
                                                GLint level,
                                                GLsizei samples)
{
    // EXT_multisampled_render_to_texture states that the value of samples
    // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
    // otherwise GL_INVALID_VALUE is generated.
    if (samples < 0 || samples > context->getCaps().maxSamples)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesOutOfRange);
        return false;
    }

    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
    {
        return false;
    }

    // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than
    // the maximum sample number supported by this format is passed.
    // The getMaxSamples method is only guaranteed to be valid when the context is ES3.
    if (texture.value != 0 && context->getClientVersion() >= ES_3_0)
    {
        Texture *tex                  = context->getTexture(texture);
        GLenum sizedInternalFormat    = tex->getFormat(textarget, level).info->sizedInternalFormat;
        const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
        if (static_cast<GLuint>(samples) > formatCaps.sampleCounts.getMaxSamples())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
            return false;
        }
    }

    // Unless EXT_multisampled_render_to_texture2 is enabled, only color attachment 0 can be used.
    if (!context->getExtensions().multisampledRenderToTexture2EXT &&
        attachment != GL_COLOR_ATTACHMENT0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
        return false;
    }

    if (!ValidTexture2DDestinationTarget(context, textarget))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    return true;
}

bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
                                               angle::EntryPoint entryPoint,
                                               GLenum target,
                                               GLsizei samples,
                                               GLenum internalformat,
                                               GLsizei width,
                                               GLsizei height)
{
    if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
                                                   internalformat, width, height))
    {
        return false;
    }

    // EXT_multisampled_render_to_texture states that the value of samples
    // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
    // otherwise GL_INVALID_VALUE is generated.
    if (samples > context->getCaps().maxSamples)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesOutOfRange);
        return false;
    }

    // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on 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 getMaxSamples method is only guaranteed to be valid when the context is ES3.
    if (context->getClientVersion() >= ES_3_0)
    {
        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
        if (static_cast<GLuint>(samples) > formatCaps.sampleCounts.getMaxSamples())
        {
            ANGLE_VALIDATION_ERROR(GL_OUT_OF_MEMORY, kSamplesOutOfRange);
            return false;
        }
    }

    return true;
}

bool ValidateBlobCacheCallbacksANGLE(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLSETBLOBPROCANGLE set,
                                     GLGETBLOBPROCANGLE get,
                                     const void *userParam)
{
    if ((get == nullptr) != (set == nullptr))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlobCacheCallbacksUnbalanced);
        return false;
    }

    return true;
}

bool ValidateGetPointervANGLE(const Context *context,
                              angle::EntryPoint entryPoint,
                              GLenum pname,
                              void *const *params)
{
    return ValidateGetPointerv(context, entryPoint, pname, params);
}

void RecordBindTextureTypeError(const Context *context,
                                angle::EntryPoint entryPoint,
                                TextureType target)
{
    ASSERT(!context->getStateCache().isValidBindTextureType(target));

    switch (target)
    {
        case TextureType::Rectangle:
            ASSERT(!context->getExtensions().textureRectangleANGLE);
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureRectangleNotSupported);
            break;

        case TextureType::_3D:
        case TextureType::_2DArray:
            ASSERT(context->getClientVersion() < ES_3_0);
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
            break;

        case TextureType::_2DMultisample:
            ASSERT(context->getClientVersion() < ES_3_1 &&
                   !context->getExtensions().textureMultisampleANGLE);
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
            break;

        case TextureType::_2DMultisampleArray:
            ASSERT(context->getClientVersion() < ES_3_2 &&
                   !context->getExtensions().textureStorageMultisample2dArrayOES);
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionOrES32Required);
            break;

        case TextureType::External:
            ASSERT(!context->getExtensions().EGLImageExternalOES &&
                   !context->getExtensions().EGLStreamConsumerExternalNV);
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExternalTextureNotSupported);
            break;

        case TextureType::Buffer:
            ASSERT(!context->getExtensions().textureBufferOES &&
                   !context->getExtensions().textureBufferEXT);
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
    }
}

}  // namespace gl
