//
// 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.
//

// validationES.cpp: Validation functions for generic OpenGL ES entry point parameters

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_buffers
#endif

#include "libANGLE/validationES.h"

#include "libANGLE/Context.h"
#include "libANGLE/Display.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Image.h"
#include "libANGLE/PixelLocalStorage.h"
#include "libANGLE/Program.h"
#include "libANGLE/Query.h"
#include "libANGLE/Texture.h"
#include "libANGLE/TransformFeedback.h"
#include "libANGLE/angletypes.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/queryconversions.h"
#include "libANGLE/queryutils.h"
#include "libANGLE/validationES2.h"
#include "libANGLE/validationES3.h"

#include "common/mathutil.h"
#include "common/utilities.h"

using namespace angle;

namespace gl
{
using namespace err;

namespace
{
bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
{
    // List of compressed format that require that the texture size is smaller than or a multiple of
    // the compressed block size.
    switch (internalFormat)
    {
        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
        case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
        case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
        case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
        case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
        case GL_COMPRESSED_RED_RGTC1_EXT:
        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
        case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
        case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
        case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
            return true;

        default:
            return false;
    }
}

bool DifferenceCanOverflow(GLint a, GLint b)
{
    CheckedNumeric<GLint> checkedA(a);
    checkedA -= b;
    // Use negation to make sure that the difference can't overflow regardless of the order.
    checkedA = -checkedA;
    return !checkedA.IsValid();
}

bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
{
    switch (type)
    {
        // Types referenced in Table 3.4 of the ES 2.0.25 spec
        case GL_UNSIGNED_BYTE:
        case GL_UNSIGNED_SHORT_4_4_4_4:
        case GL_UNSIGNED_SHORT_5_5_5_1:
        case GL_UNSIGNED_SHORT_5_6_5:
            return context->getClientVersion() >= ES_2_0;

        // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
        case GL_BYTE:
        case GL_INT:
        case GL_SHORT:
        case GL_UNSIGNED_INT:
        case GL_UNSIGNED_INT_10F_11F_11F_REV:
        case GL_UNSIGNED_INT_2_10_10_10_REV:
        case GL_UNSIGNED_INT_5_9_9_9_REV:
        case GL_UNSIGNED_SHORT:
        case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
        case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
            return context->getClientVersion() >= ES_3_0;

        case GL_FLOAT:
            return context->getClientVersion() >= ES_3_0 ||
                   context->getExtensions().textureFloatOES ||
                   context->getExtensions().colorBufferHalfFloatEXT;

        case GL_HALF_FLOAT:
            return context->getClientVersion() >= ES_3_0 ||
                   context->getExtensions().textureHalfFloatOES;

        case GL_HALF_FLOAT_OES:
            return context->getExtensions().colorBufferHalfFloatEXT;

        default:
            return false;
    }
}

bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
{
    switch (format)
    {
        // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
        case GL_RGBA:
        case GL_RGB:
        case GL_ALPHA:
            return context->getClientVersion() >= ES_2_0;

        // Formats referenced in Table 3.2 of the ES 3.0.5 spec
        case GL_RG:
        case GL_RED:
        case GL_RGBA_INTEGER:
        case GL_RGB_INTEGER:
        case GL_RG_INTEGER:
        case GL_RED_INTEGER:
            return context->getClientVersion() >= ES_3_0;

        case GL_SRGB_ALPHA_EXT:
        case GL_SRGB_EXT:
            return context->getExtensions().sRGBEXT;

        case GL_BGRA_EXT:
            return context->getExtensions().readFormatBgraEXT;

        case GL_RGBX8_ANGLE:
            return context->getExtensions().rgbxInternalFormatANGLE;

        default:
            return false;
    }
}

bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
                                                const gl::InternalFormat *info,
                                                GLenum type)
{
    bool supportsReadDepthNV = context->getExtensions().readDepthNV && (info->depthBits > 0);
    switch (type)
    {
        case GL_UNSIGNED_SHORT:
        case GL_UNSIGNED_INT:
        case GL_UNSIGNED_INT_24_8:
            return supportsReadDepthNV;
        default:
            return false;
    }
}

bool ValidReadPixelsFloatDepthType(const Context *context,
                                   const gl::InternalFormat *info,
                                   GLenum type)
{
    return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
           context->getExtensions().depthBufferFloat2NV;
}

bool ValidReadPixelsFormatType(const Context *context,
                               const gl::InternalFormat *info,
                               GLenum format,
                               GLenum type)
{
    switch (info->componentType)
    {
        case GL_UNSIGNED_NORMALIZED:
            // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
            // ReadPixels with BGRA even if the extension is not present
            switch (format)
            {
                case GL_RGBA:
                    return type == GL_UNSIGNED_BYTE ||
                           (context->getExtensions().textureNorm16EXT &&
                            type == GL_UNSIGNED_SHORT && info->type == GL_UNSIGNED_SHORT);
                case GL_BGRA_EXT:
                    return context->getExtensions().readFormatBgraEXT && (type == GL_UNSIGNED_BYTE);
                case GL_STENCIL_INDEX_OES:
                    return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
                case GL_DEPTH_COMPONENT:
                    return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
                case GL_DEPTH_STENCIL_OES:
                    return context->getExtensions().readDepthStencilNV &&
                           (type == GL_UNSIGNED_INT_24_8_OES) && info->stencilBits > 0;
                case GL_RGBX8_ANGLE:
                    return context->getExtensions().rgbxInternalFormatANGLE &&
                           (type == GL_UNSIGNED_BYTE);
                default:
                    return false;
            }
        case GL_SIGNED_NORMALIZED:
            ASSERT(context->getExtensions().renderSnormEXT);
            ASSERT(info->type == GL_BYTE ||
                   (context->getExtensions().textureNorm16EXT && info->type == GL_SHORT));
            // Type conversions are not allowed for signed normalized color buffers
            return format == GL_RGBA && type == info->type;

        case GL_INT:
            return (format == GL_RGBA_INTEGER && type == GL_INT);

        case GL_UNSIGNED_INT:
            return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);

        case GL_FLOAT:
            switch (format)
            {
                case GL_RGBA:
                    return (type == GL_FLOAT);
                case GL_DEPTH_COMPONENT:
                    return ValidReadPixelsFloatDepthType(context, info, type);
                case GL_DEPTH_STENCIL_OES:
                    return context->getExtensions().readDepthStencilNV &&
                           type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && info->stencilBits > 0;
                default:
                    return false;
            }
        default:
            UNREACHABLE();
            return false;
    }
}

template <typename ParamType>
bool ValidateTextureWrapModeValue(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  const ParamType *params,
                                  bool restrictedWrapModes)
{
    switch (ConvertToGLenum(params[0]))
    {
        case GL_CLAMP_TO_EDGE:
            break;

        case GL_CLAMP_TO_BORDER:
            if (!context->getExtensions().textureBorderClampAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            if (restrictedWrapModes)
            {
                // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
                return false;
            }
            break;

        case GL_REPEAT:
        case GL_MIRRORED_REPEAT:
            if (restrictedWrapModes)
            {
                // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
                return false;
            }
            break;

        case GL_MIRROR_CLAMP_TO_EDGE_EXT:
            if (!context->getExtensions().textureMirrorClampToEdgeEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            if (restrictedWrapModes)
            {
                // OES_EGL_image_external and ANGLE_texture_rectangle specify this error.
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidWrapModeTexture);
                return false;
            }
            break;

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

    return true;
}

template <typename ParamType>
bool ValidateTextureMinFilterValue(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   const ParamType *params,
                                   bool restrictedMinFilter)
{
    switch (ConvertToGLenum(params[0]))
    {
        case GL_NEAREST:
        case GL_LINEAR:
            break;

        case GL_NEAREST_MIPMAP_NEAREST:
        case GL_LINEAR_MIPMAP_NEAREST:
        case GL_NEAREST_MIPMAP_LINEAR:
        case GL_LINEAR_MIPMAP_LINEAR:
            if (restrictedMinFilter)
            {
                // OES_EGL_image_external specifies this error.
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFilterTexture);
                return false;
            }
            break;

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

    return true;
}

template <typename ParamType>
bool ValidateTextureMagFilterValue(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   const ParamType *params)
{
    switch (ConvertToGLenum(params[0]))
    {
        case GL_NEAREST:
        case GL_LINEAR:
            break;

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

    return true;
}

template <typename ParamType>
bool ValidateTextureCompareModeValue(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     const ParamType *params)
{
    // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
    switch (ConvertToGLenum(params[0]))
    {
        case GL_NONE:
        case GL_COMPARE_REF_TO_TEXTURE:
            break;

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

    return true;
}

template <typename ParamType>
bool ValidateTextureCompareFuncValue(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     const ParamType *params)
{
    // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
    switch (ConvertToGLenum(params[0]))
    {
        case GL_LEQUAL:
        case GL_GEQUAL:
        case GL_LESS:
        case GL_GREATER:
        case GL_EQUAL:
        case GL_NOTEQUAL:
        case GL_ALWAYS:
        case GL_NEVER:
            break;

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

    return true;
}

template <typename ParamType>
bool ValidateTextureSRGBDecodeValue(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    const ParamType *params)
{
    if (!context->getExtensions().textureSRGBDecodeEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
        return false;
    }

    switch (ConvertToGLenum(params[0]))
    {
        case GL_DECODE_EXT:
        case GL_SKIP_DECODE_EXT:
            break;

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

    return true;
}

template <typename ParamType>
bool ValidateTextureSRGBOverrideValue(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      const ParamType *params)
{
    if (!context->getExtensions().textureFormatSRGBOverrideEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
        return false;
    }

    switch (ConvertToGLenum(params[0]))
    {
        case GL_SRGB:
        case GL_NONE:
            break;

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

    return true;
}

bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context,
                                                  angle::EntryPoint entryPoint)
{
    if (!context->getExtensions().textureFilterAnisotropicEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
        return false;
    }

    return true;
}

bool ValidateTextureMaxAnisotropyValue(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       GLfloat paramValue)
{
    if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
    {
        return false;
    }

    GLfloat largest = context->getCaps().maxTextureAnisotropy;

    if (paramValue < 1 || paramValue > largest)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOutsideOfBounds);
        return false;
    }

    return true;
}

bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
{
    const auto &glState                 = context->getState();
    const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
    const Framebuffer *framebuffer      = glState.getDrawFramebuffer();

    const auto &blendStateExt = glState.getBlendStateExt();
    auto drawBufferMask = framebuffer->getDrawBufferMask() & blendStateExt.compareColorMask(0);
    auto dualSourceBlendingMask = drawBufferMask & blendStateExt.getEnabledMask() &
                                  blendStateExt.getUsesExtendedBlendFactorMask();
    auto fragmentOutputMask          = executable->getActiveOutputVariablesMask();
    auto fragmentSecondaryOutputMask = executable->getActiveSecondaryOutputVariablesMask();

    return drawBufferMask == (drawBufferMask & fragmentOutputMask) &&
           dualSourceBlendingMask == (dualSourceBlendingMask & fragmentSecondaryOutputMask);
}

bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
{
    const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
    const Framebuffer *framebuffer      = context->getState().getDrawFramebuffer();

    return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().bits(),
                                      framebuffer->getDrawBufferTypeMask().bits(),
                                      executable->getActiveOutputVariablesMask().bits(),
                                      framebuffer->getDrawBufferMask().bits());
}

bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
{
    const auto &glState                 = context->getState();
    const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
    const VertexArray *vao              = context->getState().getVertexArray();

    if (executable == nullptr)
    {
        return false;
    }

    uint64_t stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().bits();
    uint64_t vaoAttribTypeBits          = vao->getAttributesTypeMask().bits();
    uint64_t vaoAttribEnabledMask       = vao->getAttributesMask().bits();

    vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
    vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
    vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);

    return ValidateComponentTypeMasks(executable->getAttributesTypeMask().bits(), vaoAttribTypeBits,
                                      executable->getAttributesMask().bits(), 0xFFFF);
}

bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
                                            PrimitiveMode geometryShaderInputPrimitiveType)
{
    // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
    switch (drawMode)
    {
        case PrimitiveMode::Points:
            return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
        case PrimitiveMode::Lines:
        case PrimitiveMode::LineStrip:
        case PrimitiveMode::LineLoop:
            return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
        case PrimitiveMode::LinesAdjacency:
        case PrimitiveMode::LineStripAdjacency:
            return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
        case PrimitiveMode::Triangles:
        case PrimitiveMode::TriangleFan:
        case PrimitiveMode::TriangleStrip:
            return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
        case PrimitiveMode::TrianglesAdjacency:
        case PrimitiveMode::TriangleStripAdjacency:
            return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
        default:
            UNREACHABLE();
            return false;
    }
}

// GLES1 texture parameters are a small subset of the others
bool IsValidGLES1TextureParameter(GLenum pname)
{
    switch (pname)
    {
        case GL_TEXTURE_MAG_FILTER:
        case GL_TEXTURE_MIN_FILTER:
        case GL_TEXTURE_WRAP_S:
        case GL_TEXTURE_WRAP_T:
        case GL_TEXTURE_WRAP_R:
        case GL_GENERATE_MIPMAP:
        case GL_TEXTURE_CROP_RECT_OES:
            return true;
        default:
            return false;
    }
}

bool IsBlitSameResource(const FramebufferAttachment *read, const FramebufferAttachment *draw)
{
    if (read->getResource() == draw->getResource())
    {
        if (read->type() == GL_TEXTURE)
        {
            bool sameMipLevel = read->mipLevel() == draw->mipLevel();
            bool sameLayer    = read->layer() == draw->layer();
            bool sameFace     = read->cubeMapFace() == draw->cubeMapFace();
            if (sameMipLevel && sameLayer && sameFace)
            {
                return true;
            }
        }
        else
        {
            return true;
        }
    }
    return false;
}

unsigned int GetSamplerParameterCount(GLenum pname)
{
    return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
}

const char *ValidateProgramDrawAdvancedBlendState(const Context *context,
                                                  const ProgramExecutable &executable)
{
    const State &state                                 = context->getState();
    const BlendEquationBitSet &supportedBlendEquations = executable.getAdvancedBlendEquations();
    const DrawBufferMask &enabledDrawBufferMask        = state.getBlendStateExt().getEnabledMask();

    // Zero (default) means everything is BlendEquationType::Add, so check can be skipped
    if (ANGLE_UNLIKELY(state.getBlendStateExt().getEquationColorBits() != 0))
    {
        for (size_t blendEnabledBufferIndex : enabledDrawBufferMask)
        {
            const gl::BlendEquationType enabledBlendEquation =
                state.getBlendStateExt().getEquationColorIndexed(blendEnabledBufferIndex);

            if (enabledBlendEquation < gl::BlendEquationType::Multiply ||
                enabledBlendEquation > gl::BlendEquationType::HslLuminosity)
            {
                continue;
            }

            if (!supportedBlendEquations.test(enabledBlendEquation))
            {
                return gl::err::kBlendEquationNotEnabled;
            }
        }
    }

    return nullptr;
}

ANGLE_INLINE GLenum ShPixelLocalStorageFormatToGLenum(ShPixelLocalStorageFormat format)
{
    switch (format)
    {
        case ShPixelLocalStorageFormat::NotPLS:
            return GL_NONE;
        case ShPixelLocalStorageFormat::RGBA8:
            return GL_RGBA8;
        case ShPixelLocalStorageFormat::RGBA8I:
            return GL_RGBA8I;
        case ShPixelLocalStorageFormat::RGBA8UI:
            return GL_RGBA8UI;
        case ShPixelLocalStorageFormat::R32F:
            return GL_R32F;
        case ShPixelLocalStorageFormat::R32I:
            return GL_R32I;
        case ShPixelLocalStorageFormat::R32UI:
            return GL_R32UI;
    }
    UNREACHABLE();
    return GL_NONE;
}

ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context,
                                                   const Extensions &extensions,
                                                   const ProgramExecutable &executable)
{
    const State &state = context->getState();
    if (extensions.multiviewOVR)
    {
        const int programNumViews     = executable.usesMultiview() ? executable.getNumViews() : 1;
        const bool hasVertexShader    = executable.hasLinkedShaderStage(ShaderType::Vertex);
        Framebuffer *framebuffer      = state.getDrawFramebuffer();
        const int framebufferNumViews = framebuffer->getNumViews();

        // num_views layout qualifiers are allowed only in vertex shaders.
        if (hasVertexShader && ANGLE_UNLIKELY(framebufferNumViews != programNumViews))
        {
            return gl::err::kMultiviewMismatch;
        }

        if (ANGLE_UNLIKELY(state.isTransformFeedbackActiveUnpaused()) &&
            ANGLE_UNLIKELY(framebufferNumViews > 1))
        {
            return gl::err::kMultiviewTransformFeedback;
        }

        if (extensions.disjointTimerQueryEXT && ANGLE_UNLIKELY(framebufferNumViews > 1) &&
            ANGLE_UNLIKELY(state.isQueryActive(QueryType::TimeElapsed)))
        {
            return gl::err::kMultiviewTimerQuery;
        }
    }

    if (ANGLE_UNLIKELY(context->isWebGL() || context->isBufferAccessValidationEnabled()))
    {
        // Uniform buffer validation
        for (size_t uniformBlockIndex = 0; uniformBlockIndex < executable.getUniformBlocks().size();
             uniformBlockIndex++)
        {
            const InterfaceBlock &uniformBlock =
                executable.getUniformBlockByIndex(uniformBlockIndex);
            GLuint blockBinding = executable.getUniformBlockBinding(uniformBlockIndex);
            const OffsetBindingPointer<Buffer> &uniformBuffer =
                state.getIndexedUniformBuffer(blockBinding);

            if (uniformBuffer.get() == nullptr && context->isWebGL())
            {
                // undefined behaviour
                return gl::err::kUniformBufferUnbound;
            }

            size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
            if (uniformBufferSize < uniformBlock.pod.dataSize &&
                (context->isWebGL() || context->isBufferAccessValidationEnabled()))
            {
                // undefined behaviour
                return gl::err::kUniformBufferTooSmall;
            }

            if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
            {
                return gl::err::kUniformBufferBoundForTransformFeedback;
            }
        }
    }

    // ANGLE_shader_pixel_local_storage validation.
    if (extensions.shaderPixelLocalStorageANGLE)
    {
        const Framebuffer *framebuffer = state.getDrawFramebuffer();
        const PixelLocalStorage *pls   = framebuffer->peekPixelLocalStorage();
        const auto &shaderPLSFormats   = executable.getPixelLocalStorageFormats();
        size_t activePLSCount          = context->getState().getPixelLocalStorageActivePlanes();

        if (ANGLE_UNLIKELY(shaderPLSFormats.size() > activePLSCount))
        {
            // INVALID_OPERATION is generated if a draw is issued with a fragment shader that has a
            // pixel local uniform bound to an inactive pixel local storage plane.
            return gl::err::kPLSDrawProgramPlanesInactive;
        }

        if (ANGLE_UNLIKELY(shaderPLSFormats.size() < activePLSCount))
        {
            // INVALID_OPERATION is generated if a draw is issued with a fragment shader that does
            // _not_ have a pixel local uniform bound to an _active_ pixel local storage plane
            // (i.e., the fragment shader must declare uniforms bound to every single active pixel
            // local storage plane).
            return gl::err::kPLSDrawProgramActivePlanesUnused;
        }

        for (size_t i = 0; i < activePLSCount; ++i)
        {
            const auto &plsPlane = pls->getPlane(static_cast<GLint>(i));
            ASSERT(plsPlane.isActive());
            if (ANGLE_UNLIKELY(shaderPLSFormats[i] == ShPixelLocalStorageFormat::NotPLS))
            {
                // INVALID_OPERATION is generated if a draw is issued with a fragment shader that
                // does _not_ have a pixel local uniform bound to an _active_ pixel local storage
                // plane (i.e., the fragment shader must declare uniforms bound to every single
                // active pixel local storage plane).
                return gl::err::kPLSDrawProgramActivePlanesUnused;
            }

            if (ANGLE_UNLIKELY(ShPixelLocalStorageFormatToGLenum(shaderPLSFormats[i]) !=
                               plsPlane.getInternalformat()))
            {
                // INVALID_OPERATION is generated if a draw is issued with a fragment shader that
                // has a pixel local storage uniform whose format layout qualifier does not
                // identically match the internalformat of its associated pixel local storage plane
                // on the current draw framebuffer, as enumerated in Table X.3.
                return gl::err::kPLSDrawProgramFormatMismatch;
            }
        }
    }

    // Enabled blend equation validation
    const char *errorString = nullptr;

    if (extensions.blendEquationAdvancedKHR || context->getClientVersion() >= ES_3_2)
    {
        errorString = ValidateProgramDrawAdvancedBlendState(context, executable);
    }

    return errorString;
}
}  // anonymous namespace

void SetRobustLengthParam(const GLsizei *length, GLsizei value)
{
    if (length)
    {
        // Currently we modify robust length parameters in the validation layer. We should be only
        // doing this in the Context instead.
        // TODO(http://anglebug.com/42263032): Remove when possible.
        *const_cast<GLsizei *>(length) = value;
    }
}

bool ValidTextureTarget(const Context *context, TextureType type)
{
    switch (type)
    {
        case TextureType::_2D:
        case TextureType::CubeMap:
            return true;

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

        case TextureType::_3D:
            return context->getClientVersion() >= ES_3_0 || context->getExtensions().texture3DOES;

        case TextureType::_2DArray:
            return context->getClientVersion() >= ES_3_0;

        case TextureType::_2DMultisample:
            return context->getClientVersion() >= ES_3_1 ||
                   context->getExtensions().textureMultisampleANGLE;

        case TextureType::_2DMultisampleArray:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().textureStorageMultisample2dArrayOES;

        case TextureType::CubeMapArray:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().textureCubeMapArrayAny();

        case TextureType::VideoImage:
            return context->getExtensions().videoTextureWEBGL;

        case TextureType::Buffer:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().textureBufferAny();

        default:
            return false;
    }
}

bool ValidTexture2DTarget(const Context *context, TextureType type)
{
    switch (type)
    {
        case TextureType::_2D:
        case TextureType::CubeMap:
            return true;

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

        default:
            return false;
    }
}

bool ValidTexture3DTarget(const Context *context, TextureType target)
{
    switch (target)
    {
        case TextureType::_3D:
        case TextureType::_2DArray:
            return (context->getClientVersion() >= ES_3_0);

        case TextureType::CubeMapArray:
            return (context->getClientVersion() >= Version(3, 2) ||
                    context->getExtensions().textureCubeMapArrayAny());

        default:
            return false;
    }
}

// Most texture GL calls are not compatible with external textures, so we have a separate validation
// function for use in the GL calls that do
bool ValidTextureExternalTarget(const Context *context, TextureType target)
{
    return (target == TextureType::External) &&
           (context->getExtensions().EGLImageExternalOES ||
            context->getExtensions().EGLStreamConsumerExternalNV);
}

bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
{
    return (target == TextureTarget::External) &&
           ValidTextureExternalTarget(context, TextureType::External);
}

// This function differs from ValidTextureTarget in that the target must be
// usable as the destination of a 2D operation-- so a cube face is valid, but
// GL_TEXTURE_CUBE_MAP is not.
// Note: duplicate of IsInternalTextureTarget
bool ValidTexture2DDestinationTarget(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;
        case TextureTarget::VideoImage:
            return context->getExtensions().videoTextureWEBGL;
        default:
            return false;
    }
}

bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            PrimitiveMode transformFeedbackPrimitiveMode,
                                            PrimitiveMode renderPrimitiveMode)
{
    ASSERT(context);

    if (!context->getExtensions().geometryShaderAny() &&
        !context->getExtensions().tessellationShaderAny() && context->getClientVersion() < ES_3_2)
    {
        // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
        // that does not match the current transform feedback object's draw mode (if transform
        // feedback is active), (3.0.2, section 2.14, pg 86)
        return transformFeedbackPrimitiveMode == renderPrimitiveMode;
    }

    const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
    ASSERT(executable);
    if (executable->hasLinkedShaderStage(ShaderType::Geometry))
    {
        // If geometry shader is active, transform feedback mode must match what is output from this
        // stage.
        renderPrimitiveMode = executable->getGeometryShaderOutputPrimitiveType();
    }
    else if (executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
    {
        // Similarly with tessellation shaders, but only if no geometry shader is present.  With
        // tessellation shaders, only triangles are possibly output.
        return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles &&
               executable->getTessGenMode() == GL_TRIANGLES;
    }

    // [GL_EXT_geometry_shader] Table 12.1gs
    switch (renderPrimitiveMode)
    {
        case PrimitiveMode::Points:
            return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
        case PrimitiveMode::Lines:
        case PrimitiveMode::LineStrip:
        case PrimitiveMode::LineLoop:
            return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
        case PrimitiveMode::Triangles:
        case PrimitiveMode::TriangleFan:
        case PrimitiveMode::TriangleStrip:
            return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
        case PrimitiveMode::Patches:
            return transformFeedbackPrimitiveMode == PrimitiveMode::Patches;
        default:
            UNREACHABLE();
            return false;
    }
}

bool ValidateDrawElementsInstancedBase(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       PrimitiveMode mode,
                                       GLsizei count,
                                       DrawElementsType type,
                                       const void *indices,
                                       GLsizei primcount,
                                       GLuint baseinstance)
{
    if (primcount <= 0)
    {
        if (primcount < 0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativePrimcount);
            return false;
        }

        // Early exit.
        return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices,
                                          primcount);
    }

    if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, primcount))
    {
        return false;
    }

    if (count == 0)
    {
        // Early exit.
        return true;
    }

    return ValidateDrawInstancedAttribs(context, entryPoint, primcount, baseinstance);
}

bool ValidateDrawArraysInstancedBase(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     PrimitiveMode mode,
                                     GLint first,
                                     GLsizei count,
                                     GLsizei primcount,
                                     GLuint baseinstance)
{
    if (primcount <= 0)
    {
        if (primcount < 0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativePrimcount);
            return false;
        }

        // Early exit.
        return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount);
    }

    if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount))
    {
        return false;
    }

    if (count == 0)
    {
        // Early exit.
        return true;
    }

    return ValidateDrawInstancedAttribs(context, entryPoint, primcount, baseinstance);
}

bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint)
{
    // Verify there is at least one active attribute with a divisor of zero
    const State &state                  = context->getState();
    const ProgramExecutable *executable = state.getLinkedProgramExecutable(context);

    if (!executable)
    {
        // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't
        // an error.
        context->getState().getDebug().insertMessage(
            GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH,
            std::string(GetEntryPointName(entryPoint)) + ": Attempting to draw without a program",
            gl::LOG_WARN);
        return true;
    }

    const auto &attribs  = state.getVertexArray()->getVertexAttributes();
    const auto &bindings = state.getVertexArray()->getVertexBindings();
    for (size_t attributeIndex = 0; attributeIndex < attribs.size(); attributeIndex++)
    {
        const VertexAttribute &attrib = attribs[attributeIndex];
        const VertexBinding &binding  = bindings[attrib.bindingIndex];
        if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
        {
            return true;
        }
    }

    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoZeroDivisor);
    return false;
}

bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
{
    switch (target)
    {
        case TextureTarget::_3D:
            return true;
        case TextureTarget::_2DArray:
            return context->getClientVersion() >= Version(3, 0);
        case TextureTarget::CubeMapArray:
            return (context->getClientVersion() >= Version(3, 2) ||
                    context->getExtensions().textureCubeMapArrayAny());
        default:
            return false;
    }
}

bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
{
    switch (type)
    {
        case TextureType::_2D:
        case TextureType::CubeMap:
            return true;
        case TextureType::_2DArray:
            return context->getClientVersion() >= ES_3_0;
        case TextureType::_2DMultisample:
            return context->getClientVersion() >= ES_3_1 ||
                   context->getExtensions().textureMultisampleANGLE;
        case TextureType::_2DMultisampleArray:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().textureStorageMultisample2dArrayOES;
        case TextureType::_3D:
            return context->getClientVersion() >= ES_3_0 || context->getExtensions().texture3DOES;
        case TextureType::CubeMapArray:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().textureCubeMapArrayAny();
        case TextureType::Rectangle:
            return context->getExtensions().textureRectangleANGLE;
        case TextureType::External:
            return context->getExtensions().EGLImageExternalOES;
        case TextureType::Buffer:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().textureBufferAny();
        default:
            return false;
    }
}

bool ValidFramebufferTarget(const Context *context, GLenum target)
{
    static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
                      GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
                  "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");

    switch (target)
    {
        case GL_FRAMEBUFFER:
            return true;

        case GL_READ_FRAMEBUFFER:
        case GL_DRAW_FRAMEBUFFER:
            return (context->getExtensions().framebufferBlitAny() ||
                    context->getClientVersion() >= ES_3_0);

        default:
            return false;
    }
}

bool ValidMipLevel(const Context *context, TextureType type, GLint level)
{
    const auto &caps = context->getCaps();
    int maxDimension = 0;
    switch (type)
    {
        case TextureType::_2D:
        case TextureType::_2DArray:
            maxDimension = caps.max2DTextureSize;
            break;

        case TextureType::CubeMap:
        case TextureType::CubeMapArray:
            maxDimension = caps.maxCubeMapTextureSize;
            break;

        case TextureType::External:
        case TextureType::Rectangle:
        case TextureType::VideoImage:
        case TextureType::Buffer:
        case TextureType::_2DMultisample:
        case TextureType::_2DMultisampleArray:
            return level == 0;

        case TextureType::_3D:
            maxDimension = caps.max3DTextureSize;
            break;

        default:
            UNREACHABLE();
    }

    return level <= log2(maxDimension) && level >= 0;
}

bool ValidImageSizeParameters(const Context *context,
                              angle::EntryPoint entryPoint,
                              TextureType target,
                              GLint level,
                              GLsizei width,
                              GLsizei height,
                              GLsizei depth,
                              bool isSubImage)
{
    if (width < 0 || height < 0 || depth < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
        return false;
    }
    // TexSubImage parameters can be NPOT without textureNPOT extension,
    // as long as the destination texture is POT.
    bool hasNPOTSupport =
        context->getExtensions().textureNpotOES || context->getClientVersion() >= Version(3, 0);
    if (!isSubImage && !hasNPOTSupport &&
        (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureNotPow2);
        return false;
    }

    if (!ValidMipLevel(context, target, level))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return false;
    }

    return true;
}

bool ValidCompressedBaseLevel(GLsizei size, GLuint blockSize, GLint level)
{
    // Already checked in ValidMipLevel.
    ASSERT(level < 32);
    // This function is used only for 4x4 BC formats.
    ASSERT(blockSize == 4);
    // Use the constant value to avoid division.
    return ((size << level) % 4) == 0;
}

bool ValidCompressedImageSize(const Context *context,
                              GLenum internalFormat,
                              GLint level,
                              GLsizei width,
                              GLsizei height,
                              GLsizei depth)
{
    if (width < 0 || height < 0)
    {
        return false;
    }

    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);

    if (!formatInfo.compressed && !formatInfo.paletted)
    {
        return false;
    }

    // A texture format can not be both block-compressed and paletted
    ASSERT(!(formatInfo.compressed && formatInfo.paletted));

    if (formatInfo.compressed)
    {
        // Only PVRTC1 requires dimensions to be powers of two
        if (IsPVRTC1Format(internalFormat))
        {
            if (!isPow2(width) || !isPow2(height))
            {
                return false;
            }

            if (context->getLimitations().squarePvrtc1)
            {
                if (width != height)
                {
                    return false;
                }
            }
        }

        if (CompressedTextureFormatRequiresExactSize(internalFormat))
        {
            // In WebGL compatibility mode and D3D, enforce that the base level implied
            // by the compressed texture's mip level would conform to the block
            // size.
            if (context->isWebGL() ||
                context->getLimitations().compressedBaseMipLevelMultipleOfFour)
            {
                // This check is performed only for BC formats.
                ASSERT(formatInfo.compressedBlockDepth == 1);
                if (!ValidCompressedBaseLevel(width, formatInfo.compressedBlockWidth, level) ||
                    !ValidCompressedBaseLevel(height, formatInfo.compressedBlockHeight, level))
                {
                    return false;
                }
            }
            // non-WebGL and non-D3D check is not necessary for the following formats
            // From EXT_texture_compression_s3tc specification:
            // If the width or height is not a multiple of four, there will be 4x4 blocks at the
            // edge of the image that contain "extra" texels that are not part of the image. From
            // EXT_texture_compression_bptc & EXT_texture_compression_rgtc specification: If an
            // RGTC/BPTC image has a width or height that is not a multiple of four, the data
            // corresponding to texels outside the image are irrelevant and undefined.
        }
    }

    if (formatInfo.paletted)
    {
        // TODO(http://anglebug.com/42266155): multi-level paletted images
        if (level != 0)
        {
            return false;
        }
    }

    return true;
}

bool ValidCompressedSubImageSize(const Context *context,
                                 GLenum internalFormat,
                                 GLint xoffset,
                                 GLint yoffset,
                                 GLint zoffset,
                                 GLsizei width,
                                 GLsizei height,
                                 GLsizei depth,
                                 size_t textureWidth,
                                 size_t textureHeight,
                                 size_t textureDepth)
{
    // Passing non-compressed internal format to sub-image compressed entry points generates
    // INVALID_OPERATION, so check it here.
    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
    if (!formatInfo.compressed)
    {
        return false;
    }

    // Negative dimensions already checked in ValidImageSizeParameters called by
    // ValidateES2TexImageParametersBase or ValidateES3TexImageParametersBase.
    ASSERT(width >= 0 && height >= 0 && depth >= 0);

    // Negative and overflowed offsets already checked in ValidateES2TexImageParametersBase or
    // ValidateES3TexImageParametersBase.
    ASSERT(xoffset >= 0 && yoffset >= 0 && zoffset >= 0);
    ASSERT(std::numeric_limits<GLsizei>::max() - xoffset >= width &&
           std::numeric_limits<GLsizei>::max() - yoffset >= height &&
           std::numeric_limits<GLsizei>::max() - zoffset >= depth);

    // Ensure that format's block dimensions are set.
    ASSERT(formatInfo.compressedBlockWidth > 0 && formatInfo.compressedBlockHeight > 0 &&
           formatInfo.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.
    if ((xoffset == 0 && static_cast<size_t>(width) == textureWidth) &&
        (yoffset == 0 && static_cast<size_t>(height) == textureHeight) &&
        ((zoffset == 0 && static_cast<size_t>(depth) == textureDepth) ||
         formatInfo.compressedBlockDepth == 1))
    {
        // All compressed formats support whole image replacement, early pass.
        return true;
    }

    // The replaced region does not match the image size. Fail if the format does not support
    // partial updates.
    if (CompressedFormatRequiresWholeImage(internalFormat))
    {
        return false;
    }

    // The format supports partial updates. Check that the origin of the replaced region is aligned
    // to block boundaries.
    if (xoffset % formatInfo.compressedBlockWidth != 0 ||
        yoffset % formatInfo.compressedBlockHeight != 0 ||
        zoffset % formatInfo.compressedBlockDepth != 0)
    {
        return false;
    }

    // The replaced region dimensions must either be multiples of the block dimensions or exactly
    // reach the image boundaries.
    return (static_cast<size_t>(xoffset + width) == textureWidth ||
            width % formatInfo.compressedBlockWidth == 0) &&
           (static_cast<size_t>(yoffset + height) == textureHeight ||
            height % formatInfo.compressedBlockHeight == 0) &&
           (static_cast<size_t>(zoffset + depth) == textureDepth ||
            depth % formatInfo.compressedBlockDepth == 0);
}

bool ValidImageDataSize(const Context *context,
                        angle::EntryPoint entryPoint,
                        TextureType texType,
                        GLsizei width,
                        GLsizei height,
                        GLsizei depth,
                        GLenum format,
                        GLenum type,
                        const void *pixels,
                        GLsizei imageSize)
{
    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
    if (pixelUnpackBuffer == nullptr && imageSize < 0)
    {
        // Checks are not required
        return true;
    }

    // ...the data would be unpacked from the buffer object such that the memory reads required
    // would exceed the data store size.
    const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
    if (formatInfo.internalFormat == GL_NONE)
    {
        UNREACHABLE();
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInternalErrorFormatNotFound);
        return false;
    }
    const Extents size(width, height, depth);
    const auto &unpack = context->getState().getUnpackState();

    bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
    GLuint endByte  = 0;
    if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
        return false;
    }

    if (pixelUnpackBuffer)
    {
        CheckedNumeric<size_t> checkedEndByte(endByte);
        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
        checkedEndByte += checkedOffset;

        if (!checkedEndByte.IsValid() ||
            (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
        {
            // Overflow past the end of the buffer
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
            return false;
        }
        if (pixelUnpackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                   kPixelUnpackBufferBoundForTransformFeedback);
            return false;
        }
    }
    else
    {
        ASSERT(imageSize >= 0);
        if (pixels == nullptr && imageSize != 0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImageSizeMustBeZero);
            return false;
        }

        if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImageSizeTooSmall);
            return false;
        }
    }

    return true;
}

bool ValidQueryType(const Context *context, QueryType queryType)
{
    switch (queryType)
    {
        case QueryType::AnySamples:
        case QueryType::AnySamplesConservative:
            return context->getClientVersion() >= ES_3_0 ||
                   context->getExtensions().occlusionQueryBooleanEXT;
        case QueryType::TransformFeedbackPrimitivesWritten:
            return context->getClientVersion() >= ES_3_0;
        case QueryType::TimeElapsed:
            return context->getExtensions().disjointTimerQueryEXT;
        case QueryType::PrimitivesGenerated:
            return context->getClientVersion() >= ES_3_2 ||
                   context->getExtensions().geometryShaderAny();
        default:
            return false;
    }
}

bool ValidateWebGLVertexAttribPointer(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      VertexAttribType type,
                                      GLboolean normalized,
                                      GLsizei stride,
                                      const void *ptr,
                                      bool pureInteger)
{
    ASSERT(context->isWebGL());
    // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
    // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
    // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
    // parameter exceeds 255.
    constexpr GLsizei kMaxWebGLStride = 255;
    if (stride > kMaxWebGLStride)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
        return false;
    }

    // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
    // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
    // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
    // or an INVALID_OPERATION error is generated.
    angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
    size_t typeSize              = GetVertexFormatSize(internalType);

    ASSERT(isPow2(typeSize) && typeSize > 0);
    size_t sizeMask = (typeSize - 1);
    if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
        return false;
    }

    if ((stride & sizeMask) != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
        return false;
    }

    return true;
}

Program *GetValidProgramNoResolve(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  ShaderProgramID id)
{
    // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
    // generate the error INVALID_VALUE if the provided name is not the name of either a shader
    // or program object and INVALID_OPERATION if the provided name identifies an object
    // that is not the expected type."

    Program *validProgram = context->getProgramNoResolveLink(id);

    if (!validProgram)
    {
        if (context->getShaderNoResolveCompile(id))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedProgramName);
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidProgramName);
        }
    }

    return validProgram;
}

Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
{
    Program *program = GetValidProgramNoResolve(context, entryPoint, id);
    if (program)
    {
        program->resolveLink(context);
    }
    return program;
}

Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
{
    // See ValidProgram for spec details.

    Shader *validShader = context->getShaderNoResolveCompile(id);

    if (!validShader)
    {
        if (context->getProgramNoResolveLink(id))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExpectedShaderName);
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidShaderName);
        }
    }

    return validShader;
}

bool ValidateAttachmentTarget(const Context *context,
                              angle::EntryPoint entryPoint,
                              GLenum attachment)
{
    if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
    {
        if (context->getClientVersion() < ES_3_0 && !context->getExtensions().drawBuffersEXT)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
            return false;
        }

        // Color attachment 0 is validated below because it is always valid
        const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
        if (colorAttachment >= context->getCaps().maxColorAttachments)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
            return false;
        }
    }
    else
    {
        switch (attachment)
        {
            case GL_COLOR_ATTACHMENT0:
            case GL_DEPTH_ATTACHMENT:
            case GL_STENCIL_ATTACHMENT:
                break;

            case GL_DEPTH_STENCIL_ATTACHMENT:
                if (!context->isWebGL() && context->getClientVersion() < ES_3_0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
                    return false;
                }
                break;

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

    return true;
}

bool ValidateRenderbufferStorageParametersBase(const Context *context,
                                               angle::EntryPoint entryPoint,
                                               GLenum target,
                                               GLsizei samples,
                                               GLenum internalformat,
                                               GLsizei width,
                                               GLsizei height)
{
    switch (target)
    {
        case GL_RENDERBUFFER:
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
            return false;
    }

    if (width < 0 || height < 0 || samples < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
        return false;
    }

    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
    GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);

    const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
    if (!formatCaps.renderbuffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
        return false;
    }

    // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
    // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
    // only sized internal formats.
    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
    if (formatInfo.internalFormat == GL_NONE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
        return false;
    }

    if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
        return false;
    }

    RenderbufferID id = context->getState().getRenderbufferId();
    if (id.value == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
        return false;
    }

    return true;
}

bool ValidateBlitFramebufferParameters(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)
{
    switch (filter)
    {
        case GL_NEAREST:
            break;
        case GL_LINEAR:
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kBlitInvalidFilter);
            return false;
    }

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

    // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
    // color buffer, leaving only nearest being unfiltered from above
    if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
        return false;
    }

    const auto &glState          = context->getState();
    Framebuffer *readFramebuffer = glState.getReadFramebuffer();
    Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();

    if (!readFramebuffer || !drawFramebuffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFramebufferMissing);
        return false;
    }

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

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

    // The QCOM_framebuffer_foveated spec:
    if (drawFramebuffer->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 (drawFramebuffer->hasAnyAttachmentChanged())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFramebufferFoveationAttachmentChanged);
            return false;
        }
    }

    // EXT_YUV_target disallows blitting to or from a YUV framebuffer
    if ((mask & GL_COLOR_BUFFER_BIT) != 0 &&
        (readFramebuffer->hasYUVAttachment() || drawFramebuffer->hasYUVAttachment()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitYUVFramebuffer);
        return false;
    }

    // The draw and read framebuffers can only match if:
    // - They are the default framebuffer AND
    // - The read/draw surfaces are different
    if ((readFramebuffer->id() == drawFramebuffer->id()) &&
        ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
         (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitFeedbackLoop);
        return false;
    }

    // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
    // consider it MS. checkReadBufferResourceSamples = false
    if (!ValidateFramebufferNotMultisampled(context, entryPoint, drawFramebuffer, false))
    {
        return false;
    }

    // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
    // always run it in order to avoid triggering driver bugs.
    if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
        DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
        return false;
    }

    bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;

    if (mask & GL_COLOR_BUFFER_BIT)
    {
        const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
        const Extensions &extensions                 = context->getExtensions();

        if (readColorBuffer)
        {
            const Format &readFormat = readColorBuffer->getFormat();

            for (size_t drawbufferIdx = 0;
                 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
            {
                const FramebufferAttachment *attachment =
                    drawFramebuffer->getDrawBuffer(drawbufferIdx);
                if (attachment)
                {
                    const Format &drawFormat = attachment->getFormat();

                    // The GL ES 3.0.2 spec (pg 193) states that:
                    // 1) If the read buffer is fixed point format, the draw buffer must be as well
                    // 2) If the read buffer is an unsigned integer format, the draw buffer must be
                    // as well
                    // 3) If the read buffer is a signed integer format, the draw buffer must be as
                    // well
                    // Changes with EXT_color_buffer_float:
                    // Case 1) is changed to fixed point OR floating point
                    GLenum readComponentType = readFormat.info->componentType;
                    GLenum drawComponentType = drawFormat.info->componentType;
                    bool readFixedPoint      = (readComponentType == GL_UNSIGNED_NORMALIZED ||
                                           readComponentType == GL_SIGNED_NORMALIZED);
                    bool drawFixedPoint      = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
                                           drawComponentType == GL_SIGNED_NORMALIZED);

                    if (extensions.colorBufferFloatEXT)
                    {
                        bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
                        bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);

                        if (readFixedOrFloat != drawFixedOrFloat)
                        {
                            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                                   kBlitTypeMismatchFixedOrFloat);
                            return false;
                        }
                    }
                    else if (readFixedPoint != drawFixedPoint)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitTypeMismatchFixedPoint);
                        return false;
                    }

                    if (readComponentType == GL_UNSIGNED_INT &&
                        drawComponentType != GL_UNSIGNED_INT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                               kBlitTypeMismatchUnsignedInteger);
                        return false;
                    }

                    if (readComponentType == GL_INT && drawComponentType != GL_INT)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                               kBlitTypeMismatchSignedInteger);
                        return false;
                    }

                    if (readColorBuffer->getResourceSamples() > 0 &&
                        (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                               kBlitMultisampledFormatOrBoundsMismatch);
                        return false;
                    }

                    if (context->isWebGL() && *readColorBuffer == *attachment)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageColor);
                        return false;
                    }

                    if (IsBlitSameResource(readColorBuffer, attachment))
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameResource);
                        return false;
                    }
                }
            }

            if (readFormat.info->isInt() && filter == GL_LINEAR)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitIntegerWithLinearFilter);
                return false;
            }
        }
        // In OpenGL ES, blits to/from missing attachments are silently ignored.  In WebGL 2.0, this
        // is defined to be an error.
        else if (context->isWebGL() && drawFramebuffer->hasEnabledDrawBuffer())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMissingColor);
            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 (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitDepthOrStencilFormatMismatch);
                    return false;
                }

                if (readBuffer->getResourceSamples() > 0 && !sameBounds)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMultisampledBoundsMismatch);
                    return false;
                }

                if (context->isWebGL() && *readBuffer == *drawBuffer)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameImageDepthOrStencil);
                    return false;
                }

                if (IsBlitSameResource(readBuffer, drawBuffer))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitSameResource);
                    return false;
                }
            }
            // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
            else if (context->isWebGL() && drawBuffer)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBlitMissingDepthOrStencil);
                return false;
            }
        }
    }

    // OVR_multiview:
    // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
    // current draw framebuffer isMultiview() or the number of
    // views in the current read framebuffer is more than one.
    if (readFramebuffer->readDisallowedByMultiview())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
        return false;
    }
    if (drawFramebuffer->isMultiview())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
        return false;
    }

    return true;
}

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

    if (!context->getState().isBindGeneratesResourceEnabled() &&
        !context->isFramebufferGenerated(framebuffer))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
        return false;
    }

    return true;
}

bool ValidateBindRenderbufferBase(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLenum target,
                                  RenderbufferID renderbuffer)
{
    if (target != GL_RENDERBUFFER)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
        return false;
    }

    if (!context->getState().isBindGeneratesResourceEnabled() &&
        !context->isRenderbufferGenerated(renderbuffer))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kObjectNotGenerated);
        return false;
    }

    return true;
}

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

    switch (pname)
    {
        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
        {
            GLint maxWidth = context->getCaps().maxFramebufferWidth;
            if (param < 0 || param > maxWidth)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferWidth);
                return false;
            }
            break;
        }
        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
        {
            GLint maxHeight = context->getCaps().maxFramebufferHeight;
            if (param < 0 || param > maxHeight)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferHeight);
                return false;
            }
            break;
        }
        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
        {
            GLint maxSamples = context->getCaps().maxFramebufferSamples;
            if (param < 0 || param > maxSamples)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kExceedsFramebufferSamples);
                return false;
            }
            break;
        }
        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
        {
            break;
        }
        case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
        {
            if (!context->getExtensions().geometryShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
                return false;
            }
            GLint maxLayers = context->getCaps().maxFramebufferLayers;
            if (param < 0 || param > maxLayers)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFramebufferLayer);
                return false;
            }
            break;
        }
        case GL_FRAMEBUFFER_FLIP_Y_MESA:
        {
            if (!context->getExtensions().framebufferFlipYMESA)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
                return false;
            }
            break;
        }
        default:
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
            return false;
        }
    }

    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
    ASSERT(framebuffer);
    if (framebuffer->isDefault())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebuffer);
        return false;
    }
    return true;
}

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

    if (renderbuffertarget != GL_RENDERBUFFER)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
        return false;
    }

    Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);

    ASSERT(framebuffer);
    if (framebuffer->isDefault())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
        return false;
    }

    if (!ValidateAttachmentTarget(context, entryPoint, attachment))
    {
        return false;
    }

    // [OpenGL ES 2.0.25] Section 4.4.3 page 112
    // [OpenGL ES 3.0.2] Section 4.4.2 page 201
    // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
    // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
    if (renderbuffer.value != 0)
    {
        if (!context->getRenderbuffer(renderbuffer))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
            return false;
        }
    }

    return true;
}

bool ValidateFramebufferTextureBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum target,
                                    GLenum attachment,
                                    TextureID texture,
                                    GLint level)
{
    if (!ValidFramebufferTarget(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferTarget);
        return false;
    }

    if (!ValidateAttachmentTarget(context, entryPoint, attachment))
    {
        return false;
    }

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

        if (tex == nullptr)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingTexture);
            return false;
        }

        if (level < 0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
            return false;
        }

        // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
        // An INVALID_VALUE error is generated if texture is not zero and level is
        // not a supported texture level for textarget

        // Common criteria for not supported texture levels(other criteria are handled case by case
        // in non base functions): If texture refers to an immutable-format texture, level must be
        // greater than or equal to zero and smaller than the value of TEXTURE_IMMUTABLE_LEVELS for
        // texture.
        if (tex->getImmutableFormat() && context->getClientVersion() >= ES_3_1)
        {
            if (level >= static_cast<GLint>(tex->getImmutableLevels()))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
                return false;
            }
        }

        // GLES spec 3.2, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
        // An INVALID_OPERATION error is generated if <texture> is the name of a buffer texture.
        if ((context->getClientVersion() >= ES_3_2 ||
             context->getExtensions().textureBufferAny()) &&
            tex->getType() == TextureType::Buffer)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidTextureTarget);
            return false;
        }

        if (tex->getState().hasProtectedContent() != context->getState().hasProtectedContent())
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                   "Mismatch between Texture and Context Protected Content state");
            return false;
        }
    }

    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (framebuffer->isDefault())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
        return false;
    }

    return true;
}

bool ValidateGenerateMipmapBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                TextureType target)
{
    if (!ValidTextureTarget(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    Texture *texture = context->getTextureByType(target);

    if (texture == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotBound);
        return false;
    }

    if (context->getState().isTextureBoundToActivePLS(texture->id()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture);
        return false;
    }

    const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();

    // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
    // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
    if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelOutOfRange);
        return false;
    }

    TextureTarget baseTarget = (target == TextureType::CubeMap)
                                   ? TextureTarget::CubeMapPositiveX
                                   : NonCubeTextureTypeToTarget(target);
    const auto &format       = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
    if (format.sizedInternalFormat == GL_NONE || format.compressed || format.paletted ||
        format.depthBits > 0 || format.stencilBits > 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
        return false;
    }

    // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
    bool formatUnsized = !format.sized;
    bool formatColorRenderableAndFilterable =
        format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
        format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
    if (!formatUnsized && !formatColorRenderableAndFilterable)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
        return false;
    }

    // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
    // generation
    if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
        return false;
    }

    // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and
    // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT.
    if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
        return false;
    }

    // Non-power of 2 ES2 check
    if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNpotOES &&
        (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
         !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
    {
        ASSERT(target == TextureType::_2D || target == TextureType::Rectangle ||
               target == TextureType::CubeMap);
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotPow2);
        return false;
    }

    // Cube completeness check
    if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCubemapIncomplete);
        return false;
    }

    if (context->isWebGL() && (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 ||
                               texture->getHeight(baseTarget, effectiveBaseLevel) == 0))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kGenerateMipmapZeroSize);
        return false;
    }

    return true;
}

bool ValidateReadPixelsRobustANGLE(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   GLint x,
                                   GLint y,
                                   GLsizei width,
                                   GLsizei height,
                                   GLenum format,
                                   GLenum type,
                                   GLsizei bufSize,
                                   const GLsizei *length,
                                   const GLsizei *columns,
                                   const GLsizei *rows,
                                   const void *pixels)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength  = 0;
    GLsizei writeColumns = 0;
    GLsizei writeRows    = 0;

    if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
                                &writeLength, &writeColumns, &writeRows, pixels))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);
    SetRobustLengthParam(columns, writeColumns);
    SetRobustLengthParam(rows, writeRows);

    return true;
}

bool ValidateReadnPixelsEXT(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLint x,
                            GLint y,
                            GLsizei width,
                            GLsizei height,
                            GLenum format,
                            GLenum type,
                            GLsizei bufSize,
                            const void *pixels)
{
    if (bufSize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
                                  nullptr, nullptr, nullptr, pixels);
}

bool ValidateReadnPixelsRobustANGLE(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLint x,
                                    GLint y,
                                    GLsizei width,
                                    GLsizei height,
                                    GLenum format,
                                    GLenum type,
                                    GLsizei bufSize,
                                    const GLsizei *length,
                                    const GLsizei *columns,
                                    const GLsizei *rows,
                                    const void *data)
{
    if ((context->getClientVersion() < ES_3_2) && !context->getExtensions().robustnessEXT &&
        !context->getExtensions().robustnessKHR)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported);
        return false;
    }

    GLsizei writeLength  = 0;
    GLsizei writeColumns = 0;
    GLsizei writeRows    = 0;

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
                                &writeLength, &writeColumns, &writeRows, data))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);
    SetRobustLengthParam(columns, writeColumns);
    SetRobustLengthParam(rows, writeRows);

    return true;
}

bool ValidateGenQueriesEXT(const Context *context,
                           angle::EntryPoint entryPoint,
                           GLsizei n,
                           const QueryID *ids)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, ids);
}

bool ValidateDeleteQueriesEXT(const Context *context,
                              angle::EntryPoint entryPoint,
                              GLsizei n,
                              const QueryID *ids)
{
    return ValidateGenOrDelete(context->getMutableErrorSetForValidation(), entryPoint, n, ids);
}

bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id)
{
    return true;
}

bool ValidateBeginQueryBase(const Context *context,
                            angle::EntryPoint entryPoint,
                            QueryType target,
                            QueryID id)
{
    if (!ValidQueryType(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
        return false;
    }

    if (id.value == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
        return false;
    }

    // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
    // of zero, if the active query object name for <target> is non-zero (for the
    // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
    // the active query for either target is non-zero), if <id> is the name of an
    // existing query object whose type does not match <target>, or if <id> is the
    // active query object name for any query type, the error INVALID_OPERATION is
    // generated.

    // Ensure no other queries are active
    // NOTE: If other queries than occlusion are supported, we will need to check
    // separately that:
    //    a) The query ID passed is not the current active query for any target/type
    //    b) There are no active queries for the requested target (and in the case
    //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
    //       no query may be active for either if glBeginQuery targets either.

    if (context->getState().isQueryActive(target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kOtherQueryActive);
        return false;
    }

    // check that name was obtained with glGenQueries
    if (!context->isQueryGenerated(id))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
        return false;
    }

    // Check for type mismatch. If query is not yet started we're good to go.
    Query *queryObject = context->getQuery(id);
    if (queryObject && queryObject->getType() != target)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryTargetMismatch);
        return false;
    }

    return true;
}

bool ValidateBeginQueryEXT(const Context *context,
                           angle::EntryPoint entryPoint,
                           QueryType target,
                           QueryID id)
{
    return ValidateBeginQueryBase(context, entryPoint, target, id);
}

bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target)
{
    if (!ValidQueryType(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
        return false;
    }

    const Query *queryObject = context->getState().getActiveQuery(target);

    if (queryObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryInactive);
        return false;
    }

    return true;
}

bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target)
{
    return ValidateEndQueryBase(context, entryPoint, target);
}

bool ValidateQueryCounterEXT(const Context *context,
                             angle::EntryPoint entryPoint,
                             QueryID id,
                             QueryType target)
{
    if (target != QueryType::Timestamp)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget);
        return false;
    }

    if (!context->isQueryGenerated(id))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
        return false;
    }

    // If query object is not started, that's fine.
    Query *queryObject = context->getQuery(id);
    if (queryObject && context->getState().isQueryActive(queryObject))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryActive);
        return false;
    }

    // Check if target type matches the query object target type
    if (queryObject && queryObject->getType() != target)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryTargetMismatch);
        return false;
    }

    return true;
}

bool ValidateGetQueryivBase(const Context *context,
                            angle::EntryPoint entryPoint,
                            QueryType target,
                            GLenum pname,
                            GLsizei *numParams)
{
    if (numParams)
    {
        *numParams = 0;
    }

    if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryType);
        return false;
    }

    switch (pname)
    {
        case GL_CURRENT_QUERY_EXT:
            if (target == QueryType::Timestamp)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidQueryTarget);
                return false;
            }
            break;
        case GL_QUERY_COUNTER_BITS_EXT:
            if (!context->getExtensions().disjointTimerQueryEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
                return false;
            }
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
            return false;
    }

    if (numParams)
    {
        // All queries return only one value
        *numParams = 1;
    }

    return true;
}

bool ValidateGetQueryivEXT(const Context *context,
                           angle::EntryPoint entryPoint,
                           QueryType target,
                           GLenum pname,
                           const GLint *params)
{
    return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
}

bool ValidateGetQueryivRobustANGLE(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   QueryType target,
                                   GLenum pname,
                                   GLsizei bufSize,
                                   const GLsizei *length,
                                   const GLint *params)
{
    if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().disjointTimerQueryEXT &&
        !context->getExtensions().occlusionQueryBooleanEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetQueryivBase(context, entryPoint, target, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetQueryObjectValueBase(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     QueryID id,
                                     GLenum pname,
                                     GLsizei *numParams)
{
    if (numParams)
    {
        *numParams = 1;
    }

    if (context->isContextLost())
    {
        if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
        {
            // The context needs to return a value in this case.
            // It will also generate a CONTEXT_LOST error.
            return true;
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
            return false;
        }
    }

    Query *queryObject = context->getQuery(id);
    if (queryObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidQueryId);
        return false;
    }

    if (context->getState().isQueryActive(queryObject))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kQueryActive);
        return false;
    }

    switch (pname)
    {
        case GL_QUERY_RESULT_EXT:
        case GL_QUERY_RESULT_AVAILABLE_EXT:
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    return true;
}

bool ValidateGetQueryObjectivEXT(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 QueryID id,
                                 GLenum pname,
                                 const GLint *params)
{
    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
}

bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         QueryID id,
                                         GLenum pname,
                                         GLsizei bufSize,
                                         const GLsizei *length,
                                         const GLint *params)
{
    if (!context->getExtensions().disjointTimerQueryEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetQueryObjectuivEXT(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  QueryID id,
                                  GLenum pname,
                                  const GLuint *params)
{
    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
}

bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          QueryID id,
                                          GLenum pname,
                                          GLsizei bufSize,
                                          const GLsizei *length,
                                          const GLuint *params)
{
    if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().disjointTimerQueryEXT &&
        !context->getExtensions().occlusionQueryBooleanEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetQueryObjecti64vEXT(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   QueryID id,
                                   GLenum pname,
                                   const GLint64 *params)
{
    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
}

bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           QueryID id,
                                           GLenum pname,
                                           GLsizei bufSize,
                                           const GLsizei *length,
                                           const GLint64 *params)
{
    if (!context->getExtensions().disjointTimerQueryEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetQueryObjectui64vEXT(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    QueryID id,
                                    GLenum pname,
                                    const GLuint64 *params)
{
    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
}

bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            QueryID id,
                                            GLenum pname,
                                            GLsizei bufSize,
                                            const GLsizei *length,
                                            const GLuint64 *params)
{
    if (!context->getExtensions().disjointTimerQueryEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateUniform1ivValue(const Context *context,
                             angle::EntryPoint entryPoint,
                             GLenum uniformType,
                             GLsizei count,
                             const GLint *value)
{
    // Value type is GL_INT, because we only get here from glUniform1i{v}.
    // It is compatible with INT or BOOL.
    // Do these cheap tests first, for a little extra speed.
    if (GL_INT == uniformType || GL_BOOL == uniformType)
    {
        return true;
    }

    if (IsSamplerType(uniformType))
    {
        // Check that the values are in range.
        const GLint max = context->getCaps().maxCombinedTextureImageUnits;
        for (GLsizei i = 0; i < count; ++i)
        {
            if (value[i] < 0 || value[i] >= max)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplerUniformValueOutOfRange);
                return false;
            }
        }
        return true;
    }

    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUniformTypeMismatch);
    return false;
}

bool ValidateUniformMatrixValue(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLenum valueType,
                                GLenum uniformType)
{
    // Check that the value type is compatible with uniform type.
    if (valueType == uniformType)
    {
        return true;
    }

    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kUniformTypeMismatch);
    return false;
}

bool ValidateUniform(const Context *context,
                     angle::EntryPoint entryPoint,
                     GLenum valueType,
                     UniformLocation location,
                     GLsizei count)
{
    const LinkedUniform *uniform = nullptr;
    Program *programObject       = context->getActiveLinkedProgram();
    if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform))
    {
        // Error already generated.
        return false;
    }
    if (uniform == nullptr)
    {
        return true;  // no-op
    }
    return ValidateUniformValue(context, entryPoint, valueType, uniform->getType());
}

bool ValidateUniform1iv(const Context *context,
                        angle::EntryPoint entryPoint,
                        UniformLocation location,
                        GLsizei count,
                        const GLint *value)
{
    const LinkedUniform *uniform = nullptr;
    Program *programObject       = context->getActiveLinkedProgram();
    if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform))
    {
        // Error already generated.
        return false;
    }
    if (uniform == nullptr)
    {
        return true;  // no-op
    }
    return ValidateUniform1ivValue(context, entryPoint, uniform->getType(), count, value);
}

bool ValidateUniformMatrix(const Context *context,
                           angle::EntryPoint entryPoint,
                           GLenum valueType,
                           UniformLocation location,
                           GLsizei count,
                           GLboolean transpose)
{
    if (ConvertToBool(transpose) && context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kES3Required);
        return false;
    }

    const LinkedUniform *uniform = nullptr;
    Program *programObject       = context->getActiveLinkedProgram();
    if (!ValidateUniformCommonBase(context, entryPoint, programObject, location, count, &uniform))
    {
        // Error already generated.
        return false;
    }
    if (uniform == nullptr)
    {
        return true;  // no-op
    }
    return ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->getType());
}

bool ValidateStateQuery(const Context *context,
                        angle::EntryPoint entryPoint,
                        GLenum pname,
                        GLenum *nativeType,
                        unsigned int *numParams)
{
    if (!context->getQueryParameterInfo(pname, nativeType, numParams))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
        return false;
    }

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

    if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
    {
        int colorAttachment = (pname - GL_DRAW_BUFFER0);

        if (colorAttachment >= caps.maxDrawBuffers)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
            return false;
        }
    }

    switch (pname)
    {
        case GL_TEXTURE_BINDING_2D:
        case GL_TEXTURE_BINDING_CUBE_MAP:
        case GL_TEXTURE_BINDING_3D:
        case GL_TEXTURE_BINDING_2D_ARRAY:
        case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
        case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
            break;

        case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
            if (!context->getExtensions().textureRectangleANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_BINDING_EXTERNAL_OES:
            if (!context->getExtensions().EGLStreamConsumerExternalNV &&
                !context->getExtensions().EGLImageExternalOES)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_BUFFER_BINDING:
        case GL_TEXTURE_BINDING_BUFFER:
        case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
        case GL_MAX_TEXTURE_BUFFER_SIZE:
            if (context->getClientVersion() < Version(3, 2) &&
                !context->getExtensions().textureBufferAny())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
                return false;
            }
            break;

        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
        {
            Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
            ASSERT(readFramebuffer);

            if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, entryPoint,
                                                                   readFramebuffer))
            {
                return false;
            }

            if (readFramebuffer->getReadBufferState() == GL_NONE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
                return false;
            }

            const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
            if (!attachment)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNotAttached);
                return false;
            }
            break;
        }

        case GL_PRIMITIVE_BOUNDING_BOX:
            if (!context->getExtensions().primitiveBoundingBoxAny())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_SHADING_RATE_QCOM:
            if (!context->getExtensions().shadingRateQCOM)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_MULTISAMPLE_LINE_WIDTH_RANGE:
            if (context->getClientVersion() < Version(3, 2))
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY:
            if (context->getClientVersion() < Version(3, 2))
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
            if (context->getClientVersion() < Version(3, 2) &&
                !context->getExtensions().tessellationShaderAny())
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        default:
            break;
    }

    // pname is valid, but there are no parameters to return
    if (*numParams == 0)
    {
        return false;
    }

    return true;
}

bool ValidateGetBooleanvRobustANGLE(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum pname,
                                    GLsizei bufSize,
                                    const GLsizei *length,
                                    const GLboolean *params)
{
    GLenum nativeType;
    unsigned int numParams = 0;

    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetFloatvRobustANGLE(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLenum pname,
                                  GLsizei bufSize,
                                  const GLsizei *length,
                                  const GLfloat *params)
{
    GLenum nativeType;
    unsigned int numParams = 0;

    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetIntegervRobustANGLE(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum pname,
                                    GLsizei bufSize,
                                    const GLsizei *length,
                                    const GLint *data)
{
    GLenum nativeType;
    unsigned int numParams = 0;

    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetInteger64vRobustANGLE(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      GLenum pname,
                                      GLsizei bufSize,
                                      const GLsizei *length,
                                      const GLint64 *data)
{
    if ((context->getClientVersion() < ES_3_0) && !context->getExtensions().disjointTimerQueryEXT)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEntryPointBaseUnsupported);
        return false;
    }

    GLenum nativeType;
    unsigned int numParams = 0;

    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);
    return true;
}

bool ValidateRobustStateQuery(const Context *context,
                              angle::EntryPoint entryPoint,
                              GLenum pname,
                              GLsizei bufSize,
                              GLenum *nativeType,
                              unsigned int *numParams)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    if (!ValidateStateQuery(context, entryPoint, pname, nativeType, numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, *numParams))
    {
        return false;
    }

    return true;
}

bool ValidateCopyImageSubDataTargetRegion(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          GLuint name,
                                          GLenum target,
                                          GLint level,
                                          GLint offsetX,
                                          GLint offsetY,
                                          GLint offsetZ,
                                          GLsizei width,
                                          GLsizei height,
                                          GLsizei depth,
                                          GLsizei *samples)
{
    // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
    // of the corresponding image object.
    if (offsetX < 0 || offsetY < 0 || offsetZ < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
        return false;
    }

    if (target == GL_RENDERBUFFER)
    {
        // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
        // boundaries of the corresponding image object
        Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
        if ((buffer->getWidth() - offsetX < width) || (buffer->getHeight() - offsetY < height))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
            return false;
        }
    }
    else
    {
        Texture *texture = context->getTexture(PackParam<TextureID>(name));

        // INVALID_OPERATION is generated if either object is a texture and the texture is not
        // complete
        // This will handle the texture completeness check. Note that this ignores format-based
        // compleness rules.
        if (!texture->isSamplerCompleteForCopyImage(context, nullptr))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNotTextureComplete);
            return false;
        }

        GLenum textureTargetToUse = target;
        if (target == GL_TEXTURE_CUBE_MAP)
        {
            // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight
            textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
        }

        const GLsizei textureWidth = static_cast<GLsizei>(
            texture->getWidth(PackParam<TextureTarget>(textureTargetToUse), level));
        const GLsizei textureHeight = static_cast<GLsizei>(
            texture->getHeight(PackParam<TextureTarget>(textureTargetToUse), level));
        const GLsizei textureDepth =
            target == GL_TEXTURE_CUBE_MAP
                ? 6
                : static_cast<GLsizei>(
                      texture->getDepth(PackParam<TextureTarget>(textureTargetToUse), level));

        // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
        // boundaries of the corresponding image object
        if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height) ||
            (textureDepth - offsetZ < depth))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSourceTextureTooSmall);
            return false;
        }

        *samples = texture->getSamples(PackParam<TextureTarget>(textureTargetToUse), level);
        *samples = (*samples == 0) ? 1 : *samples;
    }

    return true;
}

bool ValidateCompressedRegion(const Context *context,
                              angle::EntryPoint entryPoint,
                              const gl::Texture &Texture,
                              GLenum textureTarget,
                              const GLint textureLevel,
                              const InternalFormat &formatInfo,
                              const GLint offsetX,
                              const GLint offsetY,
                              const GLint offsetZ,
                              const GLsizei width,
                              const GLsizei height,
                              const GLsizei depth)
{
    ASSERT(formatInfo.compressed);

    bool subregionAlignedWithCompressedBlock = false;
    if (textureTarget == GL_TEXTURE_CUBE_MAP)
    {
        // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight
        textureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
    }
    const gl::TextureTarget textureTargetPacked = gl::PackParam<gl::TextureTarget>(textureTarget);
    ASSERT(textureTargetPacked != gl::TextureTarget::InvalidEnum);

    const gl::Extents &textureExtents   = Texture.getExtents(textureTargetPacked, textureLevel);
    subregionAlignedWithCompressedBlock = ((offsetX % formatInfo.compressedBlockWidth) == 0) &&
                                          ((offsetX + width == textureExtents.width) ||
                                           (width % formatInfo.compressedBlockWidth == 0));
    subregionAlignedWithCompressedBlock = subregionAlignedWithCompressedBlock &&
                                          ((offsetY % formatInfo.compressedBlockHeight) == 0) &&
                                          ((offsetY + height == textureExtents.height) ||
                                           (height % formatInfo.compressedBlockHeight == 0));
    subregionAlignedWithCompressedBlock = subregionAlignedWithCompressedBlock &&
                                          ((offsetZ % formatInfo.compressedBlockDepth) == 0) &&
                                          ((offsetZ + depth == textureExtents.depth) ||
                                           (depth % formatInfo.compressedBlockDepth == 0));

    // INVALID_VALUE is generated if the image format is compressed and the dimensions of the
    // subregion fail to meet the alignment constraints of the format.
    if (!subregionAlignedWithCompressedBlock)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidCompressedRegionSize);
        return false;
    }

    return true;
}

bool ValidateCopyMixedFormatCompatible(const Context *context,
                                       GLenum uncompressedFormat,
                                       GLenum compressedFormat)
{
    // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the
    // EXT_copy_image spec.
    switch (compressedFormat)
    {
        case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
        case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
        case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
        case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
        case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
        case GL_COMPRESSED_RGBA8_ETC2_EAC:
        case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
        case GL_COMPRESSED_RG11_EAC:
        case GL_COMPRESSED_SIGNED_RG11_EAC:
        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
        case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
        case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
        case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
        case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
        case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
        case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
        case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
        case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
        case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
        case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
        {
            switch (uncompressedFormat)
            {
                case GL_RGBA32UI:
                case GL_RGBA32I:
                case GL_RGBA32F:
                    return true;
                default:
                    return false;
            }
        }
        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
        case GL_COMPRESSED_RED_RGTC1_EXT:
        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
        case GL_COMPRESSED_RGB8_ETC2:
        case GL_COMPRESSED_SRGB8_ETC2:
        case GL_COMPRESSED_R11_EAC:
        case GL_COMPRESSED_SIGNED_R11_EAC:
        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
        {
            switch (uncompressedFormat)
            {
                case GL_RGBA16UI:
                case GL_RGBA16I:
                case GL_RGBA16F:
                case GL_RG32UI:
                case GL_RG32I:
                case GL_RG32F:
                    return true;
                case GL_RGBA16_EXT:
                case GL_RGBA16_SNORM_EXT:
                    return context->getExtensions().textureNorm16EXT;
                default:
                    return false;
            }
        }
        default:
            break;
    }

    return false;
}

bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo,
                                            const InternalFormat &dstFormatInfo)
{
    // Validates compressed format compatibility from Table 4.X.2 of the EXT_copy_image spec.

    ASSERT(srcFormatInfo.internalFormat != dstFormatInfo.internalFormat);

    const GLenum srcFormat = srcFormatInfo.internalFormat;
    const GLenum dstFormat = dstFormatInfo.internalFormat;

    switch (srcFormat)
    {
        case GL_COMPRESSED_RED_RGTC1_EXT:
            return (dstFormat == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT);
        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
            return (dstFormat == GL_COMPRESSED_RED_RGTC1_EXT);
        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
            return (dstFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
            return (dstFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT);
        case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
            return (dstFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
        case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
            return (dstFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
        case GL_COMPRESSED_R11_EAC:
            return (dstFormat == GL_COMPRESSED_SIGNED_R11_EAC);
        case GL_COMPRESSED_SIGNED_R11_EAC:
            return (dstFormat == GL_COMPRESSED_R11_EAC);
        case GL_COMPRESSED_RG11_EAC:
            return (dstFormat == GL_COMPRESSED_SIGNED_RG11_EAC);
        case GL_COMPRESSED_SIGNED_RG11_EAC:
            return (dstFormat == GL_COMPRESSED_RG11_EAC);
        default:
            break;
    }

    // Since they can't be the same format and are both compressed formats, one must be linear and
    // the other nonlinear.
    if (srcFormatInfo.colorEncoding == dstFormatInfo.colorEncoding)
    {
        return false;
    }

    const GLenum linearFormat = (srcFormatInfo.colorEncoding == GL_LINEAR) ? srcFormat : dstFormat;
    const GLenum nonLinearFormat =
        (srcFormatInfo.colorEncoding != GL_LINEAR) ? srcFormat : dstFormat;

    switch (linearFormat)
    {
        case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
            return (nonLinearFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
        case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
        case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
        case GL_COMPRESSED_RGB8_ETC2:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ETC2);
        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
        case GL_COMPRESSED_RGBA8_ETC2_EAC:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
        case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES);
        case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES);
        case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES);
        case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES);
        case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES);
        case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES);
        case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES);
        case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES);
        case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES);
        case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES);
        default:
            break;
    }

    return false;
}

bool ValidateCopyFormatCompatible(const Context *context,
                                  const InternalFormat &srcFormatInfo,
                                  const InternalFormat &dstFormatInfo)
{
    // Matching source and destination formats are compatible.
    if (srcFormatInfo.internalFormat == dstFormatInfo.internalFormat)
    {
        return true;
    }

    if (srcFormatInfo.compressed != dstFormatInfo.compressed)
    {
        GLenum uncompressedFormat = (!srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
                                                                : dstFormatInfo.internalFormat;
        GLenum compressedFormat   = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
                                                               : dstFormatInfo.internalFormat;

        return ValidateCopyMixedFormatCompatible(context, uncompressedFormat, compressedFormat);
    }

    if (!srcFormatInfo.compressed)
    {
        // Source and destination are uncompressed formats.
        return (srcFormatInfo.pixelBytes == dstFormatInfo.pixelBytes);
    }

    return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo);
}

const InternalFormat *GetValidFormatInfoForCopyImageSubData(const Context *context,
                                                            angle::EntryPoint entryPoint,
                                                            GLuint name,
                                                            GLenum target,
                                                            GLint level)
{
    // An INVALID_ENUM error is generated if either target is not
    // RENDERBUFFER or a valid texture target; is TEXTURE_BUFFER or one of the
    // cubemap face selectors.
    switch (target)
    {
        case GL_RENDERBUFFER:
        case GL_TEXTURE_2D:
        case GL_TEXTURE_CUBE_MAP:
        case GL_TEXTURE_3D:
        case GL_TEXTURE_2D_ARRAY:
            break;
        case GL_TEXTURE_2D_MULTISAMPLE:
            if (context->getClientVersion() < ES_3_1 &&
                !context->getExtensions().textureMultisampleANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
                return nullptr;
            }
            break;
        case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
            if (context->getClientVersion() < ES_3_2 &&
                !context->getExtensions().textureStorageMultisample2dArrayOES)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionOrES32Required);
                return nullptr;
            }
            break;
        case GL_TEXTURE_CUBE_MAP_ARRAY:
            if (context->getClientVersion() < ES_3_2 &&
                !context->getExtensions().textureCubeMapArrayAny())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
                return nullptr;
            }
            break;
        case GL_TEXTURE_EXTERNAL_OES:
            if (!context->getExtensions().EGLImageExternalOES)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
                return nullptr;
            }
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
            return nullptr;
    }

    if (target == GL_RENDERBUFFER)
    {
        Renderbuffer *renderbufferObject =
            context->getRenderbuffer(PackParam<RenderbufferID>(name));
        if (renderbufferObject == nullptr)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidRenderbufferName);
            return nullptr;
        }

        if (level != 0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
            return nullptr;
        }

        return renderbufferObject->getFormat().info;
    }

    // If the target is not RENDERBUFFER, it could only be a texture.
    Texture *textureObject = context->getTexture(PackParam<TextureID>(name));
    if (textureObject == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureName);
        return nullptr;
    }

    // the target must match the texture type.
    const TextureType textureType = textureObject->getType();
    if (ToGLenum(textureType) != target)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureTargetInvalidForCopyImage);
        return nullptr;
    }

    // Check that mip level is not greater than the maximum possible for the texture type.
    if (!ValidMipLevel(context, textureType, level))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return nullptr;
    }

    const gl::TextureTarget textureTarget = (textureType == TextureType::CubeMap)
                                                ? kCubeMapTextureTargetMin
                                                : NonCubeTextureTypeToTarget(textureType);
    const InternalFormat *internalFormat  = textureObject->getFormat(textureTarget, level).info;
    ASSERT(internalFormat != nullptr);

    // Check that an image exists at the specified level.
    if (internalFormat->internalFormat == GL_NONE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidTextureLevel);
        return nullptr;
    }

    return internalFormat;
}

bool ValidateCopyImageSubDataBase(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLuint srcName,
                                  GLenum srcTarget,
                                  GLint srcLevel,
                                  GLint srcX,
                                  GLint srcY,
                                  GLint srcZ,
                                  GLuint dstName,
                                  GLenum dstTarget,
                                  GLint dstLevel,
                                  GLint dstX,
                                  GLint dstY,
                                  GLint dstZ,
                                  GLsizei srcWidth,
                                  GLsizei srcHeight,
                                  GLsizei srcDepth)
{
    // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
    // of the corresponding image object
    if ((srcWidth < 0) || (srcHeight < 0) || (srcDepth < 0))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeSize);
        return false;
    }

    const InternalFormat *srcFormatInfo =
        GetValidFormatInfoForCopyImageSubData(context, entryPoint, srcName, srcTarget, srcLevel);
    if (srcFormatInfo == nullptr)
    {
        // Error already generated.
        return false;
    }

    const InternalFormat *dstFormatInfo =
        GetValidFormatInfoForCopyImageSubData(context, entryPoint, dstName, dstTarget, dstLevel);
    if (dstFormatInfo == nullptr)
    {
        // Error already generated.
        return false;
    }

    GLsizei dstWidth   = srcWidth;
    GLsizei dstHeight  = srcHeight;
    GLsizei dstDepth   = srcDepth;
    GLsizei srcSamples = 1;
    GLsizei dstSamples = 1;

    // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats
    // are not compatible, if one image is compressed and the other is uncompressed and the block
    // size of compressed image is not equal to the texel size of the compressed image.
    if (!ValidateCopyFormatCompatible(context, *srcFormatInfo, *dstFormatInfo))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIncompatibleTextures);
        return false;
    }

    if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel,
                                              srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth,
                                              &srcSamples))
    {
        return false;
    }

    // When copying from a compressed image to an uncompressed image the image texel dimensions
    // written to the uncompressed image will be source extent divided by the compressed texel block
    // dimensions.
    if ((srcFormatInfo->compressed) && (!dstFormatInfo->compressed))
    {
        ASSERT(srcFormatInfo->compressedBlockWidth != 0);
        ASSERT(srcFormatInfo->compressedBlockHeight != 0);

        dstWidth /= srcFormatInfo->compressedBlockWidth;
        dstHeight /= srcFormatInfo->compressedBlockHeight;
    }
    // When copying from an uncompressed image to a compressed image the image texel dimensions
    // written to the compressed image will be the source extent multiplied by the compressed texel
    // block dimensions.
    else if ((!srcFormatInfo->compressed) && (dstFormatInfo->compressed))
    {
        dstWidth *= dstFormatInfo->compressedBlockWidth;
        dstHeight *= dstFormatInfo->compressedBlockHeight;
    }

    if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel,
                                              dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth,
                                              &dstSamples))
    {
        return false;
    }

    gl::Texture *srcTexture           = context->getTexture({srcName});
    if (srcFormatInfo->compressed &&
        !ValidateCompressedRegion(context, entryPoint, *srcTexture, srcTarget, srcLevel,
                                  *srcFormatInfo, srcX, srcY, srcZ, srcWidth, srcHeight, srcDepth))
    {
        return false;
    }

    gl::Texture *dstTexture           = context->getTexture({dstName});
    if (dstFormatInfo->compressed &&
        !ValidateCompressedRegion(context, entryPoint, *dstTexture, dstTarget, dstLevel,
                                  *dstFormatInfo, dstX, dstY, dstZ, dstWidth, dstHeight, dstDepth))
    {
        return false;
    }

    // INVALID_OPERATION is generated if the source and destination number of samples do not match
    if (srcSamples != dstSamples)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
        return false;
    }

    return true;
}

bool ValidateCopyTexImageParametersBase(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        TextureTarget target,
                                        GLint level,
                                        GLenum internalformat,
                                        bool isSubImage,
                                        GLint xoffset,
                                        GLint yoffset,
                                        GLint zoffset,
                                        GLint x,
                                        GLint y,
                                        GLsizei width,
                                        GLsizei height,
                                        GLint border,
                                        Format *textureFormatOut)
{
    TextureType texType = TextureTargetToType(target);

    if (xoffset < 0 || yoffset < 0 || zoffset < 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 (std::numeric_limits<GLsizei>::max() - xoffset < width ||
        std::numeric_limits<GLsizei>::max() - yoffset < height)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
        return false;
    }

    if (std::numeric_limits<GLint>::max() - width < x ||
        std::numeric_limits<GLint>::max() - height < y)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIntegerOverflow);
        return false;
    }

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

    if (!ValidMipLevel(context, texType, level))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return false;
    }

    const State &state           = context->getState();
    Framebuffer *readFramebuffer = state.getReadFramebuffer();
    if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
    {
        return false;
    }

    // checkReadBufferResourceSamples = true. Treat renderToTexture textures as single sample since
    // they will be resolved before copying.
    if (!readFramebuffer->isDefault() &&
        !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
    {
        return false;
    }

    if (readFramebuffer->getReadBufferState() == GL_NONE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
        return false;
    }

    // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
    // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
    // attachment and WebGL defines it to be an error. We do the check unconditionally as the
    // situation is an application error that would lead to a crash in ANGLE.
    const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
    if (source == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingReadAttachment);
        return false;
    }

    if (source->isYUV())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCopyFromYUVFramebuffer);
        return false;
    }

    // OVR_multiview spec:
    // INVALID_FRAMEBUFFER_OPERATION is generated by commands that read from the
    // framebuffer such as BlitFramebuffer, ReadPixels, CopyTexImage*, and
    // CopyTexSubImage*, if the number of views in the current read framebuffer
    // is greater than 1.
    if (readFramebuffer->readDisallowedByMultiview())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
        return false;
    }

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

    GLint maxDimension = 0;
    switch (texType)
    {
        case TextureType::_2D:
            maxDimension = caps.max2DTextureSize;
            break;

        case TextureType::CubeMap:
        case TextureType::CubeMapArray:
            maxDimension = caps.maxCubeMapTextureSize;
            break;

        case TextureType::Rectangle:
            maxDimension = caps.maxRectangleTextureSize;
            break;

        case TextureType::_2DArray:
            maxDimension = caps.max2DTextureSize;
            break;

        case TextureType::_3D:
            maxDimension = caps.max3DTextureSize;
            break;

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

    Texture *texture = state.getTargetTexture(texType);
    if (!texture)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTextureNotBound);
        return false;
    }

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

    const InternalFormat &formatInfo =
        isSubImage ? *texture->getFormat(target, level).info
                   : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);

    if (formatInfo.depthBits > 0 || formatInfo.compressed)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFormat);
        return false;
    }

    if (isSubImage)
    {
        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
            static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kOffsetOverflow);
            return false;
        }
    }
    else
    {
        if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) &&
            width != height)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kCubemapIncomplete);
            return false;
        }

        if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
        {
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, internalformat);
            return false;
        }

        int maxLevelDimension = (maxDimension >> level);
        if (static_cast<int>(width) > maxLevelDimension ||
            static_cast<int>(height) > maxLevelDimension)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kResourceMaxTextureSize);
            return false;
        }
    }

    // Do not leak the previous texture format for non-subImage case.
    if (textureFormatOut && isSubImage)
    {
        *textureFormatOut = texture->getFormat(target, level);
    }

    // Detect texture copying feedback loops for WebGL.
    if (context->isWebGL())
    {
        if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFeedbackLoop);
            return false;
        }
    }

    return true;
}

const char *ValidateProgramPipelineDrawStates(const Context *context,
                                              const Extensions &extensions,
                                              ProgramPipeline *programPipeline)
{
    for (const ShaderType shaderType : gl::AllShaderTypes())
    {
        const SharedProgramExecutable &executable =
            programPipeline->getShaderProgramExecutable(shaderType);
        if (executable)
        {
            const char *errorMsg = ValidateProgramDrawStates(context, extensions, *executable);
            if (errorMsg)
            {
                return errorMsg;
            }
        }
    }

    return nullptr;
}

const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
{
    // An INVALID_OPERATION error is generated by any command that transfers vertices to the
    // GL or launches compute work if the current set of active
    // program objects cannot be executed, for reasons including:
    // - There is no current program object specified by UseProgram, there is a current program
    //    pipeline object, and that object is empty (no executable code is installed for any stage).
    // - A program object is active for at least one, but not all of the shader
    // stages that were present when the program was linked.
    if (!programPipeline->getExecutable().getLinkedShaderStages().any())
    {
        return gl::err::kNoExecutableCodeInstalled;
    }
    for (const ShaderType shaderType : gl::AllShaderTypes())
    {
        const Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
        if (shaderProgram)
        {
            const ProgramExecutable &executable = shaderProgram->getExecutable();
            for (const ShaderType programShaderType : executable.getLinkedShaderStages())
            {
                if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
                {
                    return gl::err::kNotAllStagesOfSeparableProgramUsed;
                }
            }
        }
    }

    // [EXT_geometry_shader] Section 11.1.gs Geometry Shaders
    // A non-separable program object or program pipeline object that includes
    // a geometry shader must also include a vertex shader.
    // An INVALID_OPERATION error is generated by any command that transfers
    // vertices to the GL if the current program state has a geometry shader
    // but no vertex shader.
    if (!programPipeline->getShaderProgram(ShaderType::Vertex) &&
        programPipeline->getShaderProgram(ShaderType::Geometry))
    {
        return gl::err::kNoActiveGraphicsShaderStage;
    }

    return nullptr;
}

const char *ValidateDrawStates(const Context *context, GLenum *outErrorCode)
{
    // Note all errors returned from this function are INVALID_OPERATION except for the draw
    // framebuffer completeness check.
    *outErrorCode = GL_INVALID_OPERATION;

    const Extensions &extensions = context->getExtensions();
    const State &state           = context->getState();

    // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
    // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
    // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
    VertexArray *vertexArray = state.getVertexArray();
    ASSERT(vertexArray);

    if (!extensions.webglCompatibilityANGLE &&
        ANGLE_UNLIKELY(vertexArray->hasInvalidMappedArrayBuffer()))
    {
        return kBufferMapped;
    }

    // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
    // Section 6.10 of the WebGL 1.0 spec.
    Framebuffer *framebuffer = state.getDrawFramebuffer();
    ASSERT(framebuffer);

    if (ANGLE_UNLIKELY(context->getLimitations().noSeparateStencilRefsAndMasks ||
                       extensions.webglCompatibilityANGLE))
    {
        ASSERT(framebuffer);
        const FramebufferAttachment *dsAttachment =
            framebuffer->getStencilOrDepthStencilAttachment();
        const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
        ASSERT(stencilBits <= 8);

        const DepthStencilState &depthStencilState = state.getDepthStencilState();
        if (depthStencilState.stencilTest && stencilBits > 0)
        {
            auto maxStencilValue = angle::BitMask<GLuint>(stencilBits);

            bool differentRefs =
                clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
                clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
            bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
                                       (depthStencilState.stencilBackWritemask & maxStencilValue);
            bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
                                  (depthStencilState.stencilBackMask & maxStencilValue);

            if (differentRefs || differentWritemasks || differentMasks)
            {
                if (!extensions.webglCompatibilityANGLE)
                {
                    WARN() << "This ANGLE implementation does not support separate front/back "
                              "stencil writemasks, reference values, or stencil mask values.";
                }
                return kStencilReferenceMaskOrMismatch;
            }
        }
    }

    if (!extensions.floatBlendEXT)
    {
        const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
            state.getBlendEnabledDrawBufferMask() &
            framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
        if (ANGLE_UNLIKELY(blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any()))
        {
            return kUnsupportedFloatBlending;
        }
    }

    if (ANGLE_UNLIKELY(extensions.renderSharedExponentQCOM))
    {
        if (!ValidateColorMasksForSharedExponentColorBuffers(state.getBlendStateExt(), framebuffer))
        {
            return kUnsupportedColorMaskForSharedExponentColorBuffer;
        }
    }

    if (ANGLE_UNLIKELY(context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
                       extensions.webglCompatibilityANGLE))
    {
        if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
        {
            if (extensions.webglCompatibilityANGLE)
            {
                return kInvalidConstantColor;
            }

            WARN() << kConstantColorAlphaLimitation;
            return kConstantColorAlphaLimitation;
        }
    }

    const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
    if (ANGLE_UNLIKELY(!framebufferStatus.isComplete()))
    {
        *outErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION;
        ASSERT(framebufferStatus.reason);
        return framebufferStatus.reason;
    }

    bool framebufferIsYUV = framebuffer->hasYUVAttachment();
    if (ANGLE_UNLIKELY(framebufferIsYUV))
    {
        const BlendState &blendState = state.getBlendState();
        if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue ||
            !blendState.colorMaskAlpha)
        {
            // When rendering into a YUV framebuffer, the color mask must have r g b and alpha set
            // to true.
            return kInvalidColorMaskForYUV;
        }

        if (blendState.blend)
        {
            // When rendering into a YUV framebuffer, blending must be disabled.
            return kInvalidBlendStateForYUV;
        }
    }
    else
    {
        if (ANGLE_UNLIKELY(framebuffer->hasExternalTextureAttachment()))
        {
            // It is an error to render into an external texture that is not YUV.
            return kExternalTextureAttachmentNotYUV;
        }
    }

    // Advanced blend equation can only be enabled for a single render target.
    const BlendStateExt &blendStateExt = state.getBlendStateExt();
    if (ANGLE_UNLIKELY(blendStateExt.getUsesAdvancedBlendEquationMask().any()))
    {
        const size_t drawBufferCount            = framebuffer->getDrawbufferStateCount();
        uint32_t advancedBlendRenderTargetCount = 0;

        for (size_t drawBufferIndex : blendStateExt.getUsesAdvancedBlendEquationMask())
        {
            if (drawBufferIndex < drawBufferCount &&
                framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE &&
                blendStateExt.getEnabledMask().test(drawBufferIndex) &&
                blendStateExt.getUsesAdvancedBlendEquationMask().test(drawBufferIndex))
            {
                ++advancedBlendRenderTargetCount;
            }
        }

        if (advancedBlendRenderTargetCount > 1)
        {
            return kAdvancedBlendEquationWithMRT;
        }
    }

    // Dual-source blending functions limit the number of supported draw buffers.
    if (ANGLE_UNLIKELY(blendStateExt.getUsesExtendedBlendFactorMask().any()))
    {
        // Imply the strictest spec interpretation to pass on all OpenGL drivers:
        // dual-source blending is considered active if the blend state contains
        // any SRC1 factor no matter what.
        const size_t drawBufferCount = framebuffer->getDrawbufferStateCount();
        for (size_t drawBufferIndex = context->getCaps().maxDualSourceDrawBuffers;
             drawBufferIndex < drawBufferCount; ++drawBufferIndex)
        {
            if (framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE)
            {
                return kDualSourceBlendingDrawBuffersLimit;
            }
        }
    }

    if (ANGLE_UNLIKELY(context->hasAnyEnabledClientAttrib()))
    {
        if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled())
        {
            // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
            // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
            // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
            // to drawArrays or drawElements will generate an INVALID_OPERATION error.
            return kVertexArrayNoBuffer;
        }

        if (state.getVertexArray()->hasEnabledNullPointerClientArray())
        {
            // This is an application error that would normally result in a crash, but we catch it
            // and return an error
            return kVertexArrayNoBufferPointer;
        }
    }

    // If we are running GLES1, there is no current program.
    if (ANGLE_LIKELY(context->getClientVersion() >= Version(2, 0)))
    {
        Program *program                    = state.getLinkedProgram(context);
        ProgramPipeline *programPipeline    = state.getLinkedProgramPipeline(context);
        const ProgramExecutable *executable = state.getProgramExecutable();

        bool programIsYUVOutput = false;

        if (ANGLE_LIKELY(program))
        {
            const char *errorMsg = ValidateProgramDrawStates(context, extensions, *executable);
            if (errorMsg)
            {
                return errorMsg;
            }

            programIsYUVOutput = executable->isYUVOutput();
        }
        else if (ANGLE_UNLIKELY(programPipeline))
        {
            const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
            if (errorMsg)
            {
                return errorMsg;
            }

            errorMsg = ValidateProgramPipelineDrawStates(context, extensions, programPipeline);
            if (errorMsg)
            {
                return errorMsg;
            }

            if (!programPipeline->isLinked())
            {
                return kProgramPipelineLinkFailed;
            }

            programIsYUVOutput = executable->isYUVOutput();
        }

        if (ANGLE_LIKELY(executable))
        {
            if (!executable->validateSamplers(context->getCaps()))
            {
                return kTextureTypeConflict;
            }

            if (ANGLE_UNLIKELY(executable->hasLinkedTessellationShader()))
            {
                if (!executable->hasLinkedShaderStage(ShaderType::Vertex))
                {
                    return kTessellationShaderRequiresVertexShader;
                }

                if (!executable->hasLinkedShaderStage(ShaderType::TessControl) ||
                    !executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
                {
                    return kTessellationShaderRequiresBothControlAndEvaluation;
                }
            }

            if (ANGLE_UNLIKELY(state.isTransformFeedbackActive()))
            {
                if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
                {
                    return kTransformFeedbackBufferMissing;
                }
            }
        }

        if (programIsYUVOutput != framebufferIsYUV)
        {
            // Both the program and framebuffer must match in YUV output state.
            return kYUVOutputMissmatch;
        }

        if (!state.validateSamplerFormats())
        {
            return kSamplerFormatMismatch;
        }

        // Do some additional WebGL-specific validation
        if (ANGLE_UNLIKELY(extensions.webglCompatibilityANGLE))
        {
            const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
            if (state.isTransformFeedbackActive() &&
                transformFeedbackObject->buffersBoundForOtherUseInWebGL())
            {
                return kTransformFeedbackBufferDoubleBound;
            }

            // Detect rendering feedback loops for WebGL.
            if (framebuffer->formsRenderingFeedbackLoopWith(context))
            {
                return kFeedbackLoop;
            }

            // Detect that the vertex shader input types match the attribute types
            if (!ValidateVertexShaderAttributeTypeMatch(context))
            {
                return kVertexShaderTypeMismatch;
            }

            if (!context->getState().getRasterizerState().rasterizerDiscard &&
                !context->getState().allActiveDrawBufferChannelsMasked())
            {
                // Detect that if there's active color buffer without fragment shader output
                if (!ValidateFragmentShaderColorBufferMaskMatch(context))
                {
                    return kDrawBufferMaskMismatch;
                }

                // Detect that the color buffer types match the fragment shader output types
                if (!ValidateFragmentShaderColorBufferTypeMatch(context))
                {
                    return kDrawBufferTypeMismatch;
                }
            }

            const VertexArray *vao = context->getState().getVertexArray();
            if (vao->hasTransformFeedbackBindingConflict(context))
            {
                return kVertexBufferBoundForTransformFeedback;
            }

            // Validate that we are rendering with a linked program.
            if (program != nullptr && !program->isLinked())
            {
                return kProgramNotLinked;
            }
        }

        // The QCOM_framebuffer_foveated spec:
        if (ANGLE_UNLIKELY(framebuffer->isFoveationEnabled()))
        {
            ASSERT(extensions.framebufferFoveatedQCOM);

            //   INVALID_OPERATION is generated if a rendering command is issued and the
            //   current bound program uses tessellation or geometry shaders.
            if (executable->hasLinkedShaderStage(gl::ShaderType::Geometry) ||
                executable->hasLinkedShaderStage(gl::ShaderType::TessControl) ||
                executable->hasLinkedShaderStage(gl::ShaderType::TessEvaluation))
            {
                return err::kGeometryOrTessellationShaderBoundForFoveatedDraw;
            }

            // 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 (framebuffer->hasAnyAttachmentChanged())
            {
                return err::kFramebufferFoveationAttachmentChanged;
            }
        }
    }

    *outErrorCode = GL_NO_ERROR;
    return nullptr;
}

const char *ValidateProgramPipeline(const Context *context)
{
    const State &state = context->getState();
    // If we are running GLES1, there is no current program.
    if (context->getClientVersion() >= Version(2, 0))
    {
        ProgramPipeline *programPipeline = state.getProgramPipeline();
        if (programPipeline)
        {
            const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
            if (errorMsg)
            {
                return errorMsg;
            }
        }
    }
    return nullptr;
}

void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode)
{
    const State &state                      = context->getState();
    TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
    if (state.isTransformFeedbackActiveUnpaused())
    {
        if (!ValidateTransformFeedbackPrimitiveMode(context, entryPoint,
                                                    curTransformFeedback->getPrimitiveMode(), mode))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawModeTransformFeedback);
            return;
        }
    }

    const Extensions &extensions = context->getExtensions();

    switch (mode)
    {
        case PrimitiveMode::Points:
        case PrimitiveMode::Lines:
        case PrimitiveMode::LineLoop:
        case PrimitiveMode::LineStrip:
        case PrimitiveMode::Triangles:
        case PrimitiveMode::TriangleStrip:
        case PrimitiveMode::TriangleFan:
            break;

        case PrimitiveMode::LinesAdjacency:
        case PrimitiveMode::LineStripAdjacency:
        case PrimitiveMode::TrianglesAdjacency:
        case PrimitiveMode::TriangleStripAdjacency:
            if (!extensions.geometryShaderAny() && context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
                return;
            }
            break;

        case PrimitiveMode::Patches:
            if (!extensions.tessellationShaderAny() && context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderEXTNotEnabled);
                return;
            }
            break;

        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDrawMode);
            return;
    }

    // If we are running GLES1, there is no current program.
    if (context->getClientVersion() >= Version(2, 0))
    {
        const ProgramExecutable *executable = state.getProgramExecutable();
        ASSERT(executable);

        // Do geometry shader specific validations
        if (executable->hasLinkedShaderStage(ShaderType::Geometry))
        {
            if (!IsCompatibleDrawModeWithGeometryShader(
                    mode, executable->getGeometryShaderInputPrimitiveType()))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       kIncompatibleDrawModeAgainstGeometryShader);
                return;
            }
        }

        if (executable->hasLinkedTessellationShader() && mode != PrimitiveMode::Patches)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                   kIncompatibleDrawModeWithTessellationShader);
            return;
        }

        if (!executable->hasLinkedTessellationShader() && mode == PrimitiveMode::Patches)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                   kIncompatibleDrawModeWithoutTessellationShader);
            return;
        }
    }

    // An error should be recorded.
    UNREACHABLE();
}

bool ValidateDrawArraysInstancedANGLE(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      PrimitiveMode mode,
                                      GLint first,
                                      GLsizei count,
                                      GLsizei primcount)
{
    if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0))
    {
        return false;
    }

    return ValidateDrawInstancedANGLE(context, entryPoint);
}

bool ValidateDrawArraysInstancedEXT(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    PrimitiveMode mode,
                                    GLint first,
                                    GLsizei count,
                                    GLsizei primcount)
{
    if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount, 0))
    {
        return false;
    }

    return true;
}

const char *ValidateDrawElementsStates(const Context *context)
{
    const State &state = context->getState();

    if (ANGLE_UNLIKELY(context->getStateCache().isTransformFeedbackActiveUnpaused()))
    {
        // EXT_geometry_shader allows transform feedback to work with all draw commands.
        // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
        if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2)
        {
            // It is an invalid operation to call DrawElements, DrawRangeElements or
            // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
            // 86)
            return kUnsupportedDrawModeForTransformFeedback;
        }
    }

    const VertexArray *vao     = state.getVertexArray();
    Buffer *elementArrayBuffer = vao->getElementArrayBuffer();

    if (elementArrayBuffer)
    {
        if (ANGLE_UNLIKELY(context->isWebGL()) &&
            elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
        {
            return kElementArrayBufferBoundForTransformFeedback;
        }
        if (ANGLE_UNLIKELY(elementArrayBuffer->isMapped()) &&
            ANGLE_UNLIKELY(!elementArrayBuffer->isImmutable() ||
                           (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0))
        {
            return kBufferMapped;
        }
    }
    else
    {
        // [WebGL 1.0] Section 6.2 No Client Side Arrays
        // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
        // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
        if (ANGLE_UNLIKELY(!context->getState().areClientArraysEnabled() || context->isWebGL()))
        {
            return kMustHaveElementArrayBinding;
        }
    }

    return nullptr;
}

bool ValidateDrawElementsInstancedANGLE(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        PrimitiveMode mode,
                                        GLsizei count,
                                        DrawElementsType type,
                                        const void *indices,
                                        GLsizei primcount)
{
    if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
                                           primcount, 0))
    {
        return false;
    }

    return ValidateDrawInstancedANGLE(context, entryPoint);
}

bool ValidateDrawElementsInstancedEXT(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      PrimitiveMode mode,
                                      GLsizei count,
                                      DrawElementsType type,
                                      const void *indices,
                                      GLsizei primcount)
{
    if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
                                           primcount, 0))
    {
        return false;
    }

    return true;
}

bool ValidateGetUniformBase(const Context *context,
                            angle::EntryPoint entryPoint,
                            ShaderProgramID program,
                            UniformLocation location)
{
    if (program.value == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kProgramDoesNotExist);
        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;
    }

    if (!programObject->getExecutable().isValidUniformLocation(location))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidUniformLocation);
        return false;
    }

    return true;
}

bool ValidateSizedGetUniform(const Context *context,
                             angle::EntryPoint entryPoint,
                             ShaderProgramID program,
                             UniformLocation location,
                             GLsizei bufSize,
                             GLsizei *length)
{
    if (length)
    {
        *length = 0;
    }

    if (!ValidateGetUniformBase(context, entryPoint, program, location))
    {
        return false;
    }

    if (bufSize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNegativeBufSize);
        return false;
    }

    Program *programObject = context->getProgramResolveLink(program);
    ASSERT(programObject);

    // sized queries -- ensure the provided buffer is large enough
    const LinkedUniform &uniform = programObject->getExecutable().getUniformByLocation(location);
    size_t requiredBytes         = VariableExternalSize(uniform.getType());
    if (static_cast<size_t>(bufSize) < requiredBytes)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
        return false;
    }

    if (length)
    {
        *length = VariableComponentCount(uniform.getType());
    }
    return true;
}

bool ValidateGetnUniformfvEXT(const Context *context,
                              angle::EntryPoint entryPoint,
                              ShaderProgramID program,
                              UniformLocation location,
                              GLsizei bufSize,
                              const GLfloat *params)
{
    return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
}

bool ValidateGetnUniformfvRobustANGLE(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      ShaderProgramID program,
                                      UniformLocation location,
                                      GLsizei bufSize,
                                      const GLsizei *length,
                                      const GLfloat *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetnUniformivEXT(const Context *context,
                              angle::EntryPoint entryPoint,
                              ShaderProgramID program,
                              UniformLocation location,
                              GLsizei bufSize,
                              const GLint *params)
{
    return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
}

bool ValidateGetnUniformivRobustANGLE(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      ShaderProgramID program,
                                      UniformLocation location,
                                      GLsizei bufSize,
                                      const GLsizei *length,
                                      const GLint *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetnUniformuivRobustANGLE(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       ShaderProgramID program,
                                       UniformLocation location,
                                       GLsizei bufSize,
                                       const GLsizei *length,
                                       const GLuint *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetUniformfvRobustANGLE(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     ShaderProgramID program,
                                     UniformLocation location,
                                     GLsizei bufSize,
                                     const GLsizei *length,
                                     const GLfloat *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    // bufSize is validated in ValidateSizedGetUniform
    if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetUniformivRobustANGLE(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     ShaderProgramID program,
                                     UniformLocation location,
                                     GLsizei bufSize,
                                     const GLsizei *length,
                                     const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    // bufSize is validated in ValidateSizedGetUniform
    if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetUniformuivRobustANGLE(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      ShaderProgramID program,
                                      UniformLocation location,
                                      GLsizei bufSize,
                                      const GLsizei *length,
                                      const GLuint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    GLsizei writeLength = 0;

    // bufSize is validated in ValidateSizedGetUniform
    if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateDiscardFramebufferBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    GLenum target,
                                    GLsizei numAttachments,
                                    const GLenum *attachments,
                                    bool defaultFramebuffer)
{
    if (numAttachments < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeAttachments);
        return false;
    }

    for (GLsizei i = 0; i < numAttachments; ++i)
    {
        if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
        {
            if (defaultFramebuffer)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kDefaultFramebufferInvalidAttachment);
                return false;
            }

            if (attachments[i] >=
                GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
                return false;
            }
        }
        else
        {
            switch (attachments[i])
            {
                case GL_DEPTH_ATTACHMENT:
                case GL_STENCIL_ATTACHMENT:
                case GL_DEPTH_STENCIL_ATTACHMENT:
                    if (defaultFramebuffer)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                               kDefaultFramebufferInvalidAttachment);
                        return false;
                    }
                    break;
                case GL_COLOR:
                case GL_DEPTH:
                case GL_STENCIL:
                    if (!defaultFramebuffer)
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                               kDefaultFramebufferAttachmentOnUserFBO);
                        return false;
                    }
                    break;
                default:
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
                    return false;
            }
        }
    }

    return true;
}

bool ValidateInsertEventMarkerEXT(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLsizei length,
                                  const char *marker)
{
    return true;
}

bool ValidatePushGroupMarkerEXT(const Context *context,
                                angle::EntryPoint entryPoint,
                                GLsizei length,
                                const char *marker)
{
    // This is to prevent the stack from getting too large. The limit used here is also used for
    // pushing debug groups.
    if (context->getState().getGroupMarkerCount() >= context->getCaps().maxDebugGroupStackDepth)
    {
        ANGLE_VALIDATION_ERROR(GL_STACK_OVERFLOW, kExceedsMaxGroupMarkerStackDepth);
        return false;
    }

    return true;
}

bool ValidateEGLImageObject(const Context *context,
                            angle::EntryPoint entryPoint,
                            TextureType type,
                            egl::ImageID imageID)
{
    ASSERT(context->getDisplay());
    if (!context->getDisplay()->isValidImage(imageID))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEGLImage);
        return false;
    }

    egl::Image *imageObject = context->getDisplay()->getImage(imageID);
    if (imageObject->getSamples() > 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageCannotCreate2DMultisampled);
        return false;
    }

    if (!imageObject->isTexturable(context))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureFormatNotSupported);
        return false;
    }

    // Validate source egl image and target texture are compatible
    size_t depth = static_cast<size_t>(imageObject->getExtents().depth);
    if (imageObject->isYUV() && type != TextureType::External)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                               "Image is YUV, target must be TEXTURE_EXTERNAL_OES");
        return false;
    }

    if (depth > 1 && type != TextureType::_2DArray && type != TextureType::CubeMap &&
        type != TextureType::CubeMapArray && type != TextureType::_3D)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
        return false;
    }

    if (imageObject->isCubeMap() && type != TextureType::CubeMapArray &&
        (type != TextureType::CubeMap || depth > gl::kCubeFaceCount))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
        return false;
    }

    if (imageObject->getLevelCount() > 1 && type == TextureType::External)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
        return false;
    }

    if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                               "Mismatch between Image and Context Protected Content state");
        return false;
    }

    return true;
}

bool ValidateEGLImageTargetTexture2DOES(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        TextureType type,
                                        egl::ImageID image)
{
    switch (type)
    {
        case TextureType::_2D:
            if (!context->getExtensions().EGLImageOES)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
                return false;
            }
            break;

        case TextureType::_2DArray:
            if (!context->getExtensions().EGLImageArrayEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
                return false;
            }
            break;

        case TextureType::External:
            if (!context->getExtensions().EGLImageExternalOES)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, ToGLenum(type));
                return false;
            }
            break;

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

    return ValidateEGLImageObject(context, entryPoint, type, image);
}

bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
                                                  angle::EntryPoint entryPoint,
                                                  GLenum target,
                                                  egl::ImageID image)
{
    switch (target)
    {
        case GL_RENDERBUFFER:
            break;

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

    ASSERT(context->getDisplay());
    if (!context->getDisplay()->isValidImage(image))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidEGLImage);
        return false;
    }

    egl::Image *imageObject = context->getDisplay()->getImage(image);
    if (!imageObject->isRenderable(context))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kEGLImageRenderbufferFormatNotSupported);
        return false;
    }
    const auto &glState = context->getState();
    if (imageObject->hasProtectedContent() != glState.hasProtectedContent())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                               "Mismatch between Image and Context Protected Content state");
        return false;
    }

    Renderbuffer *renderbuffer = glState.getCurrentRenderbuffer();
    if (renderbuffer == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kRenderbufferNotBound);
        return false;
    }

    return true;
}

bool ValidateProgramBinaryBase(const Context *context,
                               angle::EntryPoint entryPoint,
                               ShaderProgramID program,
                               GLenum binaryFormat,
                               const void *binary,
                               GLint length)
{
    Program *programObject = GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
    if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
        programBinaryFormats.end())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
        return false;
    }

    if (context->hasActiveTransformFeedback(program))
    {
        // ES 3.0.4 section 2.15 page 91
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
        return false;
    }

    return true;
}

bool ValidateGetProgramBinaryBase(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  ShaderProgramID program,
                                  GLsizei bufSize,
                                  const GLsizei *length,
                                  const GLenum *binaryFormat,
                                  const void *binary)
{
    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;
    }

    if (context->getCaps().programBinaryFormats.empty())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoProgramBinaryFormats);
        return false;
    }

    return true;
}

bool ValidateDrawBuffersBase(const Context *context,
                             angle::EntryPoint entryPoint,
                             GLsizei n,
                             const GLenum *bufs)
{
    // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
    if (n < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeCount);
        return false;
    }
    if (n > context->getCaps().maxDrawBuffers)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
        return false;
    }
    // INVALID_VALUE is generated if n != 0 and bufs is NULL
    if (n != 0 && bufs == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL);
        return false;
    }

    ASSERT(context->getState().getDrawFramebuffer());
    FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
    GLuint maxColorAttachment   = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;

    // This should come first before the check for the default frame buffer
    // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
    // rather than INVALID_OPERATION
    for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
    {
        const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;

        if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
            (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
             bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
        {
            // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
            // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
            // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
            // 3.1 is still a bit ambiguous about the error, but future specs are
            // expected to clarify that GL_INVALID_ENUM is the correct error.
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidDrawBuffer);
            return false;
        }
        else if (bufs[colorAttachment] >= maxColorAttachment)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
            return false;
        }
        else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
                 frameBufferId.value != 0)
        {
            // INVALID_OPERATION-GL is bound to buffer and ith argument
            // is not COLOR_ATTACHMENTi or NONE
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawBufferValue);
            return false;
        }
    }

    // INVALID_OPERATION is generated if GL is bound to the default framebuffer
    // and n is not 1 or bufs is bound to value other than BACK and NONE
    if (frameBufferId.value == 0)
    {
        if (n != 1)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidDrawBufferCountForDefault);
            return false;
        }

        if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferInvalidDrawBuffer);
            return false;
        }
    }

    return true;
}

bool ValidateGetBufferPointervBase(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   BufferBinding target,
                                   GLenum pname,
                                   GLsizei *length,
                                   void *const *params)
{
    if (length)
    {
        *length = 0;
    }

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

    switch (pname)
    {
        case GL_BUFFER_MAP_POINTER:
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
    // target bound to zero generate an INVALID_OPERATION error."
    // GLES 3.1 section 6.6 explicitly specifies this error.
    if (context->getState().getTargetBuffer(target) == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferPointerNotAvailable);
        return false;
    }

    if (length)
    {
        *length = 1;
    }

    return true;
}

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

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

    if (buffer == nullptr || !buffer->isMapped())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotMapped);
        return false;
    }

    return true;
}

bool ValidateMapBufferRangeBase(const Context *context,
                                angle::EntryPoint entryPoint,
                                BufferBinding target,
                                GLintptr offset,
                                GLsizeiptr length,
                                GLbitfield access)
{
    if (!context->isValidBufferBinding(target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidBufferTypes);
        return false;
    }

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

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

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

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

    // Check for buffer overflow
    CheckedNumeric<size_t> checkedOffset(offset);
    auto checkedSize = checkedOffset + length;

    if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kMapOutOfRange);
        return false;
    }

    // Check for invalid bits in the mask
    constexpr GLbitfield kAllAccessBits =
        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
        GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT;

    if (buffer->isImmutable())
    {
        // GL_EXT_buffer_storage's additions to glMapBufferRange
        constexpr GLbitfield kBufferStorageAccessBits =
            kAllAccessBits | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT;

        if ((access & ~kBufferStorageAccessBits) != 0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAccessBits);
            return false;
        }

        // It is invalid if any of bufferStorageMatchedAccessBits bits are included in access,
        // but the same bits are not included in the buffer's storage flags
        constexpr GLbitfield kBufferStorageMatchedAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
                                                               GL_MAP_PERSISTENT_BIT_EXT |
                                                               GL_MAP_COHERENT_BIT_EXT;
        GLbitfield accessFlags = access & kBufferStorageMatchedAccessBits;
        if ((accessFlags & buffer->getStorageExtUsageFlags()) != accessFlags)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBits);
            return false;
        }
    }
    else if ((access & ~kAllAccessBits) != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidAccessBits);
        return false;
    }

    if (length == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kLengthZero);
        return false;
    }

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

    // Check for invalid bit combinations
    if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
        return false;
    }

    GLbitfield writeOnlyBits =
        GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;

    if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsRead);
        return false;
    }

    if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
        return false;
    }

    return ValidateMapBufferBase(context, entryPoint, target);
}

bool ValidateFlushMappedBufferRangeBase(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        BufferBinding target,
                                        GLintptr offset,
                                        GLsizeiptr length)
{
    if (offset < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeOffset);
        return false;
    }

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

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

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

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

    if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidFlushTarget);
        return false;
    }

    // Check for buffer overflow
    CheckedNumeric<size_t> checkedOffset(offset);
    auto checkedSize = checkedOffset + length;

    if (!checkedSize.IsValid() ||
        checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidFlushOutOfRange);
        return false;
    }

    return true;
}

bool ValidateGenOrDelete(ErrorSet *errors, angle::EntryPoint entryPoint, GLint n, const void *ids)
{
    if (n < 0)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
        return false;
    }

    if (n > 0 && ids == nullptr)
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kPLSParamsNULL);
        return false;
    }

    return true;
}

bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize)
{
    if (bufSize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kNegativeBufSize);
        return false;
    }

    return true;
}

bool ValidateRobustBufferSize(const Context *context,
                              angle::EntryPoint entryPoint,
                              GLsizei bufSize,
                              GLsizei numParams)
{
    if (bufSize < numParams)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientParams);
        return false;
    }

    return true;
}

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

    const Version &clientVersion = context->getClientVersion();

    switch (pname)
    {
        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
            break;

        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
            if (!context->getExtensions().multiviewOVR)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
            if (!context->getExtensions().multisampledRenderToTextureEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
            if (clientVersion < ES_3_0 && !context->getExtensions().sRGBEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
            if (clientVersion < ES_3_0 && !context->getExtensions().colorBufferHalfFloatEXT &&
                !context->getExtensions().colorBufferFloatRgbCHROMIUM &&
                !context->getExtensions().colorBufferFloatRgbaCHROMIUM)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
        case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
        case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
        case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
        case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
        case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
            if (clientVersion < ES_3_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
                return false;
            }
            break;

        case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
            if (!context->getExtensions().geometryShaderAny() && clientVersion < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
                return false;
            }
            break;

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

    // Determine if the attachment is a valid enum
    switch (attachment)
    {
        case GL_BACK:
        case GL_DEPTH:
        case GL_STENCIL:
            if (clientVersion < ES_3_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
                return false;
            }
            break;

        case GL_DEPTH_STENCIL_ATTACHMENT:
            if (clientVersion < ES_3_0 && !context->isWebGL1())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
                return false;
            }
            break;

        case GL_DEPTH_ATTACHMENT:
        case GL_STENCIL_ATTACHMENT:
            break;

        default:
            if ((clientVersion < ES_3_0 && !context->getExtensions().drawBuffersEXT) ||
                attachment < GL_COLOR_ATTACHMENT0_EXT ||
                (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
                    static_cast<GLuint>(context->getCaps().maxColorAttachments))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidAttachment);
                return false;
            }
            [[fallthrough]];

        case GL_COLOR_ATTACHMENT0:
            if (context->getPrivateState().isActivelyOverriddenPLSDrawBuffer(
                    attachment - GL_COLOR_ATTACHMENT0_EXT))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPLSColorAttachmentReserved);
                return false;
            }
            break;
    }

    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (framebuffer->isDefault())
    {
        if (clientVersion < ES_3_0)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebufferTarget);
            return false;
        }

        switch (attachment)
        {
            case GL_BACK:
            case GL_DEPTH:
            case GL_STENCIL:
                break;

            default:
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
                return false;
        }
    }
    else
    {
        if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
        {
            // Valid attachment query
        }
        else
        {
            switch (attachment)
            {
                case GL_DEPTH_ATTACHMENT:
                case GL_STENCIL_ATTACHMENT:
                    break;

                case GL_DEPTH_STENCIL_ATTACHMENT:
                    if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
                    {
                        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
                        return false;
                    }
                    break;

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

    const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
    if (attachmentObject)
    {
        ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
               attachmentObject->type() == GL_TEXTURE ||
               attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);

        switch (pname)
        {
            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
                if (attachmentObject->type() != GL_RENDERBUFFER &&
                    attachmentObject->type() != GL_TEXTURE)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
                    return false;
                }
                break;

            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
                if (attachmentObject->type() != GL_TEXTURE)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
                    return false;
                }
                break;

            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
                if (attachmentObject->type() != GL_TEXTURE)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
                    return false;
                }
                break;

            case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
                if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidAttachment);
                    return false;
                }
                break;

            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
                if (attachmentObject->type() != GL_TEXTURE)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFramebufferIncompleteAttachment);
                    return false;
                }
                break;

            default:
                break;
        }
    }
    else
    {
        // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
        // is NONE, then querying any other pname will generate INVALID_ENUM.

        // ES 3.0.2 spec pg 235 states that if the attachment type is none,
        // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
        // INVALID_OPERATION for all other pnames

        switch (pname)
        {
            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                break;

            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
                if (clientVersion < ES_3_0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter);
                    return false;
                }
                break;

            default:
                if (clientVersion < ES_3_0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFramebufferAttachmentParameter);
                    return false;
                }
                else
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                           kInvalidFramebufferAttachmentParameter);
                    return false;
                }
        }
    }

    if (numParams)
    {
        *numParams = 1;
    }

    return true;
}

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

    switch (pname)
    {
        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
            break;
        case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
            if (!context->getExtensions().geometryShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
                return false;
            }
            break;
        case GL_FRAMEBUFFER_FLIP_Y_MESA:
            if (!context->getExtensions().framebufferFlipYMESA)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
                return false;
            }
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
            return false;
    }

    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
    ASSERT(framebuffer);

    if (framebuffer->isDefault())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kDefaultFramebuffer);
        return false;
    }
    return true;
}

bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
                                                            angle::EntryPoint entryPoint,
                                                            GLenum target,
                                                            GLenum attachment,
                                                            GLenum pname,
                                                            GLsizei bufSize,
                                                            const GLsizei *length,
                                                            const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;
    if (!ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
                                                         pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
                                             angle::EntryPoint entryPoint,
                                             BufferBinding target,
                                             GLenum pname,
                                             GLsizei bufSize,
                                             const GLsizei *length,
                                             const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);
    return true;
}

bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
                                               angle::EntryPoint entryPoint,
                                               BufferBinding target,
                                               GLenum pname,
                                               GLsizei bufSize,
                                               const GLsizei *length,
                                               const GLint64 *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetProgramivBase(const Context *context,
                              angle::EntryPoint entryPoint,
                              ShaderProgramID program,
                              GLenum pname,
                              GLsizei *numParams)
{
    // Currently, all GetProgramiv queries return 1 parameter
    if (numParams)
    {
        *numParams = 1;
    }

    if (context->isContextLost())
    {
        if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
        {
            // The context needs to return a value in this case.
            // It will also generate a CONTEXT_LOST error.
            return true;
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
            return false;
        }
    }

    // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
    Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
                                 ? GetValidProgramNoResolve(context, entryPoint, program)
                                 : GetValidProgram(context, entryPoint, program);
    if (programObject == nullptr)
    {
        // Error already generated.
        return false;
    }

    switch (pname)
    {
        case GL_DELETE_STATUS:
        case GL_LINK_STATUS:
        case GL_VALIDATE_STATUS:
        case GL_INFO_LOG_LENGTH:
        case GL_ATTACHED_SHADERS:
        case GL_ACTIVE_ATTRIBUTES:
        case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
        case GL_ACTIVE_UNIFORMS:
        case GL_ACTIVE_UNIFORM_MAX_LENGTH:
            break;

        case GL_PROGRAM_BINARY_READY_ANGLE:
            if (!context->getExtensions().programBinaryReadinessQueryANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_PROGRAM_BINARY_LENGTH:
            if (context->getClientVersion() < ES_3_0 &&
                !context->getExtensions().getProgramBinaryOES)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_ACTIVE_UNIFORM_BLOCKS:
        case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
        case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
        case GL_TRANSFORM_FEEDBACK_VARYINGS:
        case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
            if (context->getClientVersion() < ES_3_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30);
                return false;
            }
            break;

        case GL_PROGRAM_SEPARABLE:
        case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
            if (context->getClientVersion() < Version(3, 1))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
                return false;
            }
            break;

        case GL_COMPUTE_WORK_GROUP_SIZE:
            if (context->getClientVersion() < Version(3, 1))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
                return false;
            }

            // [OpenGL ES 3.1] Chapter 7.12 Page 122
            // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
            // program which has not been linked successfully, or which does not contain objects to
            // form a compute shader.
            if (!programObject->isLinked())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
                return false;
            }
            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoActiveComputeShaderStage);
                return false;
            }
            break;

        case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
        case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
        case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
        case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
            if (!context->getExtensions().geometryShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGeometryShaderExtensionNotEnabled);
                return false;
            }

            // [EXT_geometry_shader] Chapter 7.12
            // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
            // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
            // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
            // successfully, or which does not contain objects to form a geometry shader.
            if (!programObject->isLinked())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
                return false;
            }
            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kNoActiveGeometryShaderStage);
                return false;
            }
            break;

        case GL_COMPLETION_STATUS_KHR:
            if (!context->getExtensions().parallelShaderCompileKHR)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
                return false;
            }
            break;
        case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT:
            if (!context->getExtensions().tessellationShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderEXTNotEnabled);
                return false;
            }
            if (!programObject->isLinked())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
                return false;
            }
            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::TessControl))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       kNoActiveTessellationControlShaderStage);
                return false;
            }
            break;
        case GL_TESS_GEN_MODE_EXT:
        case GL_TESS_GEN_SPACING_EXT:
        case GL_TESS_GEN_VERTEX_ORDER_EXT:
        case GL_TESS_GEN_POINT_MODE_EXT:
            if (!context->getExtensions().tessellationShaderAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTessellationShaderEXTNotEnabled);
                return false;
            }
            if (!programObject->isLinked())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kProgramNotLinked);
                return false;
            }
            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::TessEvaluation))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       kNoActiveTessellationEvaluationShaderStage);
                return false;
            }
            break;
        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    return true;
}

bool ValidateGetProgramivRobustANGLE(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     ShaderProgramID program,
                                     GLenum pname,
                                     GLsizei bufSize,
                                     const GLsizei *length,
                                     const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetProgramivBase(context, entryPoint, program, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
                                                   angle::EntryPoint entryPoint,
                                                   GLenum target,
                                                   GLenum pname,
                                                   GLsizei bufSize,
                                                   const GLsizei *length,
                                                   const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetShaderivRobustANGLE(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    ShaderProgramID shader,
                                    GLenum pname,
                                    GLsizei bufSize,
                                    const GLsizei *length,
                                    const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetShaderivBase(context, entryPoint, shader, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          TextureType target,
                                          GLenum pname,
                                          GLsizei bufSize,
                                          const GLsizei *length,
                                          const GLfloat *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateGetTexParameterivRobustANGLE(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          TextureType target,
                                          GLenum pname,
                                          GLsizei bufSize,
                                          const GLsizei *length,
                                          const GLint *params)
{

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }
    GLsizei numParams = 0;
    if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);
    return true;
}

bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           TextureType target,
                                           GLenum pname,
                                           GLsizei bufSize,
                                           const GLsizei *length,
                                           const GLint *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            TextureType target,
                                            GLenum pname,
                                            GLsizei bufSize,
                                            const GLsizei *length,
                                            const GLuint *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateTexParameterfvRobustANGLE(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       TextureType target,
                                       GLenum pname,
                                       GLsizei bufSize,
                                       const GLfloat *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
}

bool ValidateTexParameterivRobustANGLE(const Context *context,
                                       angle::EntryPoint entryPoint,
                                       TextureType target,
                                       GLenum pname,
                                       GLsizei bufSize,
                                       const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
}

bool ValidateTexParameterIivRobustANGLE(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        TextureType target,
                                        GLenum pname,
                                        GLsizei bufSize,
                                        const GLint *params)
{
    // TODO: Uncomment glTexParameterIivRobustANGLE tests in
    // PixelLocalStorageValidationTest.ModifyTextureDuringPLS once implemented.
    UNIMPLEMENTED();
    return false;
}

bool ValidateTexParameterIuivRobustANGLE(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target,
                                         GLenum pname,
                                         GLsizei bufSize,
                                         const GLuint *params)
{
    // TODO: Uncomment glTexParameterIuivRobustANGLE tests in
    // PixelLocalStorageValidationTest.ModifyTextureDuringPLS once implemented.
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
                                              angle::EntryPoint entryPoint,
                                              SamplerID sampler,
                                              GLenum pname,
                                              GLsizei bufSize,
                                              const GLsizei *length,
                                              const GLfloat *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams, params))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);
    return true;
}

bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
                                              angle::EntryPoint entryPoint,
                                              SamplerID sampler,
                                              GLenum pname,
                                              GLsizei bufSize,
                                              const GLsizei *length,
                                              const GLint *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams, params))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);
    return true;
}

bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
                                               angle::EntryPoint entryPoint,
                                               SamplerID sampler,
                                               GLenum pname,
                                               GLsizei bufSize,
                                               const GLsizei *length,
                                               const GLint *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
                                                angle::EntryPoint entryPoint,
                                                SamplerID sampler,
                                                GLenum pname,
                                                GLsizei bufSize,
                                                const GLsizei *length,
                                                const GLuint *params)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           SamplerID sampler,
                                           GLenum pname,
                                           GLsizei bufSize,
                                           const GLfloat *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
}

bool ValidateSamplerParameterivRobustANGLE(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           SamplerID sampler,
                                           GLenum pname,
                                           GLsizei bufSize,
                                           const GLint *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
}

bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            SamplerID sampler,
                                            GLenum pname,
                                            GLsizei bufSize,
                                            const GLint *param)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
                                             angle::EntryPoint entryPoint,
                                             SamplerID sampler,
                                             GLenum pname,
                                             GLsizei bufSize,
                                             const GLuint *param)
{
    UNIMPLEMENTED();
    return false;
}

bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          GLuint index,
                                          GLenum pname,
                                          GLsizei bufSize,
                                          const GLsizei *length,
                                          const GLfloat *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);
    return true;
}

bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          GLuint index,
                                          GLenum pname,
                                          GLsizei bufSize,
                                          const GLsizei *length,
                                          const GLint *params)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
                                                angle::EntryPoint entryPoint,
                                                GLuint index,
                                                GLenum pname,
                                                GLsizei bufSize,
                                                const GLsizei *length,
                                                void *const *pointer)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
                                           angle::EntryPoint entryPoint,
                                           GLuint index,
                                           GLenum pname,
                                           GLsizei bufSize,
                                           const GLsizei *length,
                                           const GLint *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            GLuint index,
                                            GLenum pname,
                                            GLsizei bufSize,
                                            const GLsizei *length,
                                            const GLuint *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
                                                angle::EntryPoint entryPoint,
                                                ShaderProgramID program,
                                                UniformBlockIndex uniformBlockIndex,
                                                GLenum pname,
                                                GLsizei bufSize,
                                                const GLsizei *length,
                                                const GLint *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei writeLength = 0;

    if (!ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex, pname,
                                             &writeLength))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
    {
        return false;
    }

    SetRobustLengthParam(length, writeLength);

    return true;
}

bool ValidateGetInternalformativRobustANGLE(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            GLenum target,
                                            GLenum internalformat,
                                            GLenum pname,
                                            GLsizei bufSize,
                                            const GLsizei *length,
                                            const GLint *params)
{
    if (context->getClientVersion() < ES_3_0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kES3Required);
        return false;
    }

    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    {
        return false;
    }

    GLsizei numParams = 0;

    if (!ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
                                         bufSize, &numParams))
    {
        return false;
    }

    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    {
        return false;
    }

    SetRobustLengthParam(length, numParams);

    return true;
}

bool ValidateRobustCompressedTexImageBase(const Context *context,
                                          angle::EntryPoint entryPoint,
                                          GLsizei imageSize,
                                          GLsizei dataSize)
{
    if (!ValidateRobustEntryPoint(context, entryPoint, dataSize))
    {
        return false;
    }

    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
    if (pixelUnpackBuffer == nullptr)
    {
        if (dataSize < imageSize)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
            return false;
        }
    }
    return true;
}

bool ValidateGetBufferParameterBase(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    BufferBinding target,
                                    GLenum pname,
                                    bool pointerVersion,
                                    GLsizei *numParams)
{
    if (numParams)
    {
        *numParams = 0;
    }

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

    const Buffer *buffer = context->getState().getTargetBuffer(target);
    if (!buffer)
    {
        // A null buffer means that "0" is bound to the requested buffer target
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferNotBound);
        return false;
    }

    const Extensions &extensions = context->getExtensions();

    switch (pname)
    {
        case GL_BUFFER_USAGE:
        case GL_BUFFER_SIZE:
            break;

        case GL_BUFFER_ACCESS_OES:
            if (!extensions.mapbufferOES)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_BUFFER_MAPPED:
            static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
            if (context->getClientVersion() < ES_3_0 && !extensions.mapbufferOES &&
                !extensions.mapBufferRangeEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_BUFFER_MAP_POINTER:
            if (!pointerVersion)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMapPointerQuery);
                return false;
            }
            break;

        case GL_BUFFER_ACCESS_FLAGS:
        case GL_BUFFER_MAP_OFFSET:
        case GL_BUFFER_MAP_LENGTH:
            if (context->getClientVersion() < ES_3_0 && !extensions.mapBufferRangeEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_MEMORY_SIZE_ANGLE:
            if (!extensions.memorySizeANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_RESOURCE_INITIALIZED_ANGLE:
            if (!extensions.robustResourceInitializationANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kRobustResourceInitializationExtensionRequired);
                return false;
            }
            break;
        case GL_BUFFER_IMMUTABLE_STORAGE_EXT:
        case GL_BUFFER_STORAGE_FLAGS_EXT:
            if (!extensions.bufferStorageEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    // All buffer parameter queries return one value.
    if (numParams)
    {
        *numParams = 1;
    }

    return true;
}

bool ValidateGetRenderbufferParameterivBase(const Context *context,
                                            angle::EntryPoint entryPoint,
                                            GLenum target,
                                            GLenum pname,
                                            GLsizei *length)
{
    if (length)
    {
        *length = 0;
    }

    if (target != GL_RENDERBUFFER)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidRenderbufferTarget);
        return false;
    }

    Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
    if (renderbuffer == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kRenderbufferNotBound);
        return false;
    }

    switch (pname)
    {
        case GL_RENDERBUFFER_WIDTH:
        case GL_RENDERBUFFER_HEIGHT:
        case GL_RENDERBUFFER_INTERNAL_FORMAT:
        case GL_RENDERBUFFER_RED_SIZE:
        case GL_RENDERBUFFER_GREEN_SIZE:
        case GL_RENDERBUFFER_BLUE_SIZE:
        case GL_RENDERBUFFER_ALPHA_SIZE:
        case GL_RENDERBUFFER_DEPTH_SIZE:
        case GL_RENDERBUFFER_STENCIL_SIZE:
            break;

        case GL_RENDERBUFFER_SAMPLES_ANGLE:
            if (context->getClientVersion() < ES_3_0 &&
                !context->getExtensions().framebufferMultisampleANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_MEMORY_SIZE_ANGLE:
            if (!context->getExtensions().memorySizeANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
            if (!context->getExtensions().getImageANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
                return false;
            }
            break;

        case GL_RESOURCE_INITIALIZED_ANGLE:
            if (!context->getExtensions().robustResourceInitializationANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kRobustResourceInitializationExtensionRequired);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    if (length)
    {
        *length = 1;
    }
    return true;
}

bool ValidateGetShaderivBase(const Context *context,
                             angle::EntryPoint entryPoint,
                             ShaderProgramID shader,
                             GLenum pname,
                             GLsizei *length)
{
    if (length)
    {
        *length = 0;
    }

    if (context->isContextLost())
    {
        if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
        {
            // The context needs to return a value in this case.
            // It will also generate a CONTEXT_LOST error.
            return true;
        }
        else
        {
            ANGLE_VALIDATION_ERROR(GL_CONTEXT_LOST, kContextLost);
            return false;
        }
    }

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

    switch (pname)
    {
        case GL_SHADER_TYPE:
        case GL_DELETE_STATUS:
        case GL_COMPILE_STATUS:
        case GL_INFO_LOG_LENGTH:
        case GL_SHADER_SOURCE_LENGTH:
            break;

        case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
            if (!context->getExtensions().translatedShaderSourceANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_COMPLETION_STATUS_KHR:
            if (!context->getExtensions().parallelShaderCompileKHR)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kExtensionNotEnabled);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    if (length)
    {
        *length = 1;
    }
    return true;
}

bool ValidateGetTexParameterBase(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 TextureType target,
                                 GLenum pname,
                                 GLsizei *length)
{
    if (length)
    {
        *length = 0;
    }

    if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
        target == TextureType::Buffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    if (context->getTextureByType(target) == nullptr)
    {
        // Should only be possible for external textures
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
        return false;
    }

    if (context->getClientVersion() < ES_2_0 && !IsValidGLES1TextureParameter(pname))
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
        return false;
    }

    switch (pname)
    {
        case GL_TEXTURE_MAG_FILTER:
        case GL_TEXTURE_MIN_FILTER:
        case GL_TEXTURE_WRAP_S:
        case GL_TEXTURE_WRAP_T:
            break;

        case GL_TEXTURE_USAGE_ANGLE:
            if (!context->getExtensions().textureUsageANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
            if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
            {
                return false;
            }
            break;

        case GL_TEXTURE_IMMUTABLE_FORMAT:
            if (context->getClientVersion() < ES_3_0 && !context->getExtensions().textureStorageEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_WRAP_R:
        case GL_TEXTURE_IMMUTABLE_LEVELS:
        case GL_TEXTURE_SWIZZLE_R:
        case GL_TEXTURE_SWIZZLE_G:
        case GL_TEXTURE_SWIZZLE_B:
        case GL_TEXTURE_SWIZZLE_A:
        case GL_TEXTURE_BASE_LEVEL:
        case GL_TEXTURE_MAX_LEVEL:
        case GL_TEXTURE_MIN_LOD:
        case GL_TEXTURE_MAX_LOD:
            if (context->getClientVersion() < ES_3_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES30);
                return false;
            }
            break;

        case GL_TEXTURE_COMPARE_MODE:
        case GL_TEXTURE_COMPARE_FUNC:
            if (context->getClientVersion() < ES_3_0 && !context->getExtensions().shadowSamplersEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_SRGB_DECODE_EXT:
            if (!context->getExtensions().textureSRGBDecodeEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_DEPTH_STENCIL_TEXTURE_MODE:
            if (context->getClientVersion() < ES_3_1 &&
                !context->getExtensions().stencilTexturingANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

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

        case GL_GENERATE_MIPMAP:
        case GL_TEXTURE_CROP_RECT_OES:
            // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
            // after GL_OES_draw_texture functionality implemented
            if (context->getClientVersion() >= ES_2_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
                return false;
            }
            break;

        case GL_MEMORY_SIZE_ANGLE:
            if (!context->getExtensions().memorySizeANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_BORDER_COLOR:
            if (!context->getExtensions().textureBorderClampAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_TEXTURE_NATIVE_ID_ANGLE:
            if (!context->getExtensions().textureExternalUpdateANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
            if (!context->getExtensions().getImageANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
                return false;
            }
            break;

        case GL_RESOURCE_INITIALIZED_ANGLE:
            if (!context->getExtensions().robustResourceInitializationANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kRobustResourceInitializationExtensionRequired);
                return false;
            }
            break;

        case GL_TEXTURE_PROTECTED_EXT:
            if (!context->getExtensions().protectedTexturesEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
                return false;
            }
            break;

        case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
            break;

        case GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM:
            if (!context->getExtensions().textureFoveatedQCOM)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
                return false;
            }
            break;

        case GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM:
            if (!context->getExtensions().textureFoveatedQCOM)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
                return false;
            }
            break;

        case GL_SURFACE_COMPRESSION_EXT:
            if (!context->getExtensions().textureStorageCompressionEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kTextureStorageCompressionExtensionRequired);
                return false;
            }
            break;
        case GL_TEXTURE_ASTC_DECODE_PRECISION_EXT:
            if (!context->getExtensions().textureCompressionAstcDecodeModeEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kTextureCompressionASTCDecodeModeExtensionRequired);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    if (length)
    {
        *length = GetTexParameterCount(pname);
    }
    return true;
}

bool ValidateGetVertexAttribBase(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 GLuint index,
                                 GLenum pname,
                                 GLsizei *length,
                                 bool pointer)
{
    if (length)
    {
        *length = 0;
    }

    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
        return false;
    }

    if (pointer)
    {
        if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
        {
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
        }
    }
    else
    {
        switch (pname)
        {
            case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
            case GL_VERTEX_ATTRIB_ARRAY_SIZE:
            case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
            case GL_VERTEX_ATTRIB_ARRAY_TYPE:
            case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
            case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
            case GL_CURRENT_VERTEX_ATTRIB:
                break;

            case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
                static_assert(
                    GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
                    "ANGLE extension enums not equal to GL enums.");
                if (context->getClientVersion() < ES_3_0 &&
                    !context->getExtensions().instancedArraysAny())
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                    return false;
                }
                break;

            case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
                if (context->getClientVersion() < ES_3_0)
                {
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                    return false;
                }
                break;

            case GL_VERTEX_ATTRIB_BINDING:
            case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
                if (context->getClientVersion() < ES_3_1)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumRequiresGLES31);
                    return false;
                }
                break;

            default:
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
        }
    }

    if (length)
    {
        if (pname == GL_CURRENT_VERTEX_ATTRIB)
        {
            *length = 4;
        }
        else
        {
            *length = 1;
        }
    }

    return true;
}

bool ValidatePixelPack(const Context *context,
                       angle::EntryPoint entryPoint,
                       GLenum format,
                       GLenum type,
                       GLint x,
                       GLint y,
                       GLsizei width,
                       GLsizei height,
                       GLsizei bufSize,
                       GLsizei *length,
                       const void *pixels)
{
    // Check for pixel pack buffer related API errors
    Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
    if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped() &&
        !pixelPackBuffer->isPersistentlyMapped())
    {
        // ...the buffer object's data store is currently mapped.
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferMapped);
        return false;
    }
    if (pixelPackBuffer != nullptr &&
        pixelPackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kPixelPackBufferBoundForTransformFeedback);
        return false;
    }

    // ..  the data would be packed to the buffer object such that the memory writes required
    // would exceed the data store size.
    const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
    const Extents size(width, height, 1);
    const auto &pack = context->getState().getPackState();

    GLuint endByte = 0;
    if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
        return false;
    }

    if (bufSize >= 0)
    {
        if (static_cast<size_t>(bufSize) < endByte)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
            return false;
        }
    }

    if (pixelPackBuffer != nullptr)
    {
        CheckedNumeric<size_t> checkedEndByte(endByte);
        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
        checkedEndByte += checkedOffset;

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

        const auto &typeInfo = GetTypeInfo(type);
        if (reinterpret_cast<uintptr_t>(pixels) % typeInfo.bytes != 0)
        {
            // data is not evenly divisible by the number of basic machine units needed
            // to store in memory the corresponding GL data type from table 8.4 for the
            // type parameter.
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBufferOffsetNotAligned);
            return false;
        }
    }

    if (pixelPackBuffer == nullptr && length != nullptr)
    {
        if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
            return false;
        }

        *length = static_cast<GLsizei>(endByte);
    }

    if (context->isWebGL())
    {
        // WebGL 2.0 disallows the scenario:
        //   GL_PACK_SKIP_PIXELS + width > DataStoreWidth
        // where:
        //   DataStoreWidth = (GL_PACK_ROW_LENGTH ? GL_PACK_ROW_LENGTH : width)
        // Since these two pack parameters can only be set to non-zero values
        // on WebGL 2.0 contexts, verify them for all WebGL contexts.
        GLint dataStoreWidth = pack.rowLength ? pack.rowLength : width;
        if (pack.skipPixels + width > dataStoreWidth)
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidPackParametersForWebGL);
            return false;
        }
    }

    return true;
}

bool ValidateReadPixelsBase(const Context *context,
                            angle::EntryPoint entryPoint,
                            GLint x,
                            GLint y,
                            GLsizei width,
                            GLsizei height,
                            GLenum format,
                            GLenum type,
                            GLsizei bufSize,
                            GLsizei *length,
                            GLsizei *columns,
                            GLsizei *rows,
                            const void *pixels)
{
    ASSERT((length == nullptr && columns == nullptr && rows == nullptr) ||
           (length != nullptr && columns != nullptr && rows != nullptr));
    const bool isRobust = (length != nullptr);

    if (isRobust)
    {
        *length  = 0;
        *rows    = 0;
        *columns = 0;
    }

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

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

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

    // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
    // resolved before reading.
    if (!readFramebuffer->isDefault() &&
        !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
    {
        return false;
    }

    if (readFramebuffer->getReadBufferState() == GL_NONE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kReadBufferNone);
        return false;
    }

    const FramebufferAttachment *readBuffer = nullptr;
    switch (format)
    {
        case GL_DEPTH_COMPONENT:
            readBuffer = readFramebuffer->getDepthAttachment();
            break;
        case GL_STENCIL_INDEX_OES:
        case GL_DEPTH_STENCIL_OES:
            readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
            break;
        default:
            readBuffer = readFramebuffer->getReadColorAttachment();
            break;
    }

    // OVR_multiview, Revision 1:
    // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
    // the number of views in the current read framebuffer is more than one.
    if (readFramebuffer->readDisallowedByMultiview())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION, kMultiviewReadFramebuffer);
        return false;
    }

    if (context->isWebGL())
    {
        // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
        // excluding formats LUMINANCE and LUMINANCE_ALPHA.".  This requires validating the format
        // and type before validating the combination of format and type.  However, the
        // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
        // verifies that GL_INVALID_OPERATION is generated.
        // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
        // dEQP/WebGL.
        if (!ValidReadPixelsFormatEnum(context, format))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidFormat);
            return false;
        }

        if (!ValidReadPixelsTypeEnum(context, type))
        {
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidType);
            return false;
        }
    }

    // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
    // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
    // attachment and WebGL defines it to be an error. We do the check unconditionally as the
    // situation is an application error that would lead to a crash in ANGLE.
    if (readBuffer == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMissingReadAttachment);
        return false;
    }

    GLenum currentFormat = GL_NONE;
    GLenum currentType   = GL_NONE;

    switch (format)
    {
        case GL_DEPTH_COMPONENT:
        case GL_STENCIL_INDEX_OES:
        case GL_DEPTH_STENCIL_OES:
            // Only rely on ValidReadPixelsFormatType for depth/stencil formats
            break;
        default:
            currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
            currentType   = readFramebuffer->getImplementationColorReadType(context);
            break;
    }

    bool validFormatTypeCombination =
        ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);

    if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
        return false;
    }

    if (!ValidatePixelPack(context, entryPoint, format, type, x, y, width, height, bufSize, length,
                           pixels))
    {
        return false;
    }

    auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
        ASSERT(length >= 0);
        ASSERT(bufferSize >= 0);

        angle::CheckedNumeric<int> readExtent = start;
        readExtent += length;
        if (!readExtent.IsValid())
        {
            return false;
        }

        if (outExtent == nullptr)
        {
            // Only perform integer overflow validation when robust read is not used.
            return true;
        }

        int clippedExtent = length;
        if (start < 0)
        {
            // "subtract" the area that is less than 0
            // Can't cause the overflow since |length| can't be negative.
            clippedExtent += start;
        }

        const int readExtentValue = readExtent.ValueOrDie();
        if (readExtentValue > bufferSize)
        {
            ASSERT(readExtentValue > 0);
            ASSERT((start <= 0 && clippedExtent == readExtentValue) ||
                   (start > 0 && clippedExtent == length && readExtentValue == start + length));
            // Subtract the region to the right of the read buffer
            clippedExtent -= (readExtentValue - bufferSize);
            // Integer overflow is not possible.
            ASSERT((start <= 0 && clippedExtent == bufferSize) ||
                   (start > 0 && clippedExtent >= -start));
        }

        *outExtent = std::max<int>(clippedExtent, 0);
        return true;
    };

    Extents readBufferSize;
    if (isRobust)
    {
        // Only get size when robust read is used, since buffer size does not affect the integer
        // overflow validation part of getClippedExtent() lambda.
        if (readBuffer->ensureSizeResolved(context) == angle::Result::Stop)
        {
            // Context error must be generated by the failed call itself.
            return false;
        }
        readBufferSize = readBuffer->getSize();
    }

    if (!getClippedExtent(x, width, readBufferSize.width, columns))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
        return false;
    }

    if (!getClippedExtent(y, height, readBufferSize.height, rows))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
        return false;
    }

    return true;
}

template <typename ParamType>
bool ValidateTexParameterBase(const Context *context,
                              angle::EntryPoint entryPoint,
                              TextureType target,
                              GLenum pname,
                              GLsizei bufSize,
                              bool vectorParams,
                              const ParamType *params)
{
    if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
        target == TextureType::Buffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    Texture *texture = context->getTextureByType(target);
    if (texture == nullptr)
    {
        // Should only be possible for external textures
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureNotBound);
        return false;
    }

    if (context->getState().isTextureBoundToActivePLS(texture->id()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture);
        return false;
    }

    const GLsizei minBufSize = GetTexParameterCount(pname);
    if (bufSize >= 0 && bufSize < minBufSize)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
        return false;
    }

    if (context->getClientVersion() < ES_2_0 && !IsValidGLES1TextureParameter(pname))
    {
        ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
        return false;
    }

    switch (pname)
    {
        case GL_TEXTURE_WRAP_R:
        case GL_TEXTURE_SWIZZLE_R:
        case GL_TEXTURE_SWIZZLE_G:
        case GL_TEXTURE_SWIZZLE_B:
        case GL_TEXTURE_SWIZZLE_A:
        case GL_TEXTURE_BASE_LEVEL:
        case GL_TEXTURE_MAX_LEVEL:
        case GL_TEXTURE_COMPARE_MODE:
        case GL_TEXTURE_COMPARE_FUNC:
        case GL_TEXTURE_MIN_LOD:
        case GL_TEXTURE_MAX_LOD:
            if (context->getClientVersion() < ES_3_0 &&
                !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kES3Required);
                return false;
            }
            if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_GENERATE_MIPMAP:
        case GL_TEXTURE_CROP_RECT_OES:
            if (context->getClientVersion() >= ES_2_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
                return false;
            }
            break;

        default:
            break;
    }

    if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
    {
        switch (pname)
        {
            case GL_TEXTURE_MIN_FILTER:
            case GL_TEXTURE_MAG_FILTER:
            case GL_TEXTURE_WRAP_S:
            case GL_TEXTURE_WRAP_T:
            case GL_TEXTURE_WRAP_R:
            case GL_TEXTURE_MIN_LOD:
            case GL_TEXTURE_MAX_LOD:
            case GL_TEXTURE_COMPARE_MODE:
            case GL_TEXTURE_COMPARE_FUNC:
            case GL_TEXTURE_BORDER_COLOR:
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
                return false;
        }
    }

    switch (pname)
    {
        case GL_TEXTURE_WRAP_S:
        case GL_TEXTURE_WRAP_T:
        case GL_TEXTURE_WRAP_R:
        {
            bool restrictedWrapModes = ((target == TextureType::External &&
                                         !context->getExtensions().EGLImageExternalWrapModesEXT) ||
                                        target == TextureType::Rectangle);
            if (!ValidateTextureWrapModeValue(context, entryPoint, params, restrictedWrapModes))
            {
                return false;
            }
        }
        break;

        case GL_TEXTURE_MIN_FILTER:
        {
            bool restrictedMinFilter =
                target == TextureType::External || target == TextureType::Rectangle;
            if (!ValidateTextureMinFilterValue(context, entryPoint, params, restrictedMinFilter))
            {
                return false;
            }
        }
        break;

        case GL_TEXTURE_MAG_FILTER:
            if (!ValidateTextureMagFilterValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_USAGE_ANGLE:
            if (!context->getExtensions().textureUsageANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }

            switch (ConvertToGLenum(params[0]))
            {
                case GL_NONE:
                case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
                    break;

                default:
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                    return false;
            }
            break;

        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
        {
            GLfloat paramValue = static_cast<GLfloat>(params[0]);
            if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
            {
                return false;
            }
            ASSERT(static_cast<ParamType>(paramValue) == params[0]);
        }
        break;

        case GL_TEXTURE_MIN_LOD:
        case GL_TEXTURE_MAX_LOD:
            // any value is permissible
            break;

        case GL_TEXTURE_COMPARE_MODE:
            if (!ValidateTextureCompareModeValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_COMPARE_FUNC:
            if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_SWIZZLE_R:
        case GL_TEXTURE_SWIZZLE_G:
        case GL_TEXTURE_SWIZZLE_B:
        case GL_TEXTURE_SWIZZLE_A:
            switch (ConvertToGLenum(params[0]))
            {
                case GL_RED:
                case GL_GREEN:
                case GL_BLUE:
                case GL_ALPHA:
                case GL_ZERO:
                case GL_ONE:
                    break;

                default:
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                    return false;
            }
            break;

        case GL_TEXTURE_BASE_LEVEL:
            if (ConvertToGLint(params[0]) < 0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kBaseLevelNegative);
                return false;
            }
            if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
                return false;
            }
            if ((target == TextureType::_2DMultisample ||
                 target == TextureType::_2DMultisampleArray) &&
                static_cast<GLuint>(params[0]) != 0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
                return false;
            }
            if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kBaseLevelNonZero);
                return false;
            }
            break;

        case GL_TEXTURE_MAX_LEVEL:
            if (ConvertToGLint(params[0]) < 0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
                return false;
            }
            break;

        case GL_DEPTH_STENCIL_TEXTURE_MODE:
            if (context->getClientVersion() < ES_3_1 &&
                !context->getExtensions().stencilTexturingANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            switch (ConvertToGLenum(params[0]))
            {
                case GL_DEPTH_COMPONENT:
                case GL_STENCIL_INDEX:
                    break;

                default:
                    ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                    return false;
            }
            break;

        case GL_TEXTURE_SRGB_DECODE_EXT:
            if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
            if (!ValidateTextureSRGBOverrideValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_GENERATE_MIPMAP:
            if (context->getClientVersion() >= ES_2_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
                return false;
            }
            break;

        case GL_TEXTURE_CROP_RECT_OES:
            if (context->getClientVersion() >= ES_2_0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kGLES1Only);
                return false;
            }
            if (!vectorParams)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
                return false;
            }
            break;

        case GL_TEXTURE_BORDER_COLOR:
            if (!context->getExtensions().textureBorderClampAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            if (!vectorParams)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInsufficientBufferSize);
                return false;
            }
            break;

        case GL_RESOURCE_INITIALIZED_ANGLE:
            if (!context->getExtensions().robustResourceInitializationANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kRobustResourceInitializationExtensionRequired);
                return false;
            }
            break;

        case GL_TEXTURE_PROTECTED_EXT:
            if (!context->getExtensions().protectedTexturesEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kProtectedTexturesExtensionRequired);
                return false;
            }
            if (ConvertToBool(params[0]) != context->getState().hasProtectedContent())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION,
                                       "Protected Texture must match Protected Context");
                return false;
            }
            break;

        case GL_RENDERABILITY_VALIDATION_ANGLE:
            if (!context->getExtensions().renderabilityValidationANGLE)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_TILING_EXT:
            if (!context->getExtensions().memoryObjectEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidMemoryObjectParameter);
                return false;
            }
            switch (ConvertToGLenum(params[0]))
            {
                case GL_OPTIMAL_TILING_EXT:
                case GL_LINEAR_TILING_EXT:
                    break;

                default:
                    ANGLE_VALIDATION_ERROR(
                        GL_INVALID_OPERATION,
                        "Texture Tilling Mode must be OPTIMAL_TILING_EXT or LINEAR_TILING_EXT");
                    return false;
            }
            break;

        case GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM:
            if (!context->getExtensions().textureFoveatedQCOM)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
                return false;
            }
            {
                const GLuint features               = static_cast<GLuint>(params[0]);
                constexpr GLuint kSupportedFeatures = GL_FOVEATION_ENABLE_BIT_QCOM;
                if (features != (features & kSupportedFeatures))
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureInvalidParameters);
                    return false;
                }
                if ((context->getTextureByType(target)->getFoveatedFeatureBits() &
                     GL_FOVEATION_ENABLE_BIT_QCOM) &&
                    (features & GL_FOVEATION_ENABLE_BIT_QCOM) == 0)
                {
                    ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFoveatedTextureCannotDisable);
                    return false;
                }
            }
            break;

        case GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM:
            if (!context->getExtensions().textureFoveatedQCOM)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFoveatedTextureQcomExtensionRequired);
                return false;
            }
            if (static_cast<GLfloat>(params[0]) < 0.0 || static_cast<GLfloat>(params[0]) > 1.0)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kFoveatedTextureInvalidPixelDensity);
                return false;
            }
            break;

        case GL_TEXTURE_ASTC_DECODE_PRECISION_EXT:
            if (!context->getExtensions().textureCompressionAstcDecodeModeEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kTextureCompressionASTCDecodeModeExtensionRequired);
                return false;
            }
            switch (ConvertToGLenum(params[0]))
            {
                case GL_RGBA16F:
                case GL_RGBA8:
                    break;
                case GL_RGB9_E5:
                    if (!context->getExtensions().textureCompressionAstcDecodeModeRgb9e5EXT)
                    {
                        ANGLE_VALIDATION_ERROR(
                            GL_INVALID_ENUM,
                            kTextureCompressionASTCDecodeModeRGB9E5ExtensionRequired);
                        return false;
                    }
                    break;

                default:
                    ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumInvalid);
                    return false;
            }
            break;
        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    return true;
}

template bool ValidateTexParameterBase(const Context *,
                                       angle::EntryPoint,
                                       TextureType,
                                       GLenum,
                                       GLsizei,
                                       bool,
                                       const GLfloat *);
template bool ValidateTexParameterBase(const Context *,
                                       angle::EntryPoint,
                                       TextureType,
                                       GLenum,
                                       GLsizei,
                                       bool,
                                       const GLint *);
template bool ValidateTexParameterBase(const Context *,
                                       angle::EntryPoint,
                                       TextureType,
                                       GLenum,
                                       GLsizei,
                                       bool,
                                       const GLuint *);

bool ValidateGetActiveUniformBlockivBase(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         ShaderProgramID program,
                                         UniformBlockIndex uniformBlockIndex,
                                         GLenum pname,
                                         GLsizei *length)
{
    if (length)
    {
        *length = 0;
    }

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

    const ProgramExecutable &executable = programObject->getExecutable();
    if (uniformBlockIndex.value >= executable.getUniformBlocks().size())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsActiveUniformBlockCount);
        return false;
    }

    switch (pname)
    {
        case GL_UNIFORM_BLOCK_BINDING:
        case GL_UNIFORM_BLOCK_DATA_SIZE:
        case GL_UNIFORM_BLOCK_NAME_LENGTH:
        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    if (length)
    {
        if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
        {
            const InterfaceBlock &uniformBlock =
                executable.getUniformBlockByIndex(uniformBlockIndex.value);
            *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
        }
        else
        {
            *length = 1;
        }
    }

    return true;
}

template <typename ParamType>
bool ValidateSamplerParameterBase(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  SamplerID sampler,
                                  GLenum pname,
                                  GLsizei bufSize,
                                  bool vectorParams,
                                  const ParamType *params)
{
    if (!context->isSampler(sampler))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
        return false;
    }

    if (params == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL);
        return false;
    }

    const GLsizei minBufSize = GetSamplerParameterCount(pname);
    if (bufSize >= 0 && bufSize < minBufSize)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientBufferSize);
        return false;
    }

    switch (pname)
    {
        case GL_TEXTURE_WRAP_S:
        case GL_TEXTURE_WRAP_T:
        case GL_TEXTURE_WRAP_R:
            if (!ValidateTextureWrapModeValue(context, entryPoint, params, false))
            {
                return false;
            }
            break;

        case GL_TEXTURE_MIN_FILTER:
            if (!ValidateTextureMinFilterValue(context, entryPoint, params, false))
            {
                return false;
            }
            break;

        case GL_TEXTURE_MAG_FILTER:
            if (!ValidateTextureMagFilterValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_MIN_LOD:
        case GL_TEXTURE_MAX_LOD:
            // any value is permissible
            break;

        case GL_TEXTURE_COMPARE_MODE:
            if (!ValidateTextureCompareModeValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_COMPARE_FUNC:
            if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_SRGB_DECODE_EXT:
            if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
            {
                return false;
            }
            break;

        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
        {
            GLfloat paramValue = static_cast<GLfloat>(params[0]);
            if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
            {
                return false;
            }
        }
        break;

        case GL_TEXTURE_BORDER_COLOR:
            if (!context->getExtensions().textureBorderClampAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            if (!vectorParams)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInsufficientBufferSize);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    return true;
}

template bool ValidateSamplerParameterBase(const Context *,
                                           angle::EntryPoint,
                                           SamplerID,
                                           GLenum,
                                           GLsizei,
                                           bool,
                                           const GLfloat *);
template bool ValidateSamplerParameterBase(const Context *,
                                           angle::EntryPoint,
                                           SamplerID,
                                           GLenum,
                                           GLsizei,
                                           bool,
                                           const GLint *);
template bool ValidateSamplerParameterBase(const Context *,
                                           angle::EntryPoint,
                                           SamplerID,
                                           GLenum,
                                           GLsizei,
                                           bool,
                                           const GLuint *);

template <typename ParamType>
bool ValidateGetSamplerParameterBase(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     SamplerID sampler,
                                     GLenum pname,
                                     GLsizei *length,
                                     const ParamType *params)
{
    if (length)
    {
        *length = 0;
    }

    if (!context->isSampler(sampler))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidSampler);
        return false;
    }

    switch (pname)
    {
        case GL_TEXTURE_WRAP_S:
        case GL_TEXTURE_WRAP_T:
        case GL_TEXTURE_WRAP_R:
        case GL_TEXTURE_MIN_FILTER:
        case GL_TEXTURE_MAG_FILTER:
        case GL_TEXTURE_MIN_LOD:
        case GL_TEXTURE_MAX_LOD:
        case GL_TEXTURE_COMPARE_MODE:
        case GL_TEXTURE_COMPARE_FUNC:
            break;

        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
            if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
            {
                return false;
            }
            break;

        case GL_TEXTURE_SRGB_DECODE_EXT:
            if (!context->getExtensions().textureSRGBDecodeEXT)
            {
                ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
                return false;
            }
            break;

        case GL_TEXTURE_BORDER_COLOR:
            if (!context->getExtensions().textureBorderClampAny() &&
                context->getClientVersion() < ES_3_2)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kExtensionNotEnabled);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    if (length)
    {
        *length = GetSamplerParameterCount(pname);
    }

    if (params == nullptr)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kPLSParamsNULL);
        return false;
    }

    return true;
}

template bool ValidateGetSamplerParameterBase(const Context *,
                                              angle::EntryPoint,
                                              SamplerID,
                                              GLenum,
                                              GLsizei *,
                                              const GLfloat *);
template bool ValidateGetSamplerParameterBase(const Context *,
                                              angle::EntryPoint,
                                              SamplerID,
                                              GLenum,
                                              GLsizei *,
                                              const GLint *);
template bool ValidateGetSamplerParameterBase(const Context *,
                                              angle::EntryPoint,
                                              SamplerID,
                                              GLenum,
                                              GLsizei *,
                                              const GLuint *);

bool ValidateGetInternalFormativBase(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     GLenum target,
                                     GLenum internalformat,
                                     GLenum pname,
                                     GLsizei bufSize,
                                     GLsizei *numParams)
{
    if (numParams)
    {
        *numParams = 0;
    }

    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
    if (!formatCaps.renderbuffer)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kFormatNotRenderable);
        return false;
    }

    switch (target)
    {
        case GL_RENDERBUFFER:
            break;

        case GL_TEXTURE_2D_MULTISAMPLE:
            if (context->getClientVersion() < ES_3_1 &&
                !context->getExtensions().textureMultisampleANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
                return false;
            }
            break;
        case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
            if (context->getClientVersion() < ES_3_2 &&
                !context->getExtensions().textureStorageMultisample2dArrayOES)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleArrayExtensionOrES32Required);
                return false;
            }
            break;
        case GL_TEXTURE_2D:
        case GL_TEXTURE_CUBE_MAP:
        case GL_TEXTURE_3D:
        case GL_TEXTURE_2D_ARRAY:
            if (pname != GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT &&
                pname != GL_SURFACE_COMPRESSION_EXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
                return false;
            }
            if (!context->getExtensions().textureStorageCompressionEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kTextureStorageCompressionExtensionRequired);
                return false;
            }
            break;
        default:
            ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
            return false;
    }

    if (bufSize < 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInsufficientBufferSize);
        return false;
    }

    GLsizei maxWriteParams = 0;
    switch (pname)
    {
        case GL_NUM_SAMPLE_COUNTS:
            maxWriteParams = 1;
            break;

        case GL_SAMPLES:
            maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
            break;

        case GL_NUM_SURFACE_COMPRESSION_FIXED_RATES_EXT:
        case GL_SURFACE_COMPRESSION_EXT:
            if (!context->getExtensions().textureStorageCompressionEXT)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kTextureStorageCompressionExtensionRequired);
                return false;
            }
            break;

        default:
            ANGLE_VALIDATION_ERRORF(GL_INVALID_ENUM, kEnumNotSupported, pname);
            return false;
    }

    if (numParams)
    {
        // glGetInternalFormativ will not overflow bufSize
        *numParams = std::min(bufSize, maxWriteParams);
    }

    return true;
}

bool ValidateFramebufferNotMultisampled(const Context *context,
                                        angle::EntryPoint entryPoint,
                                        const Framebuffer *framebuffer,
                                        bool checkReadBufferResourceSamples)
{
    int samples = checkReadBufferResourceSamples
                      ? framebuffer->getReadBufferResourceSamples(context)
                      : framebuffer->getSamples(context);
    if (samples != 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInvalidMultisampledFramebufferOperation);
        return false;
    }
    return true;
}

bool ValidateMultitextureUnit(const PrivateState &state,
                              ErrorSet *errors,
                              angle::EntryPoint entryPoint,
                              GLenum texture)
{
    if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + state.getCaps().maxMultitextureUnits)
    {
        errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMultitextureUnit);
        return false;
    }
    return true;
}

bool ValidateTexStorageMultisample(const Context *context,
                                   angle::EntryPoint entryPoint,
                                   TextureType target,
                                   GLsizei samples,
                                   GLint internalFormat,
                                   GLsizei width,
                                   GLsizei height)
{
    const Caps &caps = context->getCaps();
    if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
        return false;
    }

    if (samples == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kSamplesZero);
        return false;
    }

    const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
    if (!formatCaps.textureAttachment)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kRenderableInternalFormat);
        return false;
    }

    // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
    // is one of the unsized base internalformats listed in table 8.11.
    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
    if (formatInfo.internalFormat == GL_NONE)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
        return false;
    }

    if (static_cast<GLuint>(samples) > formatCaps.sampleCounts.getMaxSamples())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kSamplesOutOfRange);
        return false;
    }

    Texture *texture = context->getTextureByType(target);
    if (!texture || texture->id().value == 0)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kZeroBoundToTarget);
        return false;
    }

    if (texture->getImmutableFormat())
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kImmutableTextureBound);
        return false;
    }
    return true;
}

bool ValidateTexStorage2DMultisampleBase(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target,
                                         GLsizei samples,
                                         GLint internalFormat,
                                         GLsizei width,
                                         GLsizei height)
{
    if (target != TextureType::_2DMultisample)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
        return false;
    }

    if (width < 1 || height < 1)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
        return false;
    }

    return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalFormat,
                                         width, height);
}

bool ValidateTexStorage3DMultisampleBase(const Context *context,
                                         angle::EntryPoint entryPoint,
                                         TextureType target,
                                         GLsizei samples,
                                         GLenum internalformat,
                                         GLsizei width,
                                         GLsizei height,
                                         GLsizei depth)
{
    if (target != TextureType::_2DMultisampleArray)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTarget);
        return false;
    }

    if (width < 1 || height < 1 || depth < 1)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureSizeTooSmall);
        return false;
    }

    if (depth > context->getCaps().maxArrayTextureLayers)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kTextureDepthOutOfRange);
        return false;
    }

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

bool ValidateGetTexLevelParameterBase(const Context *context,
                                      angle::EntryPoint entryPoint,
                                      TextureTarget target,
                                      GLint level,
                                      GLenum pname,
                                      GLsizei *length)
{

    if (length)
    {
        *length = 0;
    }

    TextureType type = TextureTargetToType(target);

    if (!ValidTexLevelDestinationTarget(context, type))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    // If type is valid, the texture object must exist
    ASSERT(context->getTextureByType(type) != nullptr);

    if (!ValidMipLevel(context, type, level))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kInvalidMipLevel);
        return false;
    }

    switch (pname)
    {
        case GL_TEXTURE_RED_TYPE:
        case GL_TEXTURE_GREEN_TYPE:
        case GL_TEXTURE_BLUE_TYPE:
        case GL_TEXTURE_ALPHA_TYPE:
        case GL_TEXTURE_DEPTH_TYPE:
        case GL_TEXTURE_RED_SIZE:
        case GL_TEXTURE_GREEN_SIZE:
        case GL_TEXTURE_BLUE_SIZE:
        case GL_TEXTURE_ALPHA_SIZE:
        case GL_TEXTURE_DEPTH_SIZE:
        case GL_TEXTURE_STENCIL_SIZE:
        case GL_TEXTURE_SHARED_SIZE:
        case GL_TEXTURE_INTERNAL_FORMAT:
        case GL_TEXTURE_WIDTH:
        case GL_TEXTURE_HEIGHT:
        case GL_TEXTURE_COMPRESSED:
            break;

        case GL_MEMORY_SIZE_ANGLE:
            if (!context->getExtensions().memorySizeANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumNotSupported);
                return false;
            }
            break;

        case GL_TEXTURE_DEPTH:
            if (context->getClientVersion() < ES_3_0 && !context->getExtensions().texture3DOES)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kEnumNotSupported);
                return false;
            }
            break;

        case GL_TEXTURE_SAMPLES:
        case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
            if (context->getClientVersion() < ES_3_1 &&
                !context->getExtensions().textureMultisampleANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kMultisampleTextureExtensionOrES31Required);
                return false;
            }
            break;

        case GL_RESOURCE_INITIALIZED_ANGLE:
            if (!context->getExtensions().robustResourceInitializationANGLE)
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM,
                                       kRobustResourceInitializationExtensionRequired);
                return false;
            }
            break;

        case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
        case GL_TEXTURE_BUFFER_OFFSET:
        case GL_TEXTURE_BUFFER_SIZE:
            if (context->getClientVersion() < Version(3, 2) &&
                !context->getExtensions().textureBufferAny())
            {
                ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kTextureBufferExtensionNotAvailable);
                return false;
            }
            break;

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

    if (length)
    {
        *length = 1;
    }
    return true;
}

bool ValidateGetMultisamplefvBase(const Context *context,
                                  angle::EntryPoint entryPoint,
                                  GLenum pname,
                                  GLuint index,
                                  const GLfloat *val)
{
    if (pname != GL_SAMPLE_POSITION)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidPname);
        return false;
    }

    Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
    GLint samples            = framebuffer->getSamples(context);

    if (index >= static_cast<GLuint>(samples))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_VALUE, kIndexExceedsSamples);
        return false;
    }

    return true;
}

bool ValidateSampleMaskiBase(const PrivateState &state,
                             ErrorSet *errors,
                             angle::EntryPoint entryPoint,
                             GLuint maskNumber,
                             GLbitfield mask)
{
    if (maskNumber >= static_cast<GLuint>(state.getCaps().maxSampleMaskWords))
    {
        errors->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
        return false;
    }

    return true;
}

void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint)
{
    // An overflow can happen when adding the offset. Check against a special constant.
    if (context->getNonInstancedVertexElementLimit() == VertexAttribute::kIntegerOverflow ||
        context->getInstancedVertexElementLimit() == VertexAttribute::kIntegerOverflow)
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kIntegerOverflow);
    }
    else
    {
        // [OpenGL ES 3.0.2] section 2.9.4 page 40:
        // We can return INVALID_OPERATION if our buffer does not have enough backing data.
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
    }
}

bool ValidateLoseContextCHROMIUM(const Context *context,
                                 angle::EntryPoint entryPoint,
                                 GraphicsResetStatus current,
                                 GraphicsResetStatus other)
{
    switch (current)
    {
        case GraphicsResetStatus::GuiltyContextReset:
        case GraphicsResetStatus::InnocentContextReset:
        case GraphicsResetStatus::UnknownContextReset:
            break;

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

    switch (other)
    {
        case GraphicsResetStatus::GuiltyContextReset:
        case GraphicsResetStatus::InnocentContextReset:
        case GraphicsResetStatus::UnknownContextReset:
            break;

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

    return true;
}

bool ValidateTexImage2DExternalANGLE(const Context *context,
                                     angle::EntryPoint entryPoint,
                                     TextureTarget target,
                                     GLint level,
                                     GLint internalformat,
                                     GLsizei width,
                                     GLsizei height,
                                     GLint border,
                                     GLenum format,
                                     GLenum type)
{
    if (!ValidTexture2DDestinationTarget(context, target) &&
        !ValidTextureExternalTarget(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    if (context->getClientVersion() < ES_3_0)
    {
        if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
                                               false, false, 0, 0, width, height, border, format,
                                               type, -1, nullptr))
        {
            return false;
        }
    }
    else
    {
        if (!ValidateES3TexImageParametersBase(context, entryPoint, target, level, internalformat,
                                               false, false, 0, 0, 0, width, height, 1, border,
                                               format, type, -1, nullptr))
        {
            return false;
        }
    }

    return true;
}

bool ValidateInvalidateTextureANGLE(const Context *context,
                                    angle::EntryPoint entryPoint,
                                    TextureType target)
{
    if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_ENUM, kInvalidTextureTarget);
        return false;
    }

    Texture *texture = context->getTextureByType(target);
    if (texture != nullptr && context->getState().isTextureBoundToActivePLS(texture->id()))
    {
        ANGLE_VALIDATION_ERROR(GL_INVALID_OPERATION, kActivePLSBackingTexture);
        return false;
    }

    return true;
}

bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
                                                const ProgramExecutable *programExecutable)
{
    size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
    const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
    for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
    {
        const OffsetBindingPointer<Buffer> &buffer =
            transformFeedback->getIndexedBuffer(programXfbIndex);
        if (!buffer.get())
        {
            return false;
        }
    }

    return true;
}

bool ValidateLogicOpCommon(const PrivateState &state,
                           ErrorSet *errors,
                           angle::EntryPoint entryPoint,
                           LogicalOperation opcodePacked)
{
    switch (opcodePacked)
    {
        case LogicalOperation::And:
        case LogicalOperation::AndInverted:
        case LogicalOperation::AndReverse:
        case LogicalOperation::Clear:
        case LogicalOperation::Copy:
        case LogicalOperation::CopyInverted:
        case LogicalOperation::Equiv:
        case LogicalOperation::Invert:
        case LogicalOperation::Nand:
        case LogicalOperation::Noop:
        case LogicalOperation::Nor:
        case LogicalOperation::Or:
        case LogicalOperation::OrInverted:
        case LogicalOperation::OrReverse:
        case LogicalOperation::Set:
        case LogicalOperation::Xor:
            return true;
        default:
            errors->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLogicOp);
            return false;
    }
}
}  // namespace gl
