tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

validationES3.cpp (192481B)


      1 //
      2 // Copyright 2013 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters
      8 
      9 #include "libANGLE/validationES3_autogen.h"
     10 
     11 #include "anglebase/numerics/safe_conversions.h"
     12 #include "common/mathutil.h"
     13 #include "common/utilities.h"
     14 #include "libANGLE/Context.h"
     15 #include "libANGLE/ErrorStrings.h"
     16 #include "libANGLE/Framebuffer.h"
     17 #include "libANGLE/FramebufferAttachment.h"
     18 #include "libANGLE/PixelLocalStorage.h"
     19 #include "libANGLE/Renderbuffer.h"
     20 #include "libANGLE/Texture.h"
     21 #include "libANGLE/VertexArray.h"
     22 #include "libANGLE/formatutils.h"
     23 #include "libANGLE/validationES.h"
     24 
     25 using namespace angle;
     26 
     27 namespace gl
     28 {
     29 using namespace err;
     30 
     31 namespace
     32 {
     33 bool ValidateFramebufferTextureMultiviewBaseANGLE(const Context *context,
     34                                                  angle::EntryPoint entryPoint,
     35                                                  GLenum target,
     36                                                  GLenum attachment,
     37                                                  TextureID texture,
     38                                                  GLint level,
     39                                                  GLsizei numViews)
     40 {
     41    if (!(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
     42    {
     43        context->validationError(entryPoint, GL_INVALID_OPERATION, kMultiviewNotAvailable);
     44        return false;
     45    }
     46 
     47    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
     48    {
     49        return false;
     50    }
     51 
     52    if (texture.value != 0 && numViews < 1)
     53    {
     54        context->validationError(entryPoint, GL_INVALID_VALUE, kMultiviewViewsTooSmall);
     55        return false;
     56    }
     57 
     58    if (static_cast<GLuint>(numViews) > context->getCaps().maxViews)
     59    {
     60        context->validationError(entryPoint, GL_INVALID_VALUE, kMultiviewViewsTooLarge);
     61        return false;
     62    }
     63 
     64    return true;
     65 }
     66 
     67 bool ValidateFramebufferTextureMultiviewLevelAndFormat(const Context *context,
     68                                                       angle::EntryPoint entryPoint,
     69                                                       const Texture *texture,
     70                                                       GLint level)
     71 {
     72    TextureType type = texture->getType();
     73    if (!ValidMipLevel(context, type, level))
     74    {
     75        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
     76        return false;
     77    }
     78 
     79    const auto &format = texture->getFormat(NonCubeTextureTypeToTarget(type), level);
     80    if (format.info->compressed)
     81    {
     82        context->validationError(entryPoint, GL_INVALID_OPERATION,
     83                                 kCompressedTexturesNotAttachable);
     84        return false;
     85    }
     86    return true;
     87 }
     88 
     89 bool ValidateUniformES3(const Context *context,
     90                        angle::EntryPoint entryPoint,
     91                        GLenum uniformType,
     92                        UniformLocation location,
     93                        GLint count)
     94 {
     95    if (context->getClientMajorVersion() < 3)
     96    {
     97        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
     98        return false;
     99    }
    100 
    101    return ValidateUniform(context, entryPoint, uniformType, location, count);
    102 }
    103 
    104 bool ValidateUniformMatrixES3(const Context *context,
    105                              angle::EntryPoint entryPoint,
    106                              GLenum valueType,
    107                              UniformLocation location,
    108                              GLsizei count,
    109                              GLboolean transpose)
    110 {
    111    // Check for ES3 uniform entry points
    112    if (context->getClientMajorVersion() < 3)
    113    {
    114        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
    115        return false;
    116    }
    117 
    118    return ValidateUniformMatrix(context, entryPoint, valueType, location, count, transpose);
    119 }
    120 
    121 bool ValidateGenOrDeleteES3(const Context *context, angle::EntryPoint entryPoint, GLint n)
    122 {
    123    if (context->getClientMajorVersion() < 3)
    124    {
    125        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
    126        return false;
    127    }
    128    return ValidateGenOrDelete(context, entryPoint, n);
    129 }
    130 
    131 bool ValidateGenOrDeleteCountES3(const Context *context, angle::EntryPoint entryPoint, GLint count)
    132 {
    133    if (context->getClientMajorVersion() < 3)
    134    {
    135        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
    136        return false;
    137    }
    138    if (count < 0)
    139    {
    140        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
    141        return false;
    142    }
    143    return true;
    144 }
    145 
    146 bool ValidateCopyTexture3DCommon(const Context *context,
    147                                 angle::EntryPoint entryPoint,
    148                                 const Texture *source,
    149                                 GLint sourceLevel,
    150                                 GLint srcInternalFormat,
    151                                 const Texture *dest,
    152                                 GLint destLevel,
    153                                 GLint internalFormat,
    154                                 TextureTarget destTarget)
    155 {
    156    if (context->getClientMajorVersion() < 3)
    157    {
    158        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
    159        return false;
    160    }
    161 
    162    if (!context->getExtensions().copyTexture3dANGLE)
    163    {
    164        context->validationError(entryPoint, GL_INVALID_OPERATION, kANGLECopyTexture3DUnavailable);
    165        return false;
    166    }
    167 
    168    if (!ValidTexture3DTarget(context, source->getType()))
    169    {
    170        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    171        return false;
    172    }
    173 
    174    // Table 1.1 from the ANGLE_copy_texture_3d spec
    175    switch (GetUnsizedFormat(srcInternalFormat))
    176    {
    177        case GL_ALPHA:
    178        case GL_LUMINANCE:
    179        case GL_LUMINANCE_ALPHA:
    180        case GL_RED:
    181        case GL_RED_INTEGER:
    182        case GL_RG:
    183        case GL_RG_INTEGER:
    184        case GL_RGB:
    185        case GL_RGB_INTEGER:
    186        case GL_RGBA:
    187        case GL_RGBA_INTEGER:
    188        case GL_DEPTH_COMPONENT:
    189        case GL_DEPTH_STENCIL:
    190            break;
    191        default:
    192            context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
    193                                      srcInternalFormat);
    194            return false;
    195    }
    196 
    197    if (!ValidTexture3DTarget(context, TextureTargetToType(destTarget)))
    198    {
    199        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    200        return false;
    201    }
    202 
    203    // Table 1.0 from the ANGLE_copy_texture_3d spec
    204    switch (internalFormat)
    205    {
    206        case GL_RGB:
    207        case GL_RGBA:
    208        case GL_LUMINANCE:
    209        case GL_LUMINANCE_ALPHA:
    210        case GL_ALPHA:
    211        case GL_R8:
    212        case GL_R8_SNORM:
    213        case GL_R16F:
    214        case GL_R32F:
    215        case GL_R8UI:
    216        case GL_R8I:
    217        case GL_R16UI:
    218        case GL_R16I:
    219        case GL_R32UI:
    220        case GL_R32I:
    221        case GL_RG:
    222        case GL_RG8:
    223        case GL_RG8_SNORM:
    224        case GL_RG16F:
    225        case GL_RG32F:
    226        case GL_RG8UI:
    227        case GL_RG8I:
    228        case GL_RG16UI:
    229        case GL_RG16I:
    230        case GL_RG32UI:
    231        case GL_RG32I:
    232        case GL_RGB8:
    233        case GL_RGBX8_ANGLE:
    234        case GL_SRGB8:
    235        case GL_RGB565:
    236        case GL_RGB8_SNORM:
    237        case GL_R11F_G11F_B10F:
    238        case GL_RGB9_E5:
    239        case GL_RGB16F:
    240        case GL_RGB32F:
    241        case GL_RGB8UI:
    242        case GL_RGB8I:
    243        case GL_RGB16UI:
    244        case GL_RGB16I:
    245        case GL_RGB32UI:
    246        case GL_RGB32I:
    247        case GL_RGBA8:
    248        case GL_SRGB8_ALPHA8:
    249        case GL_RGBA8_SNORM:
    250        case GL_RGB5_A1:
    251        case GL_RGBA4:
    252        case GL_RGB10_A2:
    253        case GL_RGBA16F:
    254        case GL_RGBA32F:
    255        case GL_RGBA8UI:
    256        case GL_RGBA8I:
    257        case GL_RGB10_A2UI:
    258        case GL_RGBA16UI:
    259        case GL_RGBA16I:
    260        case GL_RGBA32I:
    261        case GL_RGBA32UI:
    262            break;
    263        default:
    264            context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
    265                                      internalFormat);
    266            return false;
    267    }
    268 
    269    return true;
    270 }
    271 }  // anonymous namespace
    272 
    273 static bool ValidateTexImageFormatCombination(const Context *context,
    274                                              angle::EntryPoint entryPoint,
    275                                              TextureType target,
    276                                              GLenum internalFormat,
    277                                              GLenum format,
    278                                              GLenum type)
    279 {
    280    // Different validation if on desktop api
    281    if (context->getClientType() == EGL_OPENGL_API)
    282    {
    283        // The type and format are valid if any supported internal format has that type and format
    284        if (!ValidDesktopFormat(format))
    285        {
    286            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
    287            return false;
    288        }
    289 
    290        if (!ValidDesktopType(type))
    291        {
    292            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
    293            return false;
    294        }
    295    }
    296    else
    297    {
    298        // The type and format are valid if any supported internal format has that type and format.
    299        // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
    300        if (gl::IsYuvFormat(format))
    301        {
    302            if (!context->getExtensions().yuvInternalFormatANGLE)
    303            {
    304                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
    305                return false;
    306            }
    307        }
    308        else
    309        {
    310            if (!ValidES3Format(format))
    311            {
    312                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
    313                return false;
    314            }
    315        }
    316 
    317        if (!ValidES3Type(type) || (type == GL_HALF_FLOAT_OES && context->isWebGL()))
    318        {
    319            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
    320            return false;
    321        }
    322    }
    323 
    324    // For historical reasons, glTexImage2D and glTexImage3D pass in their internal format as a
    325    // GLint instead of a GLenum. Therefor an invalid internal format gives a GL_INVALID_VALUE
    326    // error instead of a GL_INVALID_ENUM error. As this validation function is only called in
    327    // the validation codepaths for glTexImage2D/3D, we record a GL_INVALID_VALUE error.
    328    if (!ValidES3InternalFormat(internalFormat))
    329    {
    330        context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
    331                                  internalFormat);
    332        return false;
    333    }
    334 
    335    // From the ES 3.0 spec section 3.8.3:
    336    // Textures with a base internal format of DEPTH_COMPONENT or DEPTH_STENCIL are supported by
    337    // texture image specification commands only if target is TEXTURE_2D, TEXTURE_2D_ARRAY, or
    338    // TEXTURE_CUBE_MAP.Using these formats in conjunction with any other target will result in an
    339    // INVALID_OPERATION error.
    340    if (target == TextureType::_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL))
    341    {
    342        context->validationError(entryPoint, GL_INVALID_OPERATION, k3DDepthStencil);
    343        return false;
    344    }
    345 
    346    if (context->getClientType() == EGL_OPENGL_API)
    347    {
    348        // Check if this is a valid format combination to load texture data
    349        if (!ValidDesktopFormatCombination(format, type, internalFormat))
    350        {
    351            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination);
    352            return false;
    353        }
    354    }
    355    else
    356    {
    357        // Check if this is a valid format combination to load texture data
    358        // ANGLE_texture_external_yuv_sampling extension adds support for YUV formats
    359        if (gl::IsYuvFormat(format))
    360        {
    361            if (type != GL_UNSIGNED_BYTE)
    362            {
    363                context->validationError(entryPoint, GL_INVALID_OPERATION,
    364                                         kInvalidFormatCombination);
    365                return false;
    366            }
    367        }
    368        else
    369        {
    370            if (!ValidES3FormatCombination(format, type, internalFormat))
    371            {
    372                context->validationError(entryPoint, GL_INVALID_OPERATION,
    373                                         kInvalidFormatCombination);
    374                return false;
    375            }
    376        }
    377    }
    378 
    379    const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat, type);
    380    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
    381    {
    382        context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
    383                                  internalFormat);
    384        return false;
    385    }
    386 
    387    return true;
    388 }
    389 
    390 static bool ValidateES3CompressedFormatForTexture2DArray(const Context *context,
    391                                                         angle::EntryPoint entryPoint,
    392                                                         GLenum format)
    393 {
    394    if (IsETC1Format(format) || IsPVRTC1Format(format))
    395    {
    396        context->validationError(entryPoint, GL_INVALID_OPERATION,
    397                                 kInternalFormatRequiresTexture2D);
    398        return false;
    399    }
    400 
    401    return true;
    402 }
    403 
    404 static bool ValidateES3CompressedFormatForTexture3D(const Context *context,
    405                                                    angle::EntryPoint entryPoint,
    406                                                    GLenum format)
    407 {
    408    if (IsETC1Format(format) || IsPVRTC1Format(format))
    409    {
    410        context->validationError(entryPoint, GL_INVALID_OPERATION,
    411                                 kInternalFormatRequiresTexture2D);
    412        return false;
    413    }
    414 
    415    if (IsETC2EACFormat(format))
    416    {
    417        // ES 3.1, Section 8.7, page 169.
    418        context->validationError(entryPoint, GL_INVALID_OPERATION,
    419                                 kInternalFormatRequiresTexture2DArray);
    420        return false;
    421    }
    422 
    423    if (IsASTC2DFormat(format) && !(context->getExtensions().textureCompressionAstcHdrKHR ||
    424                                    context->getExtensions().textureCompressionAstcSliced3dKHR))
    425    {
    426        // GL_KHR_texture_compression_astc_hdr, TEXTURE_3D is not supported without HDR profile
    427        context->validationError(entryPoint, GL_INVALID_OPERATION,
    428                                 kInternalFormatRequiresTexture2DArrayASTC);
    429        return false;
    430    }
    431 
    432    if (IsS3TCFormat(format))
    433    {
    434        // GL_EXT_texture_compression_s3tc
    435        context->validationError(entryPoint, GL_INVALID_OPERATION,
    436                                 kInternalFormatRequiresTexture2DArrayS3TC);
    437        return false;
    438    }
    439 
    440    if (IsRGTCFormat(format))
    441    {
    442        // GL_EXT_texture_compression_rgtc
    443        context->validationError(entryPoint, GL_INVALID_OPERATION,
    444                                 kInternalFormatRequiresTexture2DArrayRGTC);
    445        return false;
    446    }
    447 
    448    if (IsBPTCFormat(format) && (context->getLimitations().noCompressedTexture3D))
    449    {
    450        // GL_EXT_texture_compression_bptc
    451        context->validationError(entryPoint, GL_INVALID_OPERATION,
    452                                 kInternalFormatRequiresTexture2DArrayBPTC);
    453        return false;
    454    }
    455 
    456    return true;
    457 }
    458 
    459 bool ValidateES3TexImageParametersBase(const Context *context,
    460                                       angle::EntryPoint entryPoint,
    461                                       TextureTarget target,
    462                                       GLint level,
    463                                       GLenum internalformat,
    464                                       bool isCompressed,
    465                                       bool isSubImage,
    466                                       GLint xoffset,
    467                                       GLint yoffset,
    468                                       GLint zoffset,
    469                                       GLsizei width,
    470                                       GLsizei height,
    471                                       GLsizei depth,
    472                                       GLint border,
    473                                       GLenum format,
    474                                       GLenum type,
    475                                       GLsizei imageSize,
    476                                       const void *pixels)
    477 {
    478    TextureType texType = TextureTargetToType(target);
    479 
    480    if (gl::IsYuvFormat(format))
    481    {
    482        // According to ANGLE_yuv_internal_format, the texture needs to be an immutable
    483        // texture, texture target can only be TEXTURE_2D and there is no mipmap support
    484        if (!context->getExtensions().yuvInternalFormatANGLE || !isSubImage)
    485        {
    486            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
    487            return false;
    488        }
    489 
    490        if (target != TextureTarget::_2D)
    491        {
    492            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    493            return false;
    494        }
    495 
    496        if (level != 0)
    497        {
    498            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
    499            return false;
    500        }
    501    }
    502 
    503    // Validate image size
    504    if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, depth,
    505                                  isSubImage))
    506    {
    507        // Error already processed.
    508        return false;
    509    }
    510 
    511    // Verify zero border
    512    if (border != 0)
    513    {
    514        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder);
    515        return false;
    516    }
    517 
    518    if (xoffset < 0 || yoffset < 0 || zoffset < 0)
    519    {
    520        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
    521        return false;
    522    }
    523 
    524    if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
    525        std::numeric_limits<GLsizei>::max() - yoffset < height ||
    526        std::numeric_limits<GLsizei>::max() - zoffset < depth)
    527    {
    528        context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
    529        return false;
    530    }
    531 
    532    const Caps &caps = context->getCaps();
    533 
    534    switch (texType)
    535    {
    536        case TextureType::_2D:
    537        case TextureType::External:
    538        case TextureType::VideoImage:
    539            if (width > (caps.max2DTextureSize >> level) ||
    540                height > (caps.max2DTextureSize >> level))
    541            {
    542                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    543                return false;
    544            }
    545            break;
    546 
    547        case TextureType::Rectangle:
    548            ASSERT(level == 0);
    549            if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
    550            {
    551                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    552                return false;
    553            }
    554            if (isCompressed)
    555            {
    556                context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
    557                return false;
    558            }
    559            break;
    560 
    561        case TextureType::CubeMap:
    562            if (!isSubImage && width != height)
    563            {
    564                context->validationError(entryPoint, GL_INVALID_VALUE,
    565                                         kCubemapFacesEqualDimensions);
    566                return false;
    567            }
    568 
    569            if (width > (caps.maxCubeMapTextureSize >> level))
    570            {
    571                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    572                return false;
    573            }
    574            break;
    575 
    576        case TextureType::_3D:
    577            if (width > (caps.max3DTextureSize >> level) ||
    578                height > (caps.max3DTextureSize >> level) ||
    579                depth > (caps.max3DTextureSize >> level))
    580            {
    581                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    582                return false;
    583            }
    584            break;
    585 
    586        case TextureType::_2DArray:
    587            if (width > (caps.max2DTextureSize >> level) ||
    588                height > (caps.max2DTextureSize >> level) || depth > caps.maxArrayTextureLayers)
    589            {
    590                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    591                return false;
    592            }
    593            break;
    594 
    595        case TextureType::CubeMapArray:
    596            if (!isSubImage && width != height)
    597            {
    598                context->validationError(entryPoint, GL_INVALID_VALUE,
    599                                         kCubemapFacesEqualDimensions);
    600                return false;
    601            }
    602 
    603            if (width > (caps.maxCubeMapTextureSize >> level))
    604            {
    605                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    606                return false;
    607            }
    608 
    609            if (width > (caps.max3DTextureSize >> level) ||
    610                height > (caps.max3DTextureSize >> level) ||
    611                depth > (caps.max3DTextureSize >> level))
    612            {
    613                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    614                return false;
    615            }
    616 
    617            if (!isSubImage && depth % 6 != 0)
    618            {
    619                context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapInvalidDepth);
    620                return false;
    621            }
    622            break;
    623 
    624        case TextureType::InvalidEnum:
    625            context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
    626            return false;
    627        default:
    628            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
    629                                      ToGLenum(texType));
    630            return false;
    631    }
    632 
    633    Texture *texture = context->getTextureByType(texType);
    634    if (!texture)
    635    {
    636        context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
    637        return false;
    638    }
    639 
    640    if (texture->getImmutableFormat() && !isSubImage)
    641    {
    642        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
    643        return false;
    644    }
    645 
    646    // Validate texture formats
    647    GLenum actualInternalFormat =
    648        isSubImage ? texture->getFormat(target, level).info->internalFormat : internalformat;
    649    if (isSubImage && actualInternalFormat == GL_NONE)
    650    {
    651        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevel);
    652        return false;
    653    }
    654 
    655    const InternalFormat &actualFormatInfo = isSubImage
    656                                                 ? *texture->getFormat(target, level).info
    657                                                 : GetInternalFormatInfo(internalformat, type);
    658    if (isCompressed)
    659    {
    660        // compressedTexSubImage does not generate GL_INVALID_ENUM when format is unknown or invalid
    661        if (!isSubImage)
    662        {
    663            if (!actualFormatInfo.compressed && !actualFormatInfo.paletted)
    664            {
    665                context->validationError(entryPoint, GL_INVALID_ENUM, kCompressedMismatch);
    666                return false;
    667            }
    668 
    669            if (!actualFormatInfo.textureSupport(context->getClientVersion(),
    670                                                 context->getExtensions()))
    671            {
    672                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
    673                return false;
    674            }
    675        }
    676 
    677        if (texType == TextureType::_2DArray)
    678        {
    679            GLenum compressedDataFormat = isSubImage ? format : internalformat;
    680            if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
    681                                                              compressedDataFormat))
    682            {
    683                // Error already generated.
    684                return false;
    685            }
    686        }
    687 
    688        if (texType == TextureType::_3D)
    689        {
    690            GLenum compressedDataFormat = isSubImage ? format : internalformat;
    691            if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint, compressedDataFormat))
    692            {
    693                // Error already generated.
    694                return false;
    695            }
    696        }
    697 
    698        if (isSubImage)
    699        {
    700            if (!ValidCompressedSubImageSize(
    701                    context, actualFormatInfo.internalFormat, xoffset, yoffset, zoffset, width,
    702                    height, depth, texture->getWidth(target, level),
    703                    texture->getHeight(target, level), texture->getDepth(target, level)))
    704            {
    705                context->validationError(entryPoint, GL_INVALID_OPERATION,
    706                                         kInvalidCompressedImageSize);
    707                return false;
    708            }
    709 
    710            if (format != actualInternalFormat)
    711            {
    712                context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedFormat);
    713                return false;
    714            }
    715 
    716            // GL_EXT_compressed_ETC1_RGB8_sub_texture allows this format
    717            if (IsETC1Format(actualInternalFormat) &&
    718                !context->getExtensions().compressedETC1RGB8SubTextureEXT)
    719            {
    720                context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
    721                                          internalformat);
    722                return false;
    723            }
    724        }
    725        else
    726        {
    727            if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height,
    728                                          depth))
    729            {
    730                context->validationError(entryPoint, GL_INVALID_OPERATION,
    731                                         kInvalidCompressedImageSize);
    732                return false;
    733            }
    734        }
    735 
    736        // Disallow 3D-only compressed formats from being set on 2D textures
    737        if (actualFormatInfo.compressedBlockDepth > 1 && texType != TextureType::_2DArray)
    738        {
    739            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget);
    740            return false;
    741        }
    742    }
    743    else
    744    {
    745        // Compressed formats are not valid internal formats for glTexImage*D
    746        if (!isSubImage)
    747        {
    748            const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(internalformat);
    749            if (internalFormatInfo.compressed)
    750            {
    751                context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
    752                                          internalformat);
    753                return false;
    754            }
    755        }
    756 
    757        if (!ValidateTexImageFormatCombination(context, entryPoint, texType, actualInternalFormat,
    758                                               format, type))
    759        {
    760            return false;
    761        }
    762    }
    763 
    764    // Validate sub image parameters
    765    if (isSubImage)
    766    {
    767        if (isCompressed != actualFormatInfo.compressed)
    768        {
    769            context->validationError(entryPoint, GL_INVALID_OPERATION, kCompressedMismatch);
    770            return false;
    771        }
    772 
    773        if (xoffset < 0 || yoffset < 0 || zoffset < 0)
    774        {
    775            context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
    776            return false;
    777        }
    778 
    779        if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
    780            std::numeric_limits<GLsizei>::max() - yoffset < height ||
    781            std::numeric_limits<GLsizei>::max() - zoffset < depth)
    782        {
    783            context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
    784            return false;
    785        }
    786 
    787        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
    788            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
    789            static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
    790        {
    791            context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
    792            return false;
    793        }
    794 
    795        if (width > 0 && height > 0 && depth > 0 && pixels == nullptr &&
    796            context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
    797        {
    798            context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull);
    799            return false;
    800        }
    801    }
    802 
    803    GLenum sizeCheckFormat = isSubImage ? format : internalformat;
    804    if (!ValidImageDataSize(context, entryPoint, texType, width, height, depth, sizeCheckFormat,
    805                            type, pixels, imageSize))
    806    {
    807        return false;
    808    }
    809 
    810    // Check for pixel unpack buffer related API errors
    811    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
    812    if (pixelUnpackBuffer != nullptr)
    813    {
    814        // ...data is not evenly divisible into the number of bytes needed to store in memory a
    815        // datum
    816        // indicated by type.
    817        if (!isCompressed)
    818        {
    819            size_t offset            = reinterpret_cast<size_t>(pixels);
    820            size_t dataBytesPerPixel = static_cast<size_t>(GetTypeInfo(type).bytes);
    821 
    822            if ((offset % dataBytesPerPixel) != 0)
    823            {
    824                context->validationError(entryPoint, GL_INVALID_OPERATION, kDataTypeNotAligned);
    825                return false;
    826            }
    827        }
    828 
    829        // ...the buffer object's data store is currently mapped but not persistently.
    830        if (pixelUnpackBuffer->isMapped() && !pixelUnpackBuffer->isPersistentlyMapped())
    831        {
    832            context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
    833            return false;
    834        }
    835    }
    836 
    837    if (context->getExtensions().webglCompatibilityANGLE)
    838    {
    839        // Define:
    840        //   DataStoreWidth  = (GL_UNPACK_ROW_LENGTH ? GL_UNPACK_ROW_LENGTH : width)
    841        //   DataStoreHeight = (GL_UNPACK_IMAGE_HEIGHT ? GL_UNPACK_IMAGE_HEIGHT : height)
    842        //
    843        // WebGL 2.0 imposes the following additional constraints:
    844        //
    845        // 1) texImage2D and texSubImage2D generate INVALID_OPERATION if:
    846        //      GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
    847        //    except for texImage2D if no GL_PIXEL_UNPACK_BUFFER is
    848        //    bound and _pixels_ is null.
    849        //
    850        // 2) texImage3D and texSubImage3D generate INVALID_OPERATION if:
    851        //      GL_UNPACK_SKIP_PIXELS + width > DataStoreWidth
    852        //      GL_UNPACK_SKIP_ROWS + height > DataStoreHeight
    853        //    except for texImage3D if no GL_PIXEL_UNPACK_BUFFER is
    854        //    bound and _pixels_ is null.
    855        if (!pixelUnpackBuffer && !pixels && !isSubImage)
    856        {
    857            // Exception case for texImage2D or texImage3D, above.
    858        }
    859        else
    860        {
    861            const auto &unpack   = context->getState().getUnpackState();
    862            GLint dataStoreWidth = unpack.rowLength ? unpack.rowLength : width;
    863            if (unpack.skipPixels + width > dataStoreWidth)
    864            {
    865                context->validationError(entryPoint, GL_INVALID_OPERATION,
    866                                         kInvalidUnpackParametersForWebGL);
    867                return false;
    868            }
    869            if (target == TextureTarget::_3D || target == TextureTarget::_2DArray)
    870            {
    871                GLint dataStoreHeight = unpack.imageHeight ? unpack.imageHeight : height;
    872                if (unpack.skipRows + height > dataStoreHeight)
    873                {
    874                    context->validationError(entryPoint, GL_INVALID_OPERATION,
    875                                             kInvalidUnpackParametersForWebGL);
    876                    return false;
    877                }
    878            }
    879        }
    880    }
    881 
    882    return true;
    883 }
    884 
    885 bool ValidateES3TexImage2DParameters(const Context *context,
    886                                     angle::EntryPoint entryPoint,
    887                                     TextureTarget target,
    888                                     GLint level,
    889                                     GLenum internalformat,
    890                                     bool isCompressed,
    891                                     bool isSubImage,
    892                                     GLint xoffset,
    893                                     GLint yoffset,
    894                                     GLint zoffset,
    895                                     GLsizei width,
    896                                     GLsizei height,
    897                                     GLsizei depth,
    898                                     GLint border,
    899                                     GLenum format,
    900                                     GLenum type,
    901                                     GLsizei imageSize,
    902                                     const void *pixels)
    903 {
    904    if (!ValidTexture2DDestinationTarget(context, target))
    905    {
    906        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    907        return false;
    908    }
    909 
    910    return ValidateES3TexImageParametersBase(
    911        context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
    912        yoffset, zoffset, width, height, depth, border, format, type, imageSize, pixels);
    913 }
    914 
    915 bool ValidateES3TexImage3DParameters(const Context *context,
    916                                     angle::EntryPoint entryPoint,
    917                                     TextureTarget target,
    918                                     GLint level,
    919                                     GLenum internalformat,
    920                                     bool isCompressed,
    921                                     bool isSubImage,
    922                                     GLint xoffset,
    923                                     GLint yoffset,
    924                                     GLint zoffset,
    925                                     GLsizei width,
    926                                     GLsizei height,
    927                                     GLsizei depth,
    928                                     GLint border,
    929                                     GLenum format,
    930                                     GLenum type,
    931                                     GLsizei bufSize,
    932                                     const void *pixels)
    933 {
    934    if (!ValidTexture3DDestinationTarget(context, target))
    935    {
    936        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    937        return false;
    938    }
    939 
    940    return ValidateES3TexImageParametersBase(
    941        context, entryPoint, target, level, internalformat, isCompressed, isSubImage, xoffset,
    942        yoffset, zoffset, width, height, depth, border, format, type, bufSize, pixels);
    943 }
    944 
    945 struct EffectiveInternalFormatInfo
    946 {
    947    GLenum effectiveFormat;
    948    GLenum destFormat;
    949    GLuint minRedBits;
    950    GLuint maxRedBits;
    951    GLuint minGreenBits;
    952    GLuint maxGreenBits;
    953    GLuint minBlueBits;
    954    GLuint maxBlueBits;
    955    GLuint minAlphaBits;
    956    GLuint maxAlphaBits;
    957 };
    958 
    959 static bool QueryEffectiveFormatList(const InternalFormat &srcFormat,
    960                                     GLenum targetFormat,
    961                                     const EffectiveInternalFormatInfo *list,
    962                                     size_t size,
    963                                     GLenum *outEffectiveFormat)
    964 {
    965    for (size_t curFormat = 0; curFormat < size; ++curFormat)
    966    {
    967        const EffectiveInternalFormatInfo &formatInfo = list[curFormat];
    968        if ((formatInfo.destFormat == targetFormat) &&
    969            (formatInfo.minRedBits <= srcFormat.redBits &&
    970             formatInfo.maxRedBits >= srcFormat.redBits) &&
    971            (formatInfo.minGreenBits <= srcFormat.greenBits &&
    972             formatInfo.maxGreenBits >= srcFormat.greenBits) &&
    973            (formatInfo.minBlueBits <= srcFormat.blueBits &&
    974             formatInfo.maxBlueBits >= srcFormat.blueBits) &&
    975            (formatInfo.minAlphaBits <= srcFormat.alphaBits &&
    976             formatInfo.maxAlphaBits >= srcFormat.alphaBits))
    977        {
    978            *outEffectiveFormat = formatInfo.effectiveFormat;
    979            return true;
    980        }
    981    }
    982 
    983    *outEffectiveFormat = GL_NONE;
    984    return false;
    985 }
    986 
    987 bool GetSizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
    988                                         GLenum *outEffectiveFormat)
    989 {
    990    // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
    991    // Effective internal format coresponding to destination internal format and linear source
    992    // buffer component sizes.
    993    //                                       | Source channel min/max sizes |
    994    //   Effective Internal Format   |  N/A  |  R   |  G   |  B   |  A      |
    995    // clang-format off
    996    constexpr EffectiveInternalFormatInfo list[] = {
    997        { GL_ALPHA8_EXT,              GL_NONE, 0,  0, 0,  0, 0,  0, 1, 8 },
    998        { GL_R8,                      GL_NONE, 1,  8, 0,  0, 0,  0, 0, 0 },
    999        { GL_RG8,                     GL_NONE, 1,  8, 1,  8, 0,  0, 0, 0 },
   1000        { GL_RGB565,                  GL_NONE, 1,  5, 1,  6, 1,  5, 0, 0 },
   1001        { GL_RGB8,                    GL_NONE, 6,  8, 7,  8, 6,  8, 0, 0 },
   1002        { GL_RGBA4,                   GL_NONE, 1,  4, 1,  4, 1,  4, 1, 4 },
   1003        { GL_RGB5_A1,                 GL_NONE, 5,  5, 5,  5, 5,  5, 1, 1 },
   1004        { GL_RGBA8,                   GL_NONE, 5,  8, 5,  8, 5,  8, 2, 8 },
   1005        { GL_RGB10_A2,                GL_NONE, 9, 10, 9, 10, 9, 10, 2, 2 },
   1006    };
   1007    // clang-format on
   1008 
   1009    return QueryEffectiveFormatList(srcFormat, GL_NONE, list, ArraySize(list), outEffectiveFormat);
   1010 }
   1011 
   1012 bool GetUnsizedEffectiveInternalFormatInfo(const InternalFormat &srcFormat,
   1013                                           const InternalFormat &destFormat,
   1014                                           GLenum *outEffectiveFormat)
   1015 {
   1016    constexpr GLuint umax = UINT_MAX;
   1017 
   1018    // OpenGL ES 3.0.3 Specification, Table 3.17, pg 141:
   1019    // Effective internal format coresponding to destination internal format andlinear source buffer
   1020    // component sizes.
   1021    //                                                   |   Source channel min/max sizes   |
   1022    //     Effective Internal Format |   Dest Format     |   R   |    G   |    B   |    A   |
   1023    // clang-format off
   1024    constexpr EffectiveInternalFormatInfo list[] = {
   1025        { GL_ALPHA8_EXT,             GL_ALPHA,           0, umax, 0, umax, 0, umax, 1,    8 },
   1026        { GL_LUMINANCE8_EXT,         GL_LUMINANCE,       1,    8, 0, umax, 0, umax, 0, umax },
   1027        { GL_LUMINANCE8_ALPHA8_EXT,  GL_LUMINANCE_ALPHA, 1,    8, 0, umax, 0, umax, 1,    8 },
   1028        { GL_RGB565,                 GL_RGB,             1,    5, 1,    6, 1,    5, 0, umax },
   1029        { GL_RGB8,                   GL_RGB,             6,    8, 7,    8, 6,    8, 0, umax },
   1030        { GL_RGBA4,                  GL_RGBA,            1,    4, 1,    4, 1,    4, 1,    4 },
   1031        { GL_RGB5_A1,                GL_RGBA,            5,    5, 5,    5, 5,    5, 1,    1 },
   1032        { GL_RGBA8,                  GL_RGBA,            5,    8, 5,    8, 5,    8, 5,    8 },
   1033    };
   1034    // clang-format on
   1035 
   1036    return QueryEffectiveFormatList(srcFormat, destFormat.format, list, ArraySize(list),
   1037                                    outEffectiveFormat);
   1038 }
   1039 
   1040 static bool GetEffectiveInternalFormat(const InternalFormat &srcFormat,
   1041                                       const InternalFormat &destFormat,
   1042                                       GLenum *outEffectiveFormat)
   1043 {
   1044    if (destFormat.sized)
   1045    {
   1046        return GetSizedEffectiveInternalFormatInfo(srcFormat, outEffectiveFormat);
   1047    }
   1048    else
   1049    {
   1050        return GetUnsizedEffectiveInternalFormatInfo(srcFormat, destFormat, outEffectiveFormat);
   1051    }
   1052 }
   1053 
   1054 static bool EqualOrFirstZero(GLuint first, GLuint second)
   1055 {
   1056    return first == 0 || first == second;
   1057 }
   1058 
   1059 static bool IsValidES3CopyTexImageCombination(const InternalFormat &textureFormatInfo,
   1060                                              const InternalFormat &framebufferFormatInfo,
   1061                                              FramebufferID readBufferHandle)
   1062 {
   1063    if (!ValidES3CopyConversion(textureFormatInfo.format, framebufferFormatInfo.format))
   1064    {
   1065        return false;
   1066    }
   1067 
   1068    // Section 3.8.5 of the GLES 3.0.3 spec states that source and destination formats
   1069    // must both be signed, unsigned, or fixed point and both source and destinations
   1070    // must be either both SRGB or both not SRGB. EXT_color_buffer_float adds allowed
   1071    // conversion between fixed and floating point.
   1072 
   1073    if ((textureFormatInfo.colorEncoding == GL_SRGB) !=
   1074        (framebufferFormatInfo.colorEncoding == GL_SRGB))
   1075    {
   1076        return false;
   1077    }
   1078 
   1079    if (((textureFormatInfo.componentType == GL_INT) !=
   1080         (framebufferFormatInfo.componentType == GL_INT)) ||
   1081        ((textureFormatInfo.componentType == GL_UNSIGNED_INT) !=
   1082         (framebufferFormatInfo.componentType == GL_UNSIGNED_INT)))
   1083    {
   1084        return false;
   1085    }
   1086 
   1087    if ((textureFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
   1088         textureFormatInfo.componentType == GL_SIGNED_NORMALIZED) &&
   1089        !(framebufferFormatInfo.componentType == GL_UNSIGNED_NORMALIZED ||
   1090          framebufferFormatInfo.componentType == GL_SIGNED_NORMALIZED))
   1091    {
   1092        return false;
   1093    }
   1094 
   1095    // SNORM is not supported (e.g. is not in the tables of "effective internal format" that
   1096    // correspond to internal formats.
   1097    if (textureFormatInfo.componentType == GL_SIGNED_NORMALIZED)
   1098    {
   1099        return false;
   1100    }
   1101 
   1102    // Section 3.8.5 of the GLES 3.0.3 (and section 8.6 of the GLES 3.2) spec has a caveat, that
   1103    // the KHR dEQP tests enforce:
   1104    //
   1105    // Note that the above rules disallow matches where some components sizes are smaller and
   1106    // others are larger (such as RGB10_A2).
   1107    if (!textureFormatInfo.sized && (framebufferFormatInfo.internalFormat == GL_RGB10_A2))
   1108    {
   1109        return false;
   1110    }
   1111 
   1112    // GLES specification 3.0.3, sec 3.8.5, pg 139-140:
   1113    // The effective internal format of the source buffer is determined with the following rules
   1114    // applied in order:
   1115    //    * If the source buffer is a texture or renderbuffer that was created with a sized internal
   1116    //      format then the effective internal format is the source buffer's sized internal format.
   1117    //    * If the source buffer is a texture that was created with an unsized base internal format,
   1118    //      then the effective internal format is the source image array's effective internal
   1119    //      format, as specified by table 3.12, which is determined from the <format> and <type>
   1120    //      that were used when the source image array was specified by TexImage*.
   1121    //    * Otherwise the effective internal format is determined by the row in table 3.17 or 3.18
   1122    //      where Destination Internal Format matches internalformat and where the [source channel
   1123    //      sizes] are consistent with the values of the source buffer's [channel sizes]. Table 3.17
   1124    //      is used if the FRAMEBUFFER_ATTACHMENT_ENCODING is LINEAR and table 3.18 is used if the
   1125    //      FRAMEBUFFER_ATTACHMENT_ENCODING is SRGB.
   1126    const InternalFormat *sourceEffectiveFormat = nullptr;
   1127    if (readBufferHandle.value != 0)
   1128    {
   1129        // Not the default framebuffer, therefore the read buffer must be a user-created texture or
   1130        // renderbuffer
   1131        if (framebufferFormatInfo.sized)
   1132        {
   1133            sourceEffectiveFormat = &framebufferFormatInfo;
   1134        }
   1135        else
   1136        {
   1137            // Renderbuffers cannot be created with an unsized internal format, so this must be an
   1138            // unsized-format texture. We can use the same table we use when creating textures to
   1139            // get its effective sized format.
   1140            sourceEffectiveFormat =
   1141                &GetSizedInternalFormatInfo(framebufferFormatInfo.sizedInternalFormat);
   1142        }
   1143    }
   1144    else
   1145    {
   1146        // The effective internal format must be derived from the source framebuffer's channel
   1147        // sizes. This is done in GetEffectiveInternalFormat for linear buffers (table 3.17)
   1148        if (framebufferFormatInfo.colorEncoding == GL_LINEAR)
   1149        {
   1150            GLenum effectiveFormat;
   1151            if (GetEffectiveInternalFormat(framebufferFormatInfo, textureFormatInfo,
   1152                                           &effectiveFormat))
   1153            {
   1154                sourceEffectiveFormat = &GetSizedInternalFormatInfo(effectiveFormat);
   1155            }
   1156            else
   1157            {
   1158                return false;
   1159            }
   1160        }
   1161        else if (framebufferFormatInfo.colorEncoding == GL_SRGB)
   1162        {
   1163            // SRGB buffers can only be copied to sized format destinations according to table 3.18
   1164            if (textureFormatInfo.sized &&
   1165                (framebufferFormatInfo.redBits >= 1 && framebufferFormatInfo.redBits <= 8) &&
   1166                (framebufferFormatInfo.greenBits >= 1 && framebufferFormatInfo.greenBits <= 8) &&
   1167                (framebufferFormatInfo.blueBits >= 1 && framebufferFormatInfo.blueBits <= 8) &&
   1168                (framebufferFormatInfo.alphaBits >= 1 && framebufferFormatInfo.alphaBits <= 8))
   1169            {
   1170                sourceEffectiveFormat = &GetSizedInternalFormatInfo(GL_SRGB8_ALPHA8);
   1171            }
   1172            else
   1173            {
   1174                return false;
   1175            }
   1176        }
   1177        else
   1178        {
   1179            UNREACHABLE();
   1180            return false;
   1181        }
   1182    }
   1183 
   1184    if (textureFormatInfo.sized)
   1185    {
   1186        // Section 3.8.5 of the GLES 3.0.3 spec, pg 139, requires that, if the destination format is
   1187        // sized, component sizes of the source and destination formats must exactly match if the
   1188        // destination format exists.
   1189        if (!EqualOrFirstZero(textureFormatInfo.redBits, sourceEffectiveFormat->redBits) ||
   1190            !EqualOrFirstZero(textureFormatInfo.greenBits, sourceEffectiveFormat->greenBits) ||
   1191            !EqualOrFirstZero(textureFormatInfo.blueBits, sourceEffectiveFormat->blueBits) ||
   1192            !EqualOrFirstZero(textureFormatInfo.alphaBits, sourceEffectiveFormat->alphaBits))
   1193        {
   1194            return false;
   1195        }
   1196    }
   1197 
   1198    return true;  // A conversion function exists, and no rule in the specification has precluded
   1199                  // conversion between these formats.
   1200 }
   1201 
   1202 bool ValidateES3CopyTexImageParametersBase(const Context *context,
   1203                                           angle::EntryPoint entryPoint,
   1204                                           TextureTarget target,
   1205                                           GLint level,
   1206                                           GLenum internalformat,
   1207                                           bool isSubImage,
   1208                                           GLint xoffset,
   1209                                           GLint yoffset,
   1210                                           GLint zoffset,
   1211                                           GLint x,
   1212                                           GLint y,
   1213                                           GLsizei width,
   1214                                           GLsizei height,
   1215                                           GLint border)
   1216 {
   1217    Format textureFormat = Format::Invalid();
   1218    if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
   1219                                            isSubImage, xoffset, yoffset, zoffset, x, y, width,
   1220                                            height, border, &textureFormat))
   1221    {
   1222        return false;
   1223    }
   1224    ASSERT(textureFormat.valid() || !isSubImage);
   1225 
   1226    const auto &state               = context->getState();
   1227    Framebuffer *framebuffer        = state.getReadFramebuffer();
   1228    FramebufferID readFramebufferID = framebuffer->id();
   1229 
   1230    if (!ValidateFramebufferComplete(context, entryPoint, framebuffer))
   1231    {
   1232        return false;
   1233    }
   1234 
   1235    // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
   1236    // resolved before copying
   1237    if (!framebuffer->isDefault() &&
   1238        !ValidateFramebufferNotMultisampled(context, entryPoint, framebuffer, true))
   1239    {
   1240        return false;
   1241    }
   1242 
   1243    const FramebufferAttachment *source = framebuffer->getReadColorAttachment();
   1244 
   1245    // According to ES 3.x spec, if the internalformat of the texture
   1246    // is RGB9_E5 and copy to such a texture, generate INVALID_OPERATION.
   1247    if (textureFormat.info->internalFormat == GL_RGB9_E5)
   1248    {
   1249        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
   1250        return false;
   1251    }
   1252 
   1253    if (isSubImage)
   1254    {
   1255        if (!IsValidES3CopyTexImageCombination(*textureFormat.info, *source->getFormat().info,
   1256                                               readFramebufferID))
   1257        {
   1258            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCopyCombination);
   1259            return false;
   1260        }
   1261    }
   1262    else
   1263    {
   1264        // Use format/type from the source FBO. (Might not be perfect for all cases?)
   1265        const InternalFormat &framebufferFormat = *source->getFormat().info;
   1266        const InternalFormat &copyFormat = GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
   1267        if (!IsValidES3CopyTexImageCombination(copyFormat, framebufferFormat, readFramebufferID))
   1268        {
   1269            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCopyCombination);
   1270            return false;
   1271        }
   1272    }
   1273 
   1274    // If width or height is zero, it is a no-op.  Return false without setting an error.
   1275    return (width > 0 && height > 0);
   1276 }
   1277 
   1278 bool ValidateES3CopyTexImage2DParameters(const Context *context,
   1279                                         angle::EntryPoint entryPoint,
   1280                                         TextureTarget target,
   1281                                         GLint level,
   1282                                         GLenum internalformat,
   1283                                         bool isSubImage,
   1284                                         GLint xoffset,
   1285                                         GLint yoffset,
   1286                                         GLint zoffset,
   1287                                         GLint x,
   1288                                         GLint y,
   1289                                         GLsizei width,
   1290                                         GLsizei height,
   1291                                         GLint border)
   1292 {
   1293    if (!ValidTexture2DDestinationTarget(context, target))
   1294    {
   1295        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   1296        return false;
   1297    }
   1298 
   1299    return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
   1300                                                 isSubImage, xoffset, yoffset, zoffset, x, y, width,
   1301                                                 height, border);
   1302 }
   1303 
   1304 bool ValidateES3CopyTexImage3DParameters(const Context *context,
   1305                                         angle::EntryPoint entryPoint,
   1306                                         TextureTarget target,
   1307                                         GLint level,
   1308                                         GLenum internalformat,
   1309                                         bool isSubImage,
   1310                                         GLint xoffset,
   1311                                         GLint yoffset,
   1312                                         GLint zoffset,
   1313                                         GLint x,
   1314                                         GLint y,
   1315                                         GLsizei width,
   1316                                         GLsizei height,
   1317                                         GLint border)
   1318 {
   1319    if (!ValidTexture3DDestinationTarget(context, target))
   1320    {
   1321        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   1322        return false;
   1323    }
   1324 
   1325    return ValidateES3CopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
   1326                                                 isSubImage, xoffset, yoffset, zoffset, x, y, width,
   1327                                                 height, border);
   1328 }
   1329 
   1330 bool ValidateES3TexStorageParametersLevel(const Context *context,
   1331                                          angle::EntryPoint entryPoint,
   1332                                          TextureType target,
   1333                                          GLsizei levels,
   1334                                          GLsizei width,
   1335                                          GLsizei height,
   1336                                          GLsizei depth)
   1337 {
   1338    GLsizei maxDim = std::max(width, height);
   1339    if (target != TextureType::_2DArray)
   1340    {
   1341        maxDim = std::max(maxDim, depth);
   1342    }
   1343 
   1344    if (levels > log2(maxDim) + 1)
   1345    {
   1346        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
   1347        return false;
   1348    }
   1349 
   1350    return true;
   1351 }
   1352 
   1353 bool ValidateES3TexStorageParametersExtent(const Context *context,
   1354                                           angle::EntryPoint entryPoint,
   1355                                           TextureType target,
   1356                                           GLsizei levels,
   1357                                           GLsizei width,
   1358                                           GLsizei height,
   1359                                           GLsizei depth)
   1360 {
   1361    const Caps &caps = context->getCaps();
   1362 
   1363    switch (target)
   1364    {
   1365        case TextureType::_2D:
   1366        {
   1367            if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
   1368            {
   1369                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1370                return false;
   1371            }
   1372        }
   1373        break;
   1374 
   1375        case TextureType::Rectangle:
   1376        {
   1377            if (levels != 1)
   1378            {
   1379                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevels);
   1380                return false;
   1381            }
   1382 
   1383            if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
   1384            {
   1385                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1386                return false;
   1387            }
   1388        }
   1389        break;
   1390 
   1391        case TextureType::CubeMap:
   1392        {
   1393            if (width != height)
   1394            {
   1395                context->validationError(entryPoint, GL_INVALID_VALUE,
   1396                                         kCubemapFacesEqualDimensions);
   1397                return false;
   1398            }
   1399 
   1400            if (width > caps.maxCubeMapTextureSize)
   1401            {
   1402                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1403                return false;
   1404            }
   1405        }
   1406        break;
   1407 
   1408        case TextureType::_3D:
   1409        {
   1410            if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
   1411                depth > caps.max3DTextureSize)
   1412            {
   1413                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1414                return false;
   1415            }
   1416        }
   1417        break;
   1418 
   1419        case TextureType::_2DArray:
   1420        {
   1421            if (width > caps.max2DTextureSize || height > caps.max2DTextureSize ||
   1422                depth > caps.maxArrayTextureLayers)
   1423            {
   1424                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1425                return false;
   1426            }
   1427        }
   1428        break;
   1429 
   1430        case TextureType::CubeMapArray:
   1431        {
   1432            if (width != height)
   1433            {
   1434                context->validationError(entryPoint, GL_INVALID_VALUE,
   1435                                         kCubemapFacesEqualDimensions);
   1436                return false;
   1437            }
   1438 
   1439            if (width > caps.maxCubeMapTextureSize)
   1440            {
   1441                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1442                return false;
   1443            }
   1444 
   1445            if (width > caps.max3DTextureSize || height > caps.max3DTextureSize ||
   1446                depth > caps.max3DTextureSize)
   1447            {
   1448                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1449                return false;
   1450            }
   1451 
   1452            if (depth % 6 != 0)
   1453            {
   1454                context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapInvalidDepth);
   1455                return false;
   1456            }
   1457        }
   1458        break;
   1459 
   1460        default:
   1461            UNREACHABLE();
   1462            return false;
   1463    }
   1464 
   1465    return true;
   1466 }
   1467 
   1468 bool ValidateES3TexStorageParametersTexObject(const Context *context,
   1469                                              angle::EntryPoint entryPoint,
   1470                                              TextureType target)
   1471 {
   1472    Texture *texture = context->getTextureByType(target);
   1473    if (!texture || texture->id().value == 0)
   1474    {
   1475        context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
   1476        return false;
   1477    }
   1478 
   1479    if (texture->getImmutableFormat())
   1480    {
   1481        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
   1482        return false;
   1483    }
   1484 
   1485    return true;
   1486 }
   1487 
   1488 bool ValidateES3TexStorageParametersFormat(const Context *context,
   1489                                           angle::EntryPoint entryPoint,
   1490                                           TextureType target,
   1491                                           GLsizei levels,
   1492                                           GLenum internalformat,
   1493                                           GLsizei width,
   1494                                           GLsizei height,
   1495                                           GLsizei depth)
   1496 {
   1497    // From ANGLE_texture_external_yuv_sampling:
   1498    // Texture target can only be TEXTURE_2D, there is no mipmap support
   1499    if (gl::IsYuvFormat(internalformat))
   1500    {
   1501        if (!context->getExtensions().yuvInternalFormatANGLE)
   1502        {
   1503            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1504            return false;
   1505        }
   1506 
   1507        if (target != TextureType::_2D)
   1508        {
   1509            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   1510            return false;
   1511        }
   1512 
   1513        if (levels != 1)
   1514        {
   1515            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   1516            return false;
   1517        }
   1518    }
   1519 
   1520    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
   1521    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
   1522    {
   1523        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1524        return false;
   1525    }
   1526 
   1527    if (!formatInfo.sized)
   1528    {
   1529        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1530        return false;
   1531    }
   1532 
   1533    if (formatInfo.compressed)
   1534    {
   1535        if (target == TextureType::Rectangle)
   1536        {
   1537            context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
   1538            return false;
   1539        }
   1540 
   1541        if (target == TextureType::_2DArray)
   1542        {
   1543            if (!ValidateES3CompressedFormatForTexture2DArray(context, entryPoint,
   1544                                                              formatInfo.internalFormat))
   1545            {
   1546                // Error already generated.
   1547                return false;
   1548            }
   1549        }
   1550 
   1551        if (target == TextureType::_3D)
   1552        {
   1553            if (!ValidateES3CompressedFormatForTexture3D(context, entryPoint,
   1554                                                         formatInfo.internalFormat))
   1555            {
   1556                // Error already generated.
   1557                return false;
   1558            }
   1559        }
   1560 
   1561        if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth))
   1562        {
   1563            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCompressedImageSize);
   1564            return false;
   1565        }
   1566    }
   1567 
   1568    return true;
   1569 }
   1570 
   1571 bool ValidateES3TexStorageParametersBase(const Context *context,
   1572                                         angle::EntryPoint entryPoint,
   1573                                         TextureType target,
   1574                                         GLsizei levels,
   1575                                         GLenum internalformat,
   1576                                         GLsizei width,
   1577                                         GLsizei height,
   1578                                         GLsizei depth)
   1579 {
   1580    if (width < 1 || height < 1 || depth < 1 || levels < 1)
   1581    {
   1582        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
   1583        return false;
   1584    }
   1585 
   1586    if (!ValidateES3TexStorageParametersLevel(context, entryPoint, target, levels, width, height,
   1587                                              depth))
   1588    {
   1589        // Error already generated.
   1590        return false;
   1591    }
   1592 
   1593    if (!ValidateES3TexStorageParametersExtent(context, entryPoint, target, levels, width, height,
   1594                                               depth))
   1595    {
   1596        // Error already generated.
   1597        return false;
   1598    }
   1599 
   1600    if (!ValidateES3TexStorageParametersTexObject(context, entryPoint, target))
   1601    {
   1602        // Error already generated.
   1603        return false;
   1604    }
   1605 
   1606    if (!ValidateES3TexStorageParametersFormat(context, entryPoint, target, levels, internalformat,
   1607                                               width, height, depth))
   1608    {
   1609        // Error already generated.
   1610        return false;
   1611    }
   1612 
   1613    return true;
   1614 }
   1615 
   1616 bool ValidateES3TexStorage2DParameters(const Context *context,
   1617                                       angle::EntryPoint entryPoint,
   1618                                       TextureType target,
   1619                                       GLsizei levels,
   1620                                       GLenum internalformat,
   1621                                       GLsizei width,
   1622                                       GLsizei height,
   1623                                       GLsizei depth)
   1624 {
   1625    if (!ValidTexture2DTarget(context, target))
   1626    {
   1627        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   1628        return false;
   1629    }
   1630 
   1631    return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
   1632                                               width, height, depth);
   1633 }
   1634 
   1635 bool ValidateES3TexStorage3DParameters(const Context *context,
   1636                                       angle::EntryPoint entryPoint,
   1637                                       TextureType target,
   1638                                       GLsizei levels,
   1639                                       GLenum internalformat,
   1640                                       GLsizei width,
   1641                                       GLsizei height,
   1642                                       GLsizei depth)
   1643 {
   1644    if (!ValidTexture3DTarget(context, target))
   1645    {
   1646        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   1647        return false;
   1648    }
   1649 
   1650    return ValidateES3TexStorageParametersBase(context, entryPoint, target, levels, internalformat,
   1651                                               width, height, depth);
   1652 }
   1653 
   1654 bool ValidateBeginQuery(const Context *context,
   1655                        angle::EntryPoint entryPoint,
   1656                        QueryType target,
   1657                        QueryID id)
   1658 {
   1659    if (context->getClientMajorVersion() < 3)
   1660    {
   1661        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1662        return false;
   1663    }
   1664 
   1665    return ValidateBeginQueryBase(context, entryPoint, target, id);
   1666 }
   1667 
   1668 bool ValidateEndQuery(const Context *context, angle::EntryPoint entryPoint, QueryType target)
   1669 {
   1670    if (context->getClientMajorVersion() < 3)
   1671    {
   1672        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1673        return false;
   1674    }
   1675 
   1676    return ValidateEndQueryBase(context, entryPoint, target);
   1677 }
   1678 
   1679 bool ValidateGetQueryiv(const Context *context,
   1680                        angle::EntryPoint entryPoint,
   1681                        QueryType target,
   1682                        GLenum pname,
   1683                        const GLint *params)
   1684 {
   1685    if (context->getClientMajorVersion() < 3)
   1686    {
   1687        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1688        return false;
   1689    }
   1690 
   1691    return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
   1692 }
   1693 
   1694 bool ValidateGetQueryObjectuiv(const Context *context,
   1695                               angle::EntryPoint entryPoint,
   1696                               QueryID id,
   1697                               GLenum pname,
   1698                               const GLuint *params)
   1699 {
   1700    if (context->getClientMajorVersion() < 3)
   1701    {
   1702        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1703        return false;
   1704    }
   1705 
   1706    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
   1707 }
   1708 
   1709 bool ValidateFramebufferTextureLayer(const Context *context,
   1710                                     angle::EntryPoint entryPoint,
   1711                                     GLenum target,
   1712                                     GLenum attachment,
   1713                                     TextureID texture,
   1714                                     GLint level,
   1715                                     GLint layer)
   1716 {
   1717    if (context->getClientMajorVersion() < 3)
   1718    {
   1719        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1720        return false;
   1721    }
   1722 
   1723    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
   1724    {
   1725        return false;
   1726    }
   1727 
   1728    const Caps &caps = context->getCaps();
   1729    if (texture.value != 0)
   1730    {
   1731        if (layer < 0)
   1732        {
   1733            context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLayer);
   1734            return false;
   1735        }
   1736 
   1737        Texture *tex = context->getTexture(texture);
   1738        ASSERT(tex);
   1739 
   1740        switch (tex->getType())
   1741        {
   1742            case TextureType::_2DArray:
   1743            {
   1744                if (level > log2(caps.max2DTextureSize))
   1745                {
   1746                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1747                                             kFramebufferTextureInvalidMipLevel);
   1748                    return false;
   1749                }
   1750 
   1751                if (layer >= caps.maxArrayTextureLayers)
   1752                {
   1753                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1754                                             kFramebufferTextureInvalidLayer);
   1755                    return false;
   1756                }
   1757            }
   1758            break;
   1759 
   1760            case TextureType::_3D:
   1761            {
   1762                if (level > log2(caps.max3DTextureSize))
   1763                {
   1764                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1765                                             kFramebufferTextureInvalidMipLevel);
   1766                    return false;
   1767                }
   1768 
   1769                if (layer >= caps.max3DTextureSize)
   1770                {
   1771                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1772                                             kFramebufferTextureInvalidLayer);
   1773                    return false;
   1774                }
   1775            }
   1776            break;
   1777 
   1778            case TextureType::_2DMultisampleArray:
   1779            {
   1780                if (level != 0)
   1781                {
   1782                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1783                                             kFramebufferTextureInvalidMipLevel);
   1784                    return false;
   1785                }
   1786 
   1787                if (layer >= caps.maxArrayTextureLayers)
   1788                {
   1789                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1790                                             kFramebufferTextureInvalidLayer);
   1791                    return false;
   1792                }
   1793            }
   1794            break;
   1795 
   1796            case TextureType::CubeMap:
   1797            {
   1798                if (level > log2(caps.maxCubeMapTextureSize))
   1799                {
   1800                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1801                                             kFramebufferTextureInvalidMipLevel);
   1802                    return false;
   1803                }
   1804 
   1805                if (layer >= static_cast<GLint>(kCubeFaceCount))
   1806                {
   1807                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1808                                             kFramebufferTextureInvalidLayer);
   1809                    return false;
   1810                }
   1811            }
   1812            break;
   1813 
   1814            case TextureType::CubeMapArray:
   1815            {
   1816                if (level > log2(caps.maxCubeMapTextureSize))
   1817                {
   1818                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1819                                             kFramebufferTextureInvalidMipLevel);
   1820                    return false;
   1821                }
   1822 
   1823                if (layer >= caps.maxArrayTextureLayers)
   1824                {
   1825                    context->validationError(entryPoint, GL_INVALID_VALUE,
   1826                                             kFramebufferTextureInvalidLayer);
   1827                    return false;
   1828                }
   1829            }
   1830            break;
   1831 
   1832            default:
   1833                context->validationError(entryPoint, GL_INVALID_OPERATION,
   1834                                         kFramebufferTextureLayerIncorrectTextureType);
   1835                return false;
   1836        }
   1837 
   1838        const auto &format = tex->getFormat(TextureTypeToTarget(tex->getType(), layer), level);
   1839        if (format.info->compressed)
   1840        {
   1841            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1842                                     kCompressedTexturesNotAttachable);
   1843            return false;
   1844        }
   1845    }
   1846 
   1847    return true;
   1848 }
   1849 
   1850 bool ValidateInvalidateFramebuffer(const Context *context,
   1851                                   angle::EntryPoint entryPoint,
   1852                                   GLenum target,
   1853                                   GLsizei numAttachments,
   1854                                   const GLenum *attachments)
   1855 {
   1856    if (context->getClientMajorVersion() < 3)
   1857    {
   1858        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1859        return false;
   1860    }
   1861 
   1862    bool defaultFramebuffer = false;
   1863 
   1864    switch (target)
   1865    {
   1866        case GL_DRAW_FRAMEBUFFER:
   1867        case GL_FRAMEBUFFER:
   1868            defaultFramebuffer = context->getState().getDrawFramebuffer()->isDefault();
   1869            break;
   1870        case GL_READ_FRAMEBUFFER:
   1871            defaultFramebuffer = context->getState().getReadFramebuffer()->isDefault();
   1872            break;
   1873        default:
   1874            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   1875            return false;
   1876    }
   1877 
   1878    return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
   1879                                          defaultFramebuffer);
   1880 }
   1881 
   1882 bool ValidateInvalidateSubFramebuffer(const Context *context,
   1883                                      angle::EntryPoint entryPoint,
   1884                                      GLenum target,
   1885                                      GLsizei numAttachments,
   1886                                      const GLenum *attachments,
   1887                                      GLint x,
   1888                                      GLint y,
   1889                                      GLsizei width,
   1890                                      GLsizei height)
   1891 {
   1892    if (width < 0 || height < 0)
   1893    {
   1894        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   1895        return false;
   1896    }
   1897 
   1898    return ValidateInvalidateFramebuffer(context, entryPoint, target, numAttachments, attachments);
   1899 }
   1900 
   1901 bool ValidateClearBuffer(const Context *context, angle::EntryPoint entryPoint)
   1902 {
   1903    if (context->getClientMajorVersion() < 3)
   1904    {
   1905        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1906        return false;
   1907    }
   1908 
   1909    if (!ValidateFramebufferComplete(context, entryPoint, context->getState().getDrawFramebuffer()))
   1910    {
   1911        return false;
   1912    }
   1913 
   1914    return true;
   1915 }
   1916 
   1917 bool ValidateDrawRangeElements(const Context *context,
   1918                               angle::EntryPoint entryPoint,
   1919                               PrimitiveMode mode,
   1920                               GLuint start,
   1921                               GLuint end,
   1922                               GLsizei count,
   1923                               DrawElementsType type,
   1924                               const void *indices)
   1925 {
   1926    if (context->getClientMajorVersion() < 3)
   1927    {
   1928        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1929        return false;
   1930    }
   1931 
   1932    if (end < start)
   1933    {
   1934        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidElementRange);
   1935        return false;
   1936    }
   1937 
   1938    if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, 0))
   1939    {
   1940        return false;
   1941    }
   1942 
   1943    // Skip range checks for no-op calls.
   1944    if (count <= 0)
   1945    {
   1946        return true;
   1947    }
   1948 
   1949    return true;
   1950 }
   1951 
   1952 bool ValidateGetUniformuiv(const Context *context,
   1953                           angle::EntryPoint entryPoint,
   1954                           ShaderProgramID program,
   1955                           UniformLocation location,
   1956                           const GLuint *params)
   1957 {
   1958    if (context->getClientMajorVersion() < 3)
   1959    {
   1960        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1961        return false;
   1962    }
   1963 
   1964    return ValidateGetUniformBase(context, entryPoint, program, location);
   1965 }
   1966 
   1967 bool ValidateReadBuffer(const Context *context, angle::EntryPoint entryPoint, GLenum src)
   1968 {
   1969    if (context->getClientMajorVersion() < 3)
   1970    {
   1971        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   1972        return false;
   1973    }
   1974 
   1975    const Framebuffer *readFBO = context->getState().getReadFramebuffer();
   1976 
   1977    if (readFBO == nullptr)
   1978    {
   1979        context->validationError(entryPoint, GL_INVALID_OPERATION, kNoReadFramebuffer);
   1980        return false;
   1981    }
   1982 
   1983    if (src == GL_NONE)
   1984    {
   1985        return true;
   1986    }
   1987 
   1988    if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT31))
   1989    {
   1990        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidReadBuffer);
   1991        return false;
   1992    }
   1993 
   1994    if (readFBO->isDefault())
   1995    {
   1996        if (src != GL_BACK)
   1997        {
   1998            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDefaultReadBuffer);
   1999            return false;
   2000        }
   2001    }
   2002    else
   2003    {
   2004        GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
   2005 
   2006        if (drawBuffer >= static_cast<GLuint>(context->getCaps().maxColorAttachments))
   2007        {
   2008            context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
   2009            return false;
   2010        }
   2011    }
   2012 
   2013    return true;
   2014 }
   2015 
   2016 bool ValidateCompressedTexImage3D(const Context *context,
   2017                                  angle::EntryPoint entryPoint,
   2018                                  TextureTarget target,
   2019                                  GLint level,
   2020                                  GLenum internalformat,
   2021                                  GLsizei width,
   2022                                  GLsizei height,
   2023                                  GLsizei depth,
   2024                                  GLint border,
   2025                                  GLsizei imageSize,
   2026                                  const void *data)
   2027 {
   2028    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
   2029    {
   2030        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2031        return false;
   2032    }
   2033 
   2034    if (!ValidTextureTarget(context, TextureTargetToType(target)))
   2035    {
   2036        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   2037        return false;
   2038    }
   2039 
   2040    // Validate image size
   2041    if (!ValidImageSizeParameters(context, entryPoint, TextureTargetToType(target), level, width,
   2042                                  height, depth, false))
   2043    {
   2044        // Error already generated.
   2045        return false;
   2046    }
   2047 
   2048    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
   2049    if (!formatInfo.compressed)
   2050    {
   2051        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCompressedFormat);
   2052        return false;
   2053    }
   2054 
   2055    GLuint blockSize = 0;
   2056    if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
   2057    {
   2058        context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
   2059        return false;
   2060    }
   2061 
   2062    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
   2063    {
   2064        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize);
   2065        return false;
   2066    }
   2067 
   2068    // 3D texture target validation
   2069    if (target != TextureTarget::_3D && target != TextureTarget::_2DArray)
   2070    {
   2071        if (context->getClientVersion() < ES_3_2 || target != TextureTarget::CubeMapArray)
   2072        {
   2073            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   2074            return false;
   2075        }
   2076    }
   2077 
   2078    // validateES3TexImageFormat sets the error code if there is an error
   2079    if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat, true,
   2080                                         false, 0, 0, 0, width, height, depth, border, GL_NONE,
   2081                                         GL_NONE, -1, data))
   2082    {
   2083        return false;
   2084    }
   2085 
   2086    return true;
   2087 }
   2088 
   2089 bool ValidateCompressedTexImage3DRobustANGLE(const Context *context,
   2090                                             angle::EntryPoint entryPoint,
   2091                                             TextureTarget target,
   2092                                             GLint level,
   2093                                             GLenum internalformat,
   2094                                             GLsizei width,
   2095                                             GLsizei height,
   2096                                             GLsizei depth,
   2097                                             GLint border,
   2098                                             GLsizei imageSize,
   2099                                             GLsizei dataSize,
   2100                                             const void *data)
   2101 {
   2102    if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
   2103    {
   2104        return false;
   2105    }
   2106 
   2107    return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
   2108                                        height, depth, border, imageSize, data);
   2109 }
   2110 
   2111 bool ValidateBindVertexArray(const Context *context,
   2112                             angle::EntryPoint entryPoint,
   2113                             VertexArrayID array)
   2114 {
   2115    if (context->getClientMajorVersion() < 3)
   2116    {
   2117        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2118        return false;
   2119    }
   2120 
   2121    return ValidateBindVertexArrayBase(context, entryPoint, array);
   2122 }
   2123 
   2124 bool ValidateIsVertexArray(const Context *context,
   2125                           angle::EntryPoint entryPoint,
   2126                           VertexArrayID array)
   2127 {
   2128    if (context->getClientMajorVersion() < 3)
   2129    {
   2130        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2131        return false;
   2132    }
   2133 
   2134    return true;
   2135 }
   2136 
   2137 static bool ValidateBindBufferCommon(const Context *context,
   2138                                     angle::EntryPoint entryPoint,
   2139                                     BufferBinding target,
   2140                                     GLuint index,
   2141                                     BufferID buffer,
   2142                                     GLintptr offset,
   2143                                     GLsizeiptr size)
   2144 {
   2145    if (context->getClientMajorVersion() < 3)
   2146    {
   2147        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2148        return false;
   2149    }
   2150 
   2151    if (buffer.value != 0 && offset < 0)
   2152    {
   2153        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   2154        return false;
   2155    }
   2156 
   2157    if (!context->getState().isBindGeneratesResourceEnabled() &&
   2158        !context->isBufferGenerated(buffer))
   2159    {
   2160        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   2161        return false;
   2162    }
   2163 
   2164    const Caps &caps = context->getCaps();
   2165    switch (target)
   2166    {
   2167        case BufferBinding::TransformFeedback:
   2168        {
   2169            if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
   2170            {
   2171                context->validationError(entryPoint, GL_INVALID_VALUE,
   2172                                         kIndexExceedsTransformFeedbackBufferBindings);
   2173                return false;
   2174            }
   2175            if (buffer.value != 0 && ((offset % 4) != 0 || (size % 4) != 0))
   2176            {
   2177                context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetAndSizeAlignment);
   2178                return false;
   2179            }
   2180 
   2181            if (context->getState().isTransformFeedbackActive())
   2182            {
   2183                context->validationError(entryPoint, GL_INVALID_OPERATION,
   2184                                         kTransformFeedbackTargetActive);
   2185                return false;
   2186            }
   2187            break;
   2188        }
   2189        case BufferBinding::Uniform:
   2190        {
   2191            if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
   2192            {
   2193                context->validationError(entryPoint, GL_INVALID_VALUE,
   2194                                         kIndexExceedsMaxUniformBufferBindings);
   2195                return false;
   2196            }
   2197 
   2198            ASSERT(caps.uniformBufferOffsetAlignment);
   2199            if (buffer.value != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
   2200            {
   2201                context->validationError(entryPoint, GL_INVALID_VALUE,
   2202                                         kUniformBufferOffsetAlignment);
   2203                return false;
   2204            }
   2205            break;
   2206        }
   2207        case BufferBinding::AtomicCounter:
   2208        {
   2209            if (context->getClientVersion() < ES_3_1)
   2210            {
   2211                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   2212                return false;
   2213            }
   2214            if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
   2215            {
   2216                context->validationError(entryPoint, GL_INVALID_VALUE,
   2217                                         kIndexExceedsMaxAtomicCounterBufferBindings);
   2218                return false;
   2219            }
   2220            if (buffer.value != 0 && (offset % 4) != 0)
   2221            {
   2222                context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetAlignment);
   2223                return false;
   2224            }
   2225            break;
   2226        }
   2227        case BufferBinding::ShaderStorage:
   2228        {
   2229            if (context->getClientVersion() < ES_3_1)
   2230            {
   2231                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   2232                return false;
   2233            }
   2234            if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
   2235            {
   2236                context->validationError(entryPoint, GL_INVALID_VALUE,
   2237                                         kExceedsMaxShaderStorageBufferBindings);
   2238                return false;
   2239            }
   2240            ASSERT(caps.shaderStorageBufferOffsetAlignment);
   2241            if (buffer.value != 0 && (offset % caps.shaderStorageBufferOffsetAlignment) != 0)
   2242            {
   2243                context->validationError(entryPoint, GL_INVALID_VALUE,
   2244                                         kShaderStorageBufferOffsetAlignment);
   2245                return false;
   2246            }
   2247            break;
   2248        }
   2249        case BufferBinding::Texture:
   2250        {
   2251            if (!context->getExtensions().textureBufferAny())
   2252            {
   2253                context->validationError(entryPoint, GL_INVALID_ENUM,
   2254                                         kTextureBufferExtensionNotAvailable);
   2255                return false;
   2256            }
   2257            if (index != 0)
   2258            {
   2259                context->validationError(entryPoint, GL_INVALID_VALUE,
   2260                                         kIndexExceedsMaxUniformBufferBindings);
   2261                return false;
   2262            }
   2263            if (buffer.value != 0 && (offset % caps.textureBufferOffsetAlignment) != 0)
   2264            {
   2265                context->validationError(entryPoint, GL_INVALID_VALUE,
   2266                                         kTextureBufferOffsetAlignment);
   2267                return false;
   2268            }
   2269            break;
   2270        }
   2271        case BufferBinding::InvalidEnum:
   2272            context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
   2273            return false;
   2274        default:
   2275            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   2276                                      ToGLenum(target));
   2277            return false;
   2278    }
   2279 
   2280    return true;
   2281 }
   2282 
   2283 bool ValidateBindBufferBase(const Context *context,
   2284                            angle::EntryPoint entryPoint,
   2285                            BufferBinding target,
   2286                            GLuint index,
   2287                            BufferID buffer)
   2288 {
   2289    return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, 0, 0);
   2290 }
   2291 
   2292 bool ValidateBindBufferRange(const Context *context,
   2293                             angle::EntryPoint entryPoint,
   2294                             BufferBinding target,
   2295                             GLuint index,
   2296                             BufferID buffer,
   2297                             GLintptr offset,
   2298                             GLsizeiptr size)
   2299 {
   2300    if (buffer.value != 0 && size <= 0)
   2301    {
   2302        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBindBufferSize);
   2303        return false;
   2304    }
   2305    return ValidateBindBufferCommon(context, entryPoint, target, index, buffer, offset, size);
   2306 }
   2307 
   2308 bool ValidateProgramBinary(const Context *context,
   2309                           angle::EntryPoint entryPoint,
   2310                           ShaderProgramID program,
   2311                           GLenum binaryFormat,
   2312                           const void *binary,
   2313                           GLsizei length)
   2314 {
   2315    if (context->getClientMajorVersion() < 3)
   2316    {
   2317        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2318        return false;
   2319    }
   2320 
   2321    return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
   2322 }
   2323 
   2324 bool ValidateGetProgramBinary(const Context *context,
   2325                              angle::EntryPoint entryPoint,
   2326                              ShaderProgramID program,
   2327                              GLsizei bufSize,
   2328                              const GLsizei *length,
   2329                              const GLenum *binaryFormat,
   2330                              const void *binary)
   2331 {
   2332    if (context->getClientMajorVersion() < 3)
   2333    {
   2334        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2335        return false;
   2336    }
   2337 
   2338    return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat,
   2339                                        binary);
   2340 }
   2341 
   2342 bool ValidateProgramParameteriBase(const Context *context,
   2343                                   angle::EntryPoint entryPoint,
   2344                                   ShaderProgramID program,
   2345                                   GLenum pname,
   2346                                   GLint value)
   2347 {
   2348    if (GetValidProgram(context, entryPoint, program) == nullptr)
   2349    {
   2350        return false;
   2351    }
   2352 
   2353    switch (pname)
   2354    {
   2355        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
   2356            if (value != GL_FALSE && value != GL_TRUE)
   2357            {
   2358                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBooleanValue);
   2359                return false;
   2360            }
   2361            break;
   2362 
   2363        case GL_PROGRAM_SEPARABLE:
   2364            if (context->getClientVersion() < ES_3_1)
   2365            {
   2366                context->validationError(entryPoint, GL_INVALID_ENUM, kES31Required);
   2367                return false;
   2368            }
   2369 
   2370            if (value != GL_FALSE && value != GL_TRUE)
   2371            {
   2372                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBooleanValue);
   2373                return false;
   2374            }
   2375            break;
   2376 
   2377        default:
   2378            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   2379            return false;
   2380    }
   2381 
   2382    return true;
   2383 }
   2384 
   2385 bool ValidateProgramParameteri(const Context *context,
   2386                               angle::EntryPoint entryPoint,
   2387                               ShaderProgramID program,
   2388                               GLenum pname,
   2389                               GLint value)
   2390 {
   2391    if (context->getClientMajorVersion() < 3)
   2392    {
   2393        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2394        return false;
   2395    }
   2396 
   2397    return ValidateProgramParameteriBase(context, entryPoint, program, pname, value);
   2398 }
   2399 
   2400 bool ValidateBlitFramebuffer(const Context *context,
   2401                             angle::EntryPoint entryPoint,
   2402                             GLint srcX0,
   2403                             GLint srcY0,
   2404                             GLint srcX1,
   2405                             GLint srcY1,
   2406                             GLint dstX0,
   2407                             GLint dstY0,
   2408                             GLint dstX1,
   2409                             GLint dstY1,
   2410                             GLbitfield mask,
   2411                             GLenum filter)
   2412 {
   2413    if (context->getClientMajorVersion() < 3 && !context->getExtensions().framebufferBlitNV)
   2414    {
   2415        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2416        return false;
   2417    }
   2418 
   2419    return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
   2420                                             dstY0, dstX1, dstY1, mask, filter);
   2421 }
   2422 
   2423 bool ValidateClearBufferiv(const Context *context,
   2424                           angle::EntryPoint entryPoint,
   2425                           GLenum buffer,
   2426                           GLint drawbuffer,
   2427                           const GLint *value)
   2428 {
   2429    switch (buffer)
   2430    {
   2431        case GL_COLOR:
   2432            if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
   2433            {
   2434                context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
   2435                return false;
   2436            }
   2437            if (context->getExtensions().webglCompatibilityANGLE)
   2438            {
   2439                constexpr GLenum validComponentTypes[] = {GL_INT};
   2440                if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
   2441                                                                 validComponentTypes,
   2442                                                                 ArraySize(validComponentTypes)))
   2443                {
   2444                    return false;
   2445                }
   2446            }
   2447            break;
   2448 
   2449        case GL_STENCIL:
   2450            if (drawbuffer != 0)
   2451            {
   2452                context->validationError(entryPoint, GL_INVALID_VALUE,
   2453                                         kInvalidDepthStencilDrawBuffer);
   2454                return false;
   2455            }
   2456            break;
   2457 
   2458        default:
   2459            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
   2460            return false;
   2461    }
   2462 
   2463    return ValidateClearBuffer(context, entryPoint);
   2464 }
   2465 
   2466 bool ValidateClearBufferuiv(const Context *context,
   2467                            angle::EntryPoint entryPoint,
   2468                            GLenum buffer,
   2469                            GLint drawbuffer,
   2470                            const GLuint *value)
   2471 {
   2472    switch (buffer)
   2473    {
   2474        case GL_COLOR:
   2475            if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
   2476            {
   2477                context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
   2478                return false;
   2479            }
   2480            if (context->getExtensions().webglCompatibilityANGLE)
   2481            {
   2482                constexpr GLenum validComponentTypes[] = {GL_UNSIGNED_INT};
   2483                if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
   2484                                                                 validComponentTypes,
   2485                                                                 ArraySize(validComponentTypes)))
   2486                {
   2487                    return false;
   2488                }
   2489            }
   2490            break;
   2491 
   2492        default:
   2493            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
   2494            return false;
   2495    }
   2496 
   2497    return ValidateClearBuffer(context, entryPoint);
   2498 }
   2499 
   2500 bool ValidateClearBufferfv(const Context *context,
   2501                           angle::EntryPoint entryPoint,
   2502                           GLenum buffer,
   2503                           GLint drawbuffer,
   2504                           const GLfloat *value)
   2505 {
   2506    switch (buffer)
   2507    {
   2508        case GL_COLOR:
   2509            if (drawbuffer < 0 || drawbuffer >= context->getCaps().maxDrawBuffers)
   2510            {
   2511                context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
   2512                return false;
   2513            }
   2514            if (context->getExtensions().webglCompatibilityANGLE)
   2515            {
   2516                constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
   2517                                                          GL_SIGNED_NORMALIZED};
   2518                if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawbuffer,
   2519                                                                 validComponentTypes,
   2520                                                                 ArraySize(validComponentTypes)))
   2521                {
   2522                    return false;
   2523                }
   2524            }
   2525            break;
   2526 
   2527        case GL_DEPTH:
   2528            if (drawbuffer != 0)
   2529            {
   2530                context->validationError(entryPoint, GL_INVALID_VALUE,
   2531                                         kInvalidDepthStencilDrawBuffer);
   2532                return false;
   2533            }
   2534            break;
   2535 
   2536        default:
   2537            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
   2538            return false;
   2539    }
   2540 
   2541    return ValidateClearBuffer(context, entryPoint);
   2542 }
   2543 
   2544 bool ValidateClearBufferfi(const Context *context,
   2545                           angle::EntryPoint entryPoint,
   2546                           GLenum buffer,
   2547                           GLint drawbuffer,
   2548                           GLfloat depth,
   2549                           GLint stencil)
   2550 {
   2551    switch (buffer)
   2552    {
   2553        case GL_DEPTH_STENCIL:
   2554            if (drawbuffer != 0)
   2555            {
   2556                context->validationError(entryPoint, GL_INVALID_VALUE,
   2557                                         kInvalidDepthStencilDrawBuffer);
   2558                return false;
   2559            }
   2560            break;
   2561 
   2562        default:
   2563            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, buffer);
   2564            return false;
   2565    }
   2566 
   2567    return ValidateClearBuffer(context, entryPoint);
   2568 }
   2569 
   2570 bool ValidateDrawBuffers(const Context *context,
   2571                         angle::EntryPoint entryPoint,
   2572                         GLsizei n,
   2573                         const GLenum *bufs)
   2574 {
   2575    if (context->getClientMajorVersion() < 3)
   2576    {
   2577        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2578        return false;
   2579    }
   2580 
   2581    return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
   2582 }
   2583 
   2584 bool ValidateCopyTexSubImage3D(const Context *context,
   2585                               angle::EntryPoint entryPoint,
   2586                               TextureTarget target,
   2587                               GLint level,
   2588                               GLint xoffset,
   2589                               GLint yoffset,
   2590                               GLint zoffset,
   2591                               GLint x,
   2592                               GLint y,
   2593                               GLsizei width,
   2594                               GLsizei height)
   2595 {
   2596    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
   2597    {
   2598        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2599        return false;
   2600    }
   2601 
   2602    return ValidateES3CopyTexImage3DParameters(context, entryPoint, target, level, GL_NONE, true,
   2603                                               xoffset, yoffset, zoffset, x, y, width, height, 0);
   2604 }
   2605 
   2606 bool ValidateCopyTexture3DANGLE(const Context *context,
   2607                                angle::EntryPoint entryPoint,
   2608                                TextureID sourceId,
   2609                                GLint sourceLevel,
   2610                                TextureTarget destTarget,
   2611                                TextureID destId,
   2612                                GLint destLevel,
   2613                                GLint internalFormat,
   2614                                GLenum destType,
   2615                                GLboolean unpackFlipY,
   2616                                GLboolean unpackPremultiplyAlpha,
   2617                                GLboolean unpackUnmultiplyAlpha)
   2618 {
   2619    const Texture *source = context->getTexture(sourceId);
   2620    if (source == nullptr)
   2621    {
   2622        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
   2623        return false;
   2624    }
   2625 
   2626    TextureType sourceType = source->getType();
   2627    ASSERT(sourceType != TextureType::CubeMap);
   2628    TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
   2629    const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
   2630 
   2631    const Texture *dest = context->getTexture(destId);
   2632    if (dest == nullptr)
   2633    {
   2634        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
   2635        return false;
   2636    }
   2637 
   2638    if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
   2639                                     sourceFormat.info->internalFormat, dest, destLevel,
   2640                                     internalFormat, destTarget))
   2641    {
   2642        return false;
   2643    }
   2644 
   2645    if (!ValidMipLevel(context, source->getType(), sourceLevel))
   2646    {
   2647        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel);
   2648        return false;
   2649    }
   2650 
   2651    GLsizei sourceWidth  = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
   2652    GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
   2653    if (sourceWidth == 0 || sourceHeight == 0)
   2654    {
   2655        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSourceTextureSize);
   2656        return false;
   2657    }
   2658 
   2659    if (dest->getImmutableFormat())
   2660    {
   2661        context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable);
   2662        return false;
   2663    }
   2664 
   2665    return true;
   2666 }
   2667 
   2668 bool ValidateCopySubTexture3DANGLE(const Context *context,
   2669                                   angle::EntryPoint entryPoint,
   2670                                   TextureID sourceId,
   2671                                   GLint sourceLevel,
   2672                                   TextureTarget destTarget,
   2673                                   TextureID destId,
   2674                                   GLint destLevel,
   2675                                   GLint xoffset,
   2676                                   GLint yoffset,
   2677                                   GLint zoffset,
   2678                                   GLint x,
   2679                                   GLint y,
   2680                                   GLint z,
   2681                                   GLsizei width,
   2682                                   GLsizei height,
   2683                                   GLsizei depth,
   2684                                   GLboolean unpackFlipY,
   2685                                   GLboolean unpackPremultiplyAlpha,
   2686                                   GLboolean unpackUnmultiplyAlpha)
   2687 {
   2688    const Texture *source = context->getTexture(sourceId);
   2689    if (source == nullptr)
   2690    {
   2691        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
   2692        return false;
   2693    }
   2694 
   2695    TextureType sourceType = source->getType();
   2696    ASSERT(sourceType != TextureType::CubeMap);
   2697    TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
   2698    const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
   2699 
   2700    const Texture *dest = context->getTexture(destId);
   2701    if (dest == nullptr)
   2702    {
   2703        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
   2704        return false;
   2705    }
   2706 
   2707    const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
   2708 
   2709    if (!ValidateCopyTexture3DCommon(context, entryPoint, source, sourceLevel,
   2710                                     sourceFormat.info->internalFormat, dest, destLevel,
   2711                                     destFormat.internalFormat, destTarget))
   2712    {
   2713        return false;
   2714    }
   2715 
   2716    if (x < 0 || y < 0 || z < 0)
   2717    {
   2718        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeXYZ);
   2719        return false;
   2720    }
   2721 
   2722    if (width < 0 || height < 0 || depth < 0)
   2723    {
   2724        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeHeightWidthDepth);
   2725        return false;
   2726    }
   2727 
   2728    if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
   2729        static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel) ||
   2730        static_cast<size_t>(z + depth) > source->getDepth(sourceTarget, sourceLevel))
   2731    {
   2732        context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
   2733        return false;
   2734    }
   2735 
   2736    if (TextureTargetToType(destTarget) != dest->getType())
   2737    {
   2738        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
   2739        return false;
   2740    }
   2741 
   2742    if (xoffset < 0 || yoffset < 0 || zoffset < 0)
   2743    {
   2744        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   2745        return false;
   2746    }
   2747 
   2748    if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
   2749        static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel) ||
   2750        static_cast<size_t>(zoffset + depth) > dest->getDepth(destTarget, destLevel))
   2751    {
   2752        context->validationError(entryPoint, GL_INVALID_VALUE, kDestinationTextureTooSmall);
   2753        return false;
   2754    }
   2755 
   2756    return true;
   2757 }
   2758 
   2759 bool ValidateTexImage3D(const Context *context,
   2760                        angle::EntryPoint entryPoint,
   2761                        TextureTarget target,
   2762                        GLint level,
   2763                        GLint internalformat,
   2764                        GLsizei width,
   2765                        GLsizei height,
   2766                        GLsizei depth,
   2767                        GLint border,
   2768                        GLenum format,
   2769                        GLenum type,
   2770                        const void *pixels)
   2771 {
   2772    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
   2773    {
   2774        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2775        return false;
   2776    }
   2777 
   2778    return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
   2779                                           false, false, 0, 0, 0, width, height, depth, border,
   2780                                           format, type, -1, pixels);
   2781 }
   2782 
   2783 bool ValidateTexImage3DRobustANGLE(const Context *context,
   2784                                   angle::EntryPoint entryPoint,
   2785                                   TextureTarget target,
   2786                                   GLint level,
   2787                                   GLint internalformat,
   2788                                   GLsizei width,
   2789                                   GLsizei height,
   2790                                   GLsizei depth,
   2791                                   GLint border,
   2792                                   GLenum format,
   2793                                   GLenum type,
   2794                                   GLsizei bufSize,
   2795                                   const void *pixels)
   2796 {
   2797    if (context->getClientMajorVersion() < 3)
   2798    {
   2799        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2800        return false;
   2801    }
   2802 
   2803    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2804    {
   2805        return false;
   2806    }
   2807 
   2808    return ValidateES3TexImage3DParameters(context, entryPoint, target, level, internalformat,
   2809                                           false, false, 0, 0, 0, width, height, depth, border,
   2810                                           format, type, bufSize, pixels);
   2811 }
   2812 
   2813 bool ValidateTexSubImage3D(const Context *context,
   2814                           angle::EntryPoint entryPoint,
   2815                           TextureTarget target,
   2816                           GLint level,
   2817                           GLint xoffset,
   2818                           GLint yoffset,
   2819                           GLint zoffset,
   2820                           GLsizei width,
   2821                           GLsizei height,
   2822                           GLsizei depth,
   2823                           GLenum format,
   2824                           GLenum type,
   2825                           const void *pixels)
   2826 {
   2827    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
   2828    {
   2829        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2830        return false;
   2831    }
   2832 
   2833    return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
   2834                                           xoffset, yoffset, zoffset, width, height, depth, 0,
   2835                                           format, type, -1, pixels);
   2836 }
   2837 
   2838 bool ValidateTexSubImage3DRobustANGLE(const Context *context,
   2839                                      angle::EntryPoint entryPoint,
   2840                                      TextureTarget target,
   2841                                      GLint level,
   2842                                      GLint xoffset,
   2843                                      GLint yoffset,
   2844                                      GLint zoffset,
   2845                                      GLsizei width,
   2846                                      GLsizei height,
   2847                                      GLsizei depth,
   2848                                      GLenum format,
   2849                                      GLenum type,
   2850                                      GLsizei bufSize,
   2851                                      const void *pixels)
   2852 {
   2853    if (context->getClientMajorVersion() < 3)
   2854    {
   2855        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2856        return false;
   2857    }
   2858 
   2859    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2860    {
   2861        return false;
   2862    }
   2863 
   2864    return ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, false, true,
   2865                                           xoffset, yoffset, zoffset, width, height, depth, 0,
   2866                                           format, type, bufSize, pixels);
   2867 }
   2868 
   2869 bool ValidateCompressedTexSubImage3D(const Context *context,
   2870                                     angle::EntryPoint entryPoint,
   2871                                     TextureTarget target,
   2872                                     GLint level,
   2873                                     GLint xoffset,
   2874                                     GLint yoffset,
   2875                                     GLint zoffset,
   2876                                     GLsizei width,
   2877                                     GLsizei height,
   2878                                     GLsizei depth,
   2879                                     GLenum format,
   2880                                     GLsizei imageSize,
   2881                                     const void *data)
   2882 {
   2883    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().texture3DOES)
   2884    {
   2885        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   2886        return false;
   2887    }
   2888 
   2889    if (!ValidateES3TexImage3DParameters(context, entryPoint, target, level, GL_NONE, true, true,
   2890                                         xoffset, yoffset, zoffset, width, height, depth, 0, format,
   2891                                         GL_NONE, -1, data))
   2892    {
   2893        return false;
   2894    }
   2895 
   2896    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
   2897 
   2898    if (!formatInfo.compressed)
   2899    {
   2900        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCompressedFormat);
   2901        return false;
   2902    }
   2903 
   2904    GLuint blockSize = 0;
   2905    if (!formatInfo.computeCompressedImageSize(Extents(width, height, depth), &blockSize))
   2906    {
   2907        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   2908        return false;
   2909    }
   2910 
   2911    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
   2912    {
   2913        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize);
   2914        return false;
   2915    }
   2916 
   2917    if (data == nullptr)
   2918    {
   2919        if (context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
   2920        {
   2921            // If data is null, we need an unpack buffer to read from
   2922            context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull);
   2923            return false;
   2924        }
   2925 
   2926        if (context->getTextureByTarget(target)->isCompressedFormatEmulated(context, target, level))
   2927        {
   2928            // TODO (anglebug.com/7464): Can't populate from a buffer using emulated format
   2929            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEmulatedFormat);
   2930            return false;
   2931        }
   2932    }
   2933 
   2934    return true;
   2935 }
   2936 
   2937 bool ValidateCompressedTexSubImage3DRobustANGLE(const Context *context,
   2938                                                angle::EntryPoint entryPoint,
   2939                                                TextureTarget target,
   2940                                                GLint level,
   2941                                                GLint xoffset,
   2942                                                GLint yoffset,
   2943                                                GLint zoffset,
   2944                                                GLsizei width,
   2945                                                GLsizei height,
   2946                                                GLsizei depth,
   2947                                                GLenum format,
   2948                                                GLsizei imageSize,
   2949                                                GLsizei dataSize,
   2950                                                const void *data)
   2951 {
   2952    if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
   2953    {
   2954        return false;
   2955    }
   2956 
   2957    return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
   2958                                           zoffset, width, height, depth, format, imageSize, data);
   2959 }
   2960 
   2961 bool ValidateGenQueries(const Context *context,
   2962                        angle::EntryPoint entryPoint,
   2963                        GLsizei n,
   2964                        const QueryID *queries)
   2965 {
   2966    return ValidateGenOrDeleteES3(context, entryPoint, n);
   2967 }
   2968 
   2969 bool ValidateDeleteQueries(const Context *context,
   2970                           angle::EntryPoint entryPoint,
   2971                           GLsizei n,
   2972                           const QueryID *queries)
   2973 {
   2974    return ValidateGenOrDeleteES3(context, entryPoint, n);
   2975 }
   2976 
   2977 bool ValidateGenSamplers(const Context *context,
   2978                         angle::EntryPoint entryPoint,
   2979                         GLsizei count,
   2980                         const SamplerID *samplers)
   2981 {
   2982    return ValidateGenOrDeleteCountES3(context, entryPoint, count);
   2983 }
   2984 
   2985 bool ValidateDeleteSamplers(const Context *context,
   2986                            angle::EntryPoint entryPoint,
   2987                            GLsizei count,
   2988                            const SamplerID *samplers)
   2989 {
   2990    return ValidateGenOrDeleteCountES3(context, entryPoint, count);
   2991 }
   2992 
   2993 bool ValidateGenTransformFeedbacks(const Context *context,
   2994                                   angle::EntryPoint entryPoint,
   2995                                   GLsizei n,
   2996                                   const TransformFeedbackID *ids)
   2997 {
   2998    return ValidateGenOrDeleteES3(context, entryPoint, n);
   2999 }
   3000 
   3001 bool ValidateDeleteTransformFeedbacks(const Context *context,
   3002                                      angle::EntryPoint entryPoint,
   3003                                      GLsizei n,
   3004                                      const TransformFeedbackID *ids)
   3005 {
   3006    if (!ValidateGenOrDeleteES3(context, entryPoint, n))
   3007    {
   3008        return false;
   3009    }
   3010    for (GLint i = 0; i < n; ++i)
   3011    {
   3012        auto *transformFeedback = context->getTransformFeedback(ids[i]);
   3013        if (transformFeedback != nullptr && transformFeedback->isActive())
   3014        {
   3015            // ES 3.0.4 section 2.15.1 page 86
   3016            context->validationError(entryPoint, GL_INVALID_OPERATION,
   3017                                     kTransformFeedbackActiveDelete);
   3018            return false;
   3019        }
   3020    }
   3021    return true;
   3022 }
   3023 
   3024 bool ValidateGenVertexArrays(const Context *context,
   3025                             angle::EntryPoint entryPoint,
   3026                             GLsizei n,
   3027                             const VertexArrayID *arrays)
   3028 {
   3029    return ValidateGenOrDeleteES3(context, entryPoint, n);
   3030 }
   3031 
   3032 bool ValidateDeleteVertexArrays(const Context *context,
   3033                                angle::EntryPoint entryPoint,
   3034                                GLsizei n,
   3035                                const VertexArrayID *arrays)
   3036 {
   3037    return ValidateGenOrDeleteES3(context, entryPoint, n);
   3038 }
   3039 
   3040 bool ValidateBeginTransformFeedback(const Context *context,
   3041                                    angle::EntryPoint entryPoint,
   3042                                    PrimitiveMode primitiveMode)
   3043 {
   3044    if (context->getClientMajorVersion() < 3)
   3045    {
   3046        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3047        return false;
   3048    }
   3049    switch (primitiveMode)
   3050    {
   3051        case PrimitiveMode::Triangles:
   3052        case PrimitiveMode::Lines:
   3053        case PrimitiveMode::Points:
   3054            break;
   3055 
   3056        default:
   3057            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPrimitiveMode);
   3058            return false;
   3059    }
   3060 
   3061    TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
   3062    ASSERT(transformFeedback != nullptr);
   3063 
   3064    if (transformFeedback->isActive())
   3065    {
   3066        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransfomFeedbackAlreadyActive);
   3067        return false;
   3068    }
   3069 
   3070    for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
   3071    {
   3072        const OffsetBindingPointer<Buffer> &buffer = transformFeedback->getIndexedBuffer(i);
   3073        if (buffer.get())
   3074        {
   3075            if (buffer->isMapped())
   3076            {
   3077                context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
   3078                return false;
   3079            }
   3080            if ((context->getLimitations().noDoubleBoundTransformFeedbackBuffers ||
   3081                 context->getExtensions().webglCompatibilityANGLE) &&
   3082                buffer->isDoubleBoundForTransformFeedback())
   3083            {
   3084                context->validationError(entryPoint, GL_INVALID_OPERATION,
   3085                                         kTransformFeedbackBufferMultipleOutputs);
   3086                return false;
   3087            }
   3088        }
   3089    }
   3090 
   3091    const ProgramExecutable *programExecutable =
   3092        context->getState().getLinkedProgramExecutable(context);
   3093    if (!programExecutable)
   3094    {
   3095        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotBound);
   3096        return false;
   3097    }
   3098 
   3099    if (programExecutable->getLinkedTransformFeedbackVaryings().empty())
   3100    {
   3101        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3102                                 kNoTransformFeedbackOutputVariables);
   3103        return false;
   3104    }
   3105 
   3106    if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
   3107    {
   3108        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
   3109        return false;
   3110    }
   3111 
   3112    return true;
   3113 }
   3114 
   3115 bool ValidateGetBufferPointerv(const Context *context,
   3116                               angle::EntryPoint entryPoint,
   3117                               BufferBinding target,
   3118                               GLenum pname,
   3119                               void *const *params)
   3120 {
   3121    if (context->getClientMajorVersion() < 3)
   3122    {
   3123        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3124        return false;
   3125    }
   3126 
   3127    return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
   3128 }
   3129 
   3130 bool ValidateGetBufferPointervRobustANGLE(const Context *context,
   3131                                          angle::EntryPoint entryPoint,
   3132                                          BufferBinding target,
   3133                                          GLenum pname,
   3134                                          GLsizei bufSize,
   3135                                          const GLsizei *length,
   3136                                          void *const *params)
   3137 {
   3138    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   3139    {
   3140        return false;
   3141    }
   3142 
   3143    GLsizei numParams = 0;
   3144 
   3145    if (context->getClientMajorVersion() < 3 && !context->getExtensions().mapbufferOES)
   3146    {
   3147        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3148        return false;
   3149    }
   3150 
   3151    if (!ValidateGetBufferPointervBase(context, entryPoint, target, pname, &numParams, params))
   3152    {
   3153        return false;
   3154    }
   3155 
   3156    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   3157    {
   3158        return false;
   3159    }
   3160 
   3161    SetRobustLengthParam(length, numParams);
   3162 
   3163    return true;
   3164 }
   3165 
   3166 bool ValidateUnmapBuffer(const Context *context, angle::EntryPoint entryPoint, BufferBinding target)
   3167 {
   3168    if (context->getClientMajorVersion() < 3)
   3169    {
   3170        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3171        return false;
   3172    }
   3173 
   3174    return ValidateUnmapBufferBase(context, entryPoint, target);
   3175 }
   3176 
   3177 bool ValidateMapBufferRange(const Context *context,
   3178                            angle::EntryPoint entryPoint,
   3179                            BufferBinding target,
   3180                            GLintptr offset,
   3181                            GLsizeiptr length,
   3182                            GLbitfield access)
   3183 {
   3184    if (context->getClientMajorVersion() < 3)
   3185    {
   3186        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3187        return false;
   3188    }
   3189 
   3190    return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
   3191 }
   3192 
   3193 bool ValidateFlushMappedBufferRange(const Context *context,
   3194                                    angle::EntryPoint entryPoint,
   3195                                    BufferBinding target,
   3196                                    GLintptr offset,
   3197                                    GLsizeiptr length)
   3198 {
   3199    if (context->getClientMajorVersion() < 3)
   3200    {
   3201        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3202        return false;
   3203    }
   3204 
   3205    return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
   3206 }
   3207 
   3208 bool ValidateIndexedStateQuery(const Context *context,
   3209                               angle::EntryPoint entryPoint,
   3210                               GLenum pname,
   3211                               GLuint index,
   3212                               GLsizei *length)
   3213 {
   3214    if (length)
   3215    {
   3216        *length = 0;
   3217    }
   3218 
   3219    GLenum nativeType;
   3220    unsigned int numParams;
   3221    if (!context->getIndexedQueryParameterInfo(pname, &nativeType, &numParams))
   3222    {
   3223        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   3224        return false;
   3225    }
   3226 
   3227    const Caps &caps = context->getCaps();
   3228    switch (pname)
   3229    {
   3230        case GL_BLEND_SRC_RGB:
   3231        case GL_BLEND_SRC_ALPHA:
   3232        case GL_BLEND_DST_RGB:
   3233        case GL_BLEND_DST_ALPHA:
   3234        case GL_BLEND_EQUATION_RGB:
   3235        case GL_BLEND_EQUATION_ALPHA:
   3236        case GL_COLOR_WRITEMASK:
   3237            if (!context->getExtensions().drawBuffersIndexedAny())
   3238            {
   3239                context->validationError(entryPoint, GL_INVALID_ENUM,
   3240                                         kDrawBuffersIndexedExtensionNotAvailable);
   3241                return false;
   3242            }
   3243            if (index >= static_cast<GLuint>(caps.maxDrawBuffers))
   3244            {
   3245                context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
   3246                return false;
   3247            }
   3248            break;
   3249        case GL_TRANSFORM_FEEDBACK_BUFFER_START:
   3250        case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
   3251        case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
   3252            if (index >= static_cast<GLuint>(caps.maxTransformFeedbackSeparateAttributes))
   3253            {
   3254                context->validationError(entryPoint, GL_INVALID_VALUE,
   3255                                         kIndexExceedsMaxTransformFeedbackAttribs);
   3256                return false;
   3257            }
   3258            break;
   3259 
   3260        case GL_UNIFORM_BUFFER_START:
   3261        case GL_UNIFORM_BUFFER_SIZE:
   3262        case GL_UNIFORM_BUFFER_BINDING:
   3263            if (index >= static_cast<GLuint>(caps.maxUniformBufferBindings))
   3264            {
   3265                context->validationError(entryPoint, GL_INVALID_VALUE,
   3266                                         kIndexExceedsMaxUniformBufferBindings);
   3267                return false;
   3268            }
   3269            break;
   3270 
   3271        case GL_MAX_COMPUTE_WORK_GROUP_SIZE:
   3272        case GL_MAX_COMPUTE_WORK_GROUP_COUNT:
   3273            if (index >= 3u)
   3274            {
   3275                context->validationError(entryPoint, GL_INVALID_VALUE,
   3276                                         kIndexExceedsMaxWorkgroupDimensions);
   3277                return false;
   3278            }
   3279            break;
   3280 
   3281        case GL_ATOMIC_COUNTER_BUFFER_START:
   3282        case GL_ATOMIC_COUNTER_BUFFER_SIZE:
   3283        case GL_ATOMIC_COUNTER_BUFFER_BINDING:
   3284            if (context->getClientVersion() < ES_3_1)
   3285            {
   3286                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   3287                return false;
   3288            }
   3289            if (index >= static_cast<GLuint>(caps.maxAtomicCounterBufferBindings))
   3290            {
   3291                context->validationError(entryPoint, GL_INVALID_VALUE,
   3292                                         kIndexExceedsMaxAtomicCounterBufferBindings);
   3293                return false;
   3294            }
   3295            break;
   3296 
   3297        case GL_SHADER_STORAGE_BUFFER_START:
   3298        case GL_SHADER_STORAGE_BUFFER_SIZE:
   3299        case GL_SHADER_STORAGE_BUFFER_BINDING:
   3300            if (context->getClientVersion() < ES_3_1)
   3301            {
   3302                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   3303                return false;
   3304            }
   3305            if (index >= static_cast<GLuint>(caps.maxShaderStorageBufferBindings))
   3306            {
   3307                context->validationError(entryPoint, GL_INVALID_VALUE,
   3308                                         kExceedsMaxShaderStorageBufferBindings);
   3309                return false;
   3310            }
   3311            break;
   3312 
   3313        case GL_VERTEX_BINDING_BUFFER:
   3314        case GL_VERTEX_BINDING_DIVISOR:
   3315        case GL_VERTEX_BINDING_OFFSET:
   3316        case GL_VERTEX_BINDING_STRIDE:
   3317            if (context->getClientVersion() < ES_3_1)
   3318            {
   3319                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   3320                return false;
   3321            }
   3322            if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
   3323            {
   3324                context->validationError(entryPoint, GL_INVALID_VALUE,
   3325                                         kExceedsMaxVertexAttribBindings);
   3326                return false;
   3327            }
   3328            break;
   3329        case GL_SAMPLE_MASK_VALUE:
   3330            if (context->getClientVersion() < ES_3_1)
   3331            {
   3332                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   3333                return false;
   3334            }
   3335            if (index >= static_cast<GLuint>(caps.maxSampleMaskWords))
   3336            {
   3337                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
   3338                return false;
   3339            }
   3340            break;
   3341        case GL_IMAGE_BINDING_NAME:
   3342        case GL_IMAGE_BINDING_LEVEL:
   3343        case GL_IMAGE_BINDING_LAYERED:
   3344        case GL_IMAGE_BINDING_LAYER:
   3345        case GL_IMAGE_BINDING_ACCESS:
   3346        case GL_IMAGE_BINDING_FORMAT:
   3347            if (context->getClientVersion() < ES_3_1)
   3348            {
   3349                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   3350                return false;
   3351            }
   3352            if (index >= static_cast<GLuint>(caps.maxImageUnits))
   3353            {
   3354                context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxImageUnits);
   3355                return false;
   3356            }
   3357            break;
   3358        // GL_ANGLE_shader_pixel_local_storage
   3359        case GL_PIXEL_LOCAL_FORMAT_ANGLE:
   3360        case GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE:
   3361        case GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE:
   3362        case GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE:
   3363        {
   3364            // Check that the pixel local storage extension is enabled at all.
   3365            if (!context->getExtensions().shaderPixelLocalStorageANGLE)
   3366            {
   3367                context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSExtensionNotEnabled);
   3368                return false;
   3369            }
   3370            // INVALID_FRAMEBUFFER_OPERATION is generated if the default framebuffer object name 0
   3371            // is bound to DRAW_FRAMEBUFFER.
   3372            Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
   3373            if (framebuffer->id().value == 0)
   3374            {
   3375                context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
   3376                                         kPLSDefaultFramebufferBound);
   3377                return false;
   3378            }
   3379            // INVALID_VALUE is generated if <index> >= MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE.
   3380            if (index >= context->getCaps().maxPixelLocalStoragePlanes)
   3381            {
   3382                context->validationError(entryPoint, GL_INVALID_OPERATION, kPLSPlaneOutOfRange);
   3383                return false;
   3384            }
   3385            break;
   3386        }
   3387        default:
   3388            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   3389            return false;
   3390    }
   3391 
   3392    if (length)
   3393    {
   3394        if (pname == GL_COLOR_WRITEMASK)
   3395        {
   3396            *length = 4;
   3397        }
   3398        else
   3399        {
   3400            *length = 1;
   3401        }
   3402    }
   3403 
   3404    return true;
   3405 }
   3406 
   3407 bool ValidateGetIntegeri_v(const Context *context,
   3408                           angle::EntryPoint entryPoint,
   3409                           GLenum target,
   3410                           GLuint index,
   3411                           const GLint *data)
   3412 {
   3413    if (context->getClientVersion() < ES_3_0)
   3414    {
   3415        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3416        return false;
   3417    }
   3418    return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
   3419 }
   3420 
   3421 bool ValidateGetIntegeri_vRobustANGLE(const Context *context,
   3422                                      angle::EntryPoint entryPoint,
   3423                                      GLenum target,
   3424                                      GLuint index,
   3425                                      GLsizei bufSize,
   3426                                      const GLsizei *length,
   3427                                      const GLint *data)
   3428 {
   3429    if (context->getClientVersion() < ES_3_0)
   3430    {
   3431        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3432        return false;
   3433    }
   3434 
   3435    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   3436    {
   3437        return false;
   3438    }
   3439 
   3440    GLsizei numParams = 0;
   3441 
   3442    if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
   3443    {
   3444        return false;
   3445    }
   3446 
   3447    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   3448    {
   3449        return false;
   3450    }
   3451 
   3452    SetRobustLengthParam(length, numParams);
   3453 
   3454    return true;
   3455 }
   3456 
   3457 bool ValidateGetInteger64i_v(const Context *context,
   3458                             angle::EntryPoint entryPoint,
   3459                             GLenum target,
   3460                             GLuint index,
   3461                             const GLint64 *data)
   3462 {
   3463    if (context->getClientVersion() < ES_3_0)
   3464    {
   3465        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3466        return false;
   3467    }
   3468    return ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr);
   3469 }
   3470 
   3471 bool ValidateGetInteger64i_vRobustANGLE(const Context *context,
   3472                                        angle::EntryPoint entryPoint,
   3473                                        GLenum target,
   3474                                        GLuint index,
   3475                                        GLsizei bufSize,
   3476                                        const GLsizei *length,
   3477                                        const GLint64 *data)
   3478 {
   3479    if (context->getClientVersion() < ES_3_0)
   3480    {
   3481        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3482        return false;
   3483    }
   3484 
   3485    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   3486    {
   3487        return false;
   3488    }
   3489 
   3490    GLsizei numParams = 0;
   3491 
   3492    if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
   3493    {
   3494        return false;
   3495    }
   3496 
   3497    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   3498    {
   3499        return false;
   3500    }
   3501 
   3502    SetRobustLengthParam(length, numParams);
   3503 
   3504    return true;
   3505 }
   3506 
   3507 bool ValidateCopyBufferSubData(const Context *context,
   3508                               angle::EntryPoint entryPoint,
   3509                               BufferBinding readTarget,
   3510                               BufferBinding writeTarget,
   3511                               GLintptr readOffset,
   3512                               GLintptr writeOffset,
   3513                               GLsizeiptr size)
   3514 {
   3515    if (context->getClientMajorVersion() < 3)
   3516    {
   3517        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3518        return false;
   3519    }
   3520 
   3521    if (!context->isValidBufferBinding(readTarget) || !context->isValidBufferBinding(writeTarget))
   3522    {
   3523        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   3524        return false;
   3525    }
   3526 
   3527    Buffer *readBuffer  = context->getState().getTargetBuffer(readTarget);
   3528    Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
   3529 
   3530    if (!readBuffer || !writeBuffer)
   3531    {
   3532        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
   3533        return false;
   3534    }
   3535 
   3536    // EXT_buffer_storage allows persistently mapped buffers to be updated via glCopyBufferSubData
   3537    bool isReadPersistent  = (readBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
   3538    bool isWritePersistent = (writeBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
   3539 
   3540    // Verify that readBuffer and writeBuffer are not currently mapped unless persistent
   3541    if ((readBuffer->isMapped() && !isReadPersistent) ||
   3542        (writeBuffer->isMapped() && !isWritePersistent))
   3543    {
   3544        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
   3545        return false;
   3546    }
   3547 
   3548    if (readBuffer->hasWebGLXFBBindingConflict(context->isWebGL()) ||
   3549        writeBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   3550    {
   3551        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3552                                 kBufferBoundForTransformFeedback);
   3553        return false;
   3554    }
   3555 
   3556    CheckedNumeric<GLintptr> checkedReadOffset(readOffset);
   3557    CheckedNumeric<GLintptr> checkedWriteOffset(writeOffset);
   3558    CheckedNumeric<GLintptr> checkedSize(size);
   3559 
   3560    auto checkedReadSum  = checkedReadOffset + checkedSize;
   3561    auto checkedWriteSum = checkedWriteOffset + checkedSize;
   3562 
   3563    if (!checkedReadSum.IsValid() || !checkedWriteSum.IsValid() ||
   3564        !IsValueInRangeForNumericType<GLintptr>(readBuffer->getSize()) ||
   3565        !IsValueInRangeForNumericType<GLintptr>(writeBuffer->getSize()))
   3566    {
   3567        context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
   3568        return false;
   3569    }
   3570 
   3571    if (readOffset < 0 || writeOffset < 0)
   3572    {
   3573        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   3574        return false;
   3575    }
   3576 
   3577    if (size < 0)
   3578    {
   3579        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   3580        return false;
   3581    }
   3582 
   3583    if (checkedReadSum.ValueOrDie() > readBuffer->getSize() ||
   3584        checkedWriteSum.ValueOrDie() > writeBuffer->getSize())
   3585    {
   3586        context->validationError(entryPoint, GL_INVALID_VALUE, kBufferOffsetOverflow);
   3587        return false;
   3588    }
   3589 
   3590    if (readBuffer == writeBuffer)
   3591    {
   3592        auto checkedOffsetDiff = (checkedReadOffset - checkedWriteOffset).Abs();
   3593        if (!checkedOffsetDiff.IsValid())
   3594        {
   3595            // This shold not be possible.
   3596            UNREACHABLE();
   3597            context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
   3598            return false;
   3599        }
   3600 
   3601        if (checkedOffsetDiff.ValueOrDie() < size)
   3602        {
   3603            context->validationError(entryPoint, GL_INVALID_VALUE, kCopyAlias);
   3604            return false;
   3605        }
   3606    }
   3607 
   3608    return true;
   3609 }
   3610 
   3611 bool ValidateGetStringi(const Context *context,
   3612                        angle::EntryPoint entryPoint,
   3613                        GLenum name,
   3614                        GLuint index)
   3615 {
   3616    if (context->getClientMajorVersion() < 3)
   3617    {
   3618        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3619        return false;
   3620    }
   3621 
   3622    switch (name)
   3623    {
   3624        case GL_EXTENSIONS:
   3625            if (index >= context->getExtensionStringCount())
   3626            {
   3627                context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsNumExtensions);
   3628                return false;
   3629            }
   3630            break;
   3631 
   3632        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
   3633            if (!context->getExtensions().requestExtensionANGLE)
   3634            {
   3635                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
   3636                return false;
   3637            }
   3638            if (index >= context->getRequestableExtensionStringCount())
   3639            {
   3640                context->validationError(entryPoint, GL_INVALID_VALUE,
   3641                                         kExceedsNumRequestableExtensions);
   3642                return false;
   3643            }
   3644            break;
   3645 
   3646        default:
   3647            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
   3648            return false;
   3649    }
   3650 
   3651    return true;
   3652 }
   3653 
   3654 bool ValidateRenderbufferStorageMultisample(const Context *context,
   3655                                            angle::EntryPoint entryPoint,
   3656                                            GLenum target,
   3657                                            GLsizei samples,
   3658                                            GLenum internalformat,
   3659                                            GLsizei width,
   3660                                            GLsizei height)
   3661 {
   3662    if (context->getClientMajorVersion() < 3)
   3663    {
   3664        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3665        return false;
   3666    }
   3667 
   3668    if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
   3669                                                   internalformat, width, height))
   3670    {
   3671        return false;
   3672    }
   3673 
   3674    // The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer
   3675    // format if samples is greater than zero. In ES3.1(section 9.2.5), it can support integer
   3676    // multisample renderbuffer, but the samples should not be greater than MAX_INTEGER_SAMPLES.
   3677    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
   3678    if (formatInfo.isInt())
   3679    {
   3680        if ((samples > 0 && context->getClientVersion() == ES_3_0) ||
   3681            samples > context->getCaps().maxIntegerSamples)
   3682        {
   3683            context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
   3684            return false;
   3685        }
   3686    }
   3687 
   3688    // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
   3689    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
   3690    if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
   3691    {
   3692        context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
   3693        return false;
   3694    }
   3695 
   3696    return true;
   3697 }
   3698 
   3699 bool ValidateVertexAttribIPointer(const Context *context,
   3700                                  angle::EntryPoint entryPoint,
   3701                                  GLuint index,
   3702                                  GLint size,
   3703                                  VertexAttribType type,
   3704                                  GLsizei stride,
   3705                                  const void *pointer)
   3706 {
   3707    if (context->getClientMajorVersion() < 3)
   3708    {
   3709        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3710        return false;
   3711    }
   3712 
   3713    if (!ValidateIntegerVertexFormat(context, entryPoint, index, size, type))
   3714    {
   3715        return false;
   3716    }
   3717 
   3718    if (stride < 0)
   3719    {
   3720        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeStride);
   3721        return false;
   3722    }
   3723 
   3724    const Caps &caps = context->getCaps();
   3725    if (context->getClientVersion() >= ES_3_1)
   3726    {
   3727        if (stride > caps.maxVertexAttribStride)
   3728        {
   3729            context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
   3730            return false;
   3731        }
   3732 
   3733        // [OpenGL ES 3.1] Section 10.3.1 page 245:
   3734        // glVertexAttribBinding is part of the equivalent code of VertexAttribIPointer, so its
   3735        // validation should be inherited.
   3736        if (index >= static_cast<GLuint>(caps.maxVertexAttribBindings))
   3737        {
   3738            context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
   3739            return false;
   3740        }
   3741    }
   3742 
   3743    // [OpenGL ES 3.0.2] Section 2.8 page 24:
   3744    // An INVALID_OPERATION error is generated when a non-zero vertex array object
   3745    // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
   3746    // and the pointer argument is not NULL.
   3747    if (context->getState().getVertexArrayId().value != 0 &&
   3748        context->getState().getTargetBuffer(BufferBinding::Array) == 0 && pointer != nullptr)
   3749    {
   3750        context->validationError(entryPoint, GL_INVALID_OPERATION, kClientDataInVertexArray);
   3751        return false;
   3752    }
   3753 
   3754    if (context->getExtensions().webglCompatibilityANGLE)
   3755    {
   3756        if (!ValidateWebGLVertexAttribPointer(context, entryPoint, type, false, stride, pointer,
   3757                                              true))
   3758        {
   3759            return false;
   3760        }
   3761    }
   3762 
   3763    return true;
   3764 }
   3765 
   3766 bool ValidateGetSynciv(const Context *context,
   3767                       angle::EntryPoint entryPoint,
   3768                       GLsync sync,
   3769                       GLenum pname,
   3770                       GLsizei bufSize,
   3771                       const GLsizei *length,
   3772                       const GLint *values)
   3773 {
   3774    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   3775    {
   3776        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3777        return false;
   3778    }
   3779 
   3780    if (bufSize < 0)
   3781    {
   3782        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   3783        return false;
   3784    }
   3785 
   3786    if (context->isContextLost())
   3787    {
   3788        context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
   3789 
   3790        if (pname == GL_SYNC_STATUS)
   3791        {
   3792            // Generate an error but still return true, the context still needs to return a
   3793            // value in this case.
   3794            return true;
   3795        }
   3796        else
   3797        {
   3798            return false;
   3799        }
   3800    }
   3801 
   3802    Sync *syncObject = context->getSync(sync);
   3803    if (!syncObject)
   3804    {
   3805        context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
   3806        return false;
   3807    }
   3808 
   3809    switch (pname)
   3810    {
   3811        case GL_OBJECT_TYPE:
   3812        case GL_SYNC_CONDITION:
   3813        case GL_SYNC_FLAGS:
   3814        case GL_SYNC_STATUS:
   3815            break;
   3816 
   3817        default:
   3818            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   3819            return false;
   3820    }
   3821 
   3822    return true;
   3823 }
   3824 
   3825 bool ValidateDrawElementsInstanced(const Context *context,
   3826                                   angle::EntryPoint entryPoint,
   3827                                   PrimitiveMode mode,
   3828                                   GLsizei count,
   3829                                   DrawElementsType type,
   3830                                   const void *indices,
   3831                                   GLsizei instanceCount)
   3832 {
   3833    if (context->getClientMajorVersion() < 3)
   3834    {
   3835        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   3836        return false;
   3837    }
   3838 
   3839    return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
   3840                                             instanceCount);
   3841 }
   3842 
   3843 bool ValidateMultiDrawArraysInstancedANGLE(const Context *context,
   3844                                           angle::EntryPoint entryPoint,
   3845                                           PrimitiveMode mode,
   3846                                           const GLint *firsts,
   3847                                           const GLsizei *counts,
   3848                                           const GLsizei *instanceCounts,
   3849                                           GLsizei drawcount)
   3850 {
   3851    if (!context->getExtensions().multiDrawANGLE)
   3852    {
   3853        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3854        return false;
   3855    }
   3856    if (context->getClientMajorVersion() < 3)
   3857    {
   3858        if (!context->getExtensions().instancedArraysAny())
   3859        {
   3860            context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3861            return false;
   3862        }
   3863        if (!ValidateDrawInstancedANGLE(context, entryPoint))
   3864        {
   3865            return false;
   3866        }
   3867    }
   3868    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
   3869    {
   3870        if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, firsts[drawID],
   3871                                             counts[drawID], instanceCounts[drawID]))
   3872        {
   3873            return false;
   3874        }
   3875    }
   3876    return true;
   3877 }
   3878 
   3879 bool ValidateMultiDrawElementsInstancedANGLE(const Context *context,
   3880                                             angle::EntryPoint entryPoint,
   3881                                             PrimitiveMode mode,
   3882                                             const GLsizei *counts,
   3883                                             DrawElementsType type,
   3884                                             const GLvoid *const *indices,
   3885                                             const GLsizei *instanceCounts,
   3886                                             GLsizei drawcount)
   3887 {
   3888    if (!context->getExtensions().multiDrawANGLE)
   3889    {
   3890        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3891        return false;
   3892    }
   3893    if (context->getClientMajorVersion() < 3)
   3894    {
   3895        if (!context->getExtensions().instancedArraysAny())
   3896        {
   3897            context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3898            return false;
   3899        }
   3900        if (!ValidateDrawInstancedANGLE(context, entryPoint))
   3901        {
   3902            return false;
   3903        }
   3904    }
   3905    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
   3906    {
   3907        if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, counts[drawID], type,
   3908                                               indices[drawID], instanceCounts[drawID]))
   3909        {
   3910            return false;
   3911        }
   3912    }
   3913    return true;
   3914 }
   3915 
   3916 bool ValidateDrawArraysInstancedBaseInstanceANGLE(const Context *context,
   3917                                                  angle::EntryPoint entryPoint,
   3918                                                  PrimitiveMode mode,
   3919                                                  GLint first,
   3920                                                  GLsizei count,
   3921                                                  GLsizei instanceCount,
   3922                                                  GLuint baseInstance)
   3923 {
   3924    if (!context->getExtensions().baseVertexBaseInstanceANGLE)
   3925    {
   3926        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3927        return false;
   3928    }
   3929 
   3930    return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, instanceCount);
   3931 }
   3932 
   3933 bool ValidateDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
   3934                                                              angle::EntryPoint entryPoint,
   3935                                                              PrimitiveMode mode,
   3936                                                              GLsizei count,
   3937                                                              DrawElementsType type,
   3938                                                              const GLvoid *indices,
   3939                                                              GLsizei instanceCount,
   3940                                                              GLint baseVertex,
   3941                                                              GLuint baseInstance)
   3942 {
   3943    if (!context->getExtensions().baseVertexBaseInstanceANGLE)
   3944    {
   3945        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3946        return false;
   3947    }
   3948 
   3949    return ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
   3950                                             instanceCount);
   3951 }
   3952 
   3953 bool ValidateMultiDrawArraysInstancedBaseInstanceANGLE(const Context *context,
   3954                                                       angle::EntryPoint entryPoint,
   3955                                                       PrimitiveMode modePacked,
   3956                                                       const GLint *firsts,
   3957                                                       const GLsizei *counts,
   3958                                                       const GLsizei *instanceCounts,
   3959                                                       const GLuint *baseInstances,
   3960                                                       GLsizei drawcount)
   3961 {
   3962    if (!context->getExtensions().multiDrawANGLE)
   3963    {
   3964        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3965        return false;
   3966    }
   3967    if (drawcount < 0)
   3968    {
   3969        return false;
   3970    }
   3971    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
   3972    {
   3973        if (!ValidateDrawArraysInstancedBase(context, entryPoint, modePacked, firsts[drawID],
   3974                                             counts[drawID], instanceCounts[drawID]))
   3975        {
   3976            return false;
   3977        }
   3978    }
   3979    return true;
   3980 }
   3981 
   3982 bool ValidateMultiDrawElementsInstancedBaseVertexBaseInstanceANGLE(const Context *context,
   3983                                                                   angle::EntryPoint entryPoint,
   3984                                                                   PrimitiveMode modePacked,
   3985                                                                   const GLsizei *counts,
   3986                                                                   DrawElementsType typePacked,
   3987                                                                   const GLvoid *const *indices,
   3988                                                                   const GLsizei *instanceCounts,
   3989                                                                   const GLint *baseVertices,
   3990                                                                   const GLuint *baseInstances,
   3991                                                                   GLsizei drawcount)
   3992 {
   3993    if (!context->getExtensions().multiDrawANGLE)
   3994    {
   3995        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3996        return false;
   3997    }
   3998    if (drawcount < 0)
   3999    {
   4000        return false;
   4001    }
   4002    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
   4003    {
   4004        if (!ValidateDrawElementsInstancedBase(context, entryPoint, modePacked, counts[drawID],
   4005                                               typePacked, indices[drawID], instanceCounts[drawID]))
   4006        {
   4007            return false;
   4008        }
   4009    }
   4010    return true;
   4011 }
   4012 
   4013 bool ValidateFramebufferTextureMultiviewOVR(const Context *context,
   4014                                            angle::EntryPoint entryPoint,
   4015                                            GLenum target,
   4016                                            GLenum attachment,
   4017                                            TextureID texture,
   4018                                            GLint level,
   4019                                            GLint baseViewIndex,
   4020                                            GLsizei numViews)
   4021 {
   4022    if (!ValidateFramebufferTextureMultiviewBaseANGLE(context, entryPoint, target, attachment,
   4023                                                      texture, level, numViews))
   4024    {
   4025        return false;
   4026    }
   4027 
   4028    if (texture.value != 0)
   4029    {
   4030        if (baseViewIndex < 0)
   4031        {
   4032            context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBaseViewIndex);
   4033            return false;
   4034        }
   4035 
   4036        Texture *tex = context->getTexture(texture);
   4037        ASSERT(tex);
   4038 
   4039        switch (tex->getType())
   4040        {
   4041            case TextureType::_2DArray:
   4042            case TextureType::_2DMultisampleArray:
   4043            {
   4044                if (tex->getType() == TextureType::_2DMultisampleArray)
   4045                {
   4046                    if (!context->getExtensions().multiviewMultisampleANGLE)
   4047                    {
   4048                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   4049                                                 kInvalidTextureType);
   4050                        return false;
   4051                    }
   4052                }
   4053 
   4054                const Caps &caps = context->getCaps();
   4055                if (baseViewIndex + numViews > caps.maxArrayTextureLayers)
   4056                {
   4057                    context->validationError(entryPoint, GL_INVALID_VALUE,
   4058                                             kViewsExceedMaxArrayLayers);
   4059                    return false;
   4060                }
   4061 
   4062                break;
   4063            }
   4064            default:
   4065                context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureType);
   4066                return false;
   4067        }
   4068 
   4069        if (!ValidateFramebufferTextureMultiviewLevelAndFormat(context, entryPoint, tex, level))
   4070        {
   4071            return false;
   4072        }
   4073    }
   4074 
   4075    return true;
   4076 }
   4077 
   4078 bool ValidateUniform1ui(const Context *context,
   4079                        angle::EntryPoint entryPoint,
   4080                        UniformLocation location,
   4081                        GLuint v0)
   4082 {
   4083    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, 1);
   4084 }
   4085 
   4086 bool ValidateUniform2ui(const Context *context,
   4087                        angle::EntryPoint entryPoint,
   4088                        UniformLocation location,
   4089                        GLuint v0,
   4090                        GLuint v1)
   4091 {
   4092    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, 1);
   4093 }
   4094 
   4095 bool ValidateUniform3ui(const Context *context,
   4096                        angle::EntryPoint entryPoint,
   4097                        UniformLocation location,
   4098                        GLuint v0,
   4099                        GLuint v1,
   4100                        GLuint v2)
   4101 {
   4102    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, 1);
   4103 }
   4104 
   4105 bool ValidateUniform4ui(const Context *context,
   4106                        angle::EntryPoint entryPoint,
   4107                        UniformLocation location,
   4108                        GLuint v0,
   4109                        GLuint v1,
   4110                        GLuint v2,
   4111                        GLuint v3)
   4112 {
   4113    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, 1);
   4114 }
   4115 
   4116 bool ValidateUniform1uiv(const Context *context,
   4117                         angle::EntryPoint entryPoint,
   4118                         UniformLocation location,
   4119                         GLsizei count,
   4120                         const GLuint *value)
   4121 {
   4122    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT, location, count);
   4123 }
   4124 
   4125 bool ValidateUniform2uiv(const Context *context,
   4126                         angle::EntryPoint entryPoint,
   4127                         UniformLocation location,
   4128                         GLsizei count,
   4129                         const GLuint *value)
   4130 {
   4131    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC2, location, count);
   4132 }
   4133 
   4134 bool ValidateUniform3uiv(const Context *context,
   4135                         angle::EntryPoint entryPoint,
   4136                         UniformLocation location,
   4137                         GLsizei count,
   4138                         const GLuint *value)
   4139 {
   4140    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC3, location, count);
   4141 }
   4142 
   4143 bool ValidateUniform4uiv(const Context *context,
   4144                         angle::EntryPoint entryPoint,
   4145                         UniformLocation location,
   4146                         GLsizei count,
   4147                         const GLuint *value)
   4148 {
   4149    return ValidateUniformES3(context, entryPoint, GL_UNSIGNED_INT_VEC4, location, count);
   4150 }
   4151 
   4152 bool ValidateIsQuery(const Context *context, angle::EntryPoint entryPoint, QueryID id)
   4153 {
   4154    if (context->getClientMajorVersion() < 3)
   4155    {
   4156        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4157        return false;
   4158    }
   4159 
   4160    return true;
   4161 }
   4162 
   4163 bool ValidateUniformMatrix2x3fv(const Context *context,
   4164                                angle::EntryPoint entryPoint,
   4165                                UniformLocation location,
   4166                                GLsizei count,
   4167                                GLboolean transpose,
   4168                                const GLfloat *value)
   4169 {
   4170    return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x3, location, count,
   4171                                    transpose);
   4172 }
   4173 
   4174 bool ValidateUniformMatrix3x2fv(const Context *context,
   4175                                angle::EntryPoint entryPoint,
   4176                                UniformLocation location,
   4177                                GLsizei count,
   4178                                GLboolean transpose,
   4179                                const GLfloat *value)
   4180 {
   4181    return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x2, location, count,
   4182                                    transpose);
   4183 }
   4184 
   4185 bool ValidateUniformMatrix2x4fv(const Context *context,
   4186                                angle::EntryPoint entryPoint,
   4187                                UniformLocation location,
   4188                                GLsizei count,
   4189                                GLboolean transpose,
   4190                                const GLfloat *value)
   4191 {
   4192    return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT2x4, location, count,
   4193                                    transpose);
   4194 }
   4195 
   4196 bool ValidateUniformMatrix4x2fv(const Context *context,
   4197                                angle::EntryPoint entryPoint,
   4198                                UniformLocation location,
   4199                                GLsizei count,
   4200                                GLboolean transpose,
   4201                                const GLfloat *value)
   4202 {
   4203    return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x2, location, count,
   4204                                    transpose);
   4205 }
   4206 
   4207 bool ValidateUniformMatrix3x4fv(const Context *context,
   4208                                angle::EntryPoint entryPoint,
   4209                                UniformLocation location,
   4210                                GLsizei count,
   4211                                GLboolean transpose,
   4212                                const GLfloat *value)
   4213 {
   4214    return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT3x4, location, count,
   4215                                    transpose);
   4216 }
   4217 
   4218 bool ValidateUniformMatrix4x3fv(const Context *context,
   4219                                angle::EntryPoint entryPoint,
   4220                                UniformLocation location,
   4221                                GLsizei count,
   4222                                GLboolean transpose,
   4223                                const GLfloat *value)
   4224 {
   4225    return ValidateUniformMatrixES3(context, entryPoint, GL_FLOAT_MAT4x3, location, count,
   4226                                    transpose);
   4227 }
   4228 
   4229 bool ValidateEndTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
   4230 {
   4231    if (context->getClientMajorVersion() < 3)
   4232    {
   4233        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4234        return false;
   4235    }
   4236 
   4237    TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
   4238    ASSERT(transformFeedback != nullptr);
   4239 
   4240    if (!transformFeedback->isActive())
   4241    {
   4242        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
   4243        return false;
   4244    }
   4245 
   4246    return true;
   4247 }
   4248 
   4249 bool ValidateTransformFeedbackVaryings(const Context *context,
   4250                                       angle::EntryPoint entryPoint,
   4251                                       ShaderProgramID program,
   4252                                       GLsizei count,
   4253                                       const GLchar *const *varyings,
   4254                                       GLenum bufferMode)
   4255 {
   4256    if (context->getClientMajorVersion() < 3)
   4257    {
   4258        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4259        return false;
   4260    }
   4261 
   4262    if (count < 0)
   4263    {
   4264        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   4265        return false;
   4266    }
   4267 
   4268    switch (bufferMode)
   4269    {
   4270        case GL_INTERLEAVED_ATTRIBS:
   4271            break;
   4272        case GL_SEPARATE_ATTRIBS:
   4273        {
   4274            const Caps &caps = context->getCaps();
   4275            if (count > caps.maxTransformFeedbackSeparateAttributes)
   4276            {
   4277                context->validationError(entryPoint, GL_INVALID_VALUE,
   4278                                         kInvalidTransformFeedbackAttribsCount);
   4279                return false;
   4280            }
   4281            break;
   4282        }
   4283        default:
   4284            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, bufferMode);
   4285            return false;
   4286    }
   4287 
   4288    Program *programObject = GetValidProgram(context, entryPoint, program);
   4289    if (!programObject)
   4290    {
   4291        return false;
   4292    }
   4293 
   4294    return true;
   4295 }
   4296 
   4297 bool ValidateGetTransformFeedbackVarying(const Context *context,
   4298                                         angle::EntryPoint entryPoint,
   4299                                         ShaderProgramID program,
   4300                                         GLuint index,
   4301                                         GLsizei bufSize,
   4302                                         const GLsizei *length,
   4303                                         const GLsizei *size,
   4304                                         const GLenum *type,
   4305                                         const GLchar *name)
   4306 {
   4307    if (context->getClientMajorVersion() < 3)
   4308    {
   4309        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4310        return false;
   4311    }
   4312 
   4313    if (bufSize < 0)
   4314    {
   4315        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   4316        return false;
   4317    }
   4318 
   4319    Program *programObject = GetValidProgram(context, entryPoint, program);
   4320    if (!programObject)
   4321    {
   4322        return false;
   4323    }
   4324 
   4325    if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
   4326    {
   4327        context->validationError(entryPoint, GL_INVALID_VALUE,
   4328                                 kTransformFeedbackVaryingIndexOutOfRange);
   4329        return false;
   4330    }
   4331 
   4332    return true;
   4333 }
   4334 
   4335 bool ValidateBindTransformFeedback(const Context *context,
   4336                                   angle::EntryPoint entryPoint,
   4337                                   GLenum target,
   4338                                   TransformFeedbackID id)
   4339 {
   4340    if (context->getClientMajorVersion() < 3)
   4341    {
   4342        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4343        return false;
   4344    }
   4345 
   4346    switch (target)
   4347    {
   4348        case GL_TRANSFORM_FEEDBACK:
   4349        {
   4350            // Cannot bind a transform feedback object if the current one is started and not
   4351            // paused (3.0.2 pg 85 section 2.14.1)
   4352            if (context->getState().isTransformFeedbackActiveUnpaused())
   4353            {
   4354                context->validationError(entryPoint, GL_INVALID_OPERATION,
   4355                                         kTransformFeedbackNotPaused);
   4356                return false;
   4357            }
   4358 
   4359            // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section
   4360            // 2.14.1)
   4361            if (!context->isTransformFeedbackGenerated(id))
   4362            {
   4363                context->validationError(entryPoint, GL_INVALID_OPERATION,
   4364                                         kTransformFeedbackDoesNotExist);
   4365                return false;
   4366            }
   4367        }
   4368        break;
   4369 
   4370        default:
   4371            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
   4372            return false;
   4373    }
   4374 
   4375    return true;
   4376 }
   4377 
   4378 bool ValidateIsTransformFeedback(const Context *context,
   4379                                 angle::EntryPoint entryPoint,
   4380                                 TransformFeedbackID id)
   4381 {
   4382    if (context->getClientMajorVersion() < 3)
   4383    {
   4384        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4385        return false;
   4386    }
   4387 
   4388    return true;
   4389 }
   4390 
   4391 bool ValidatePauseTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
   4392 {
   4393    if (context->getClientMajorVersion() < 3)
   4394    {
   4395        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4396        return false;
   4397    }
   4398 
   4399    TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
   4400    ASSERT(transformFeedback != nullptr);
   4401 
   4402    // Current transform feedback must be active and not paused in order to pause (3.0.2 pg 86)
   4403    if (!transformFeedback->isActive())
   4404    {
   4405        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
   4406        return false;
   4407    }
   4408 
   4409    if (transformFeedback->isPaused())
   4410    {
   4411        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackPaused);
   4412        return false;
   4413    }
   4414 
   4415    return true;
   4416 }
   4417 
   4418 bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint entryPoint)
   4419 {
   4420    if (context->getClientMajorVersion() < 3)
   4421    {
   4422        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4423        return false;
   4424    }
   4425 
   4426    TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
   4427    ASSERT(transformFeedback != nullptr);
   4428 
   4429    // Current transform feedback must be active and paused in order to resume (3.0.2 pg 86)
   4430    if (!transformFeedback->isActive())
   4431    {
   4432        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotActive);
   4433        return false;
   4434    }
   4435 
   4436    if (!transformFeedback->isPaused())
   4437    {
   4438        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackNotPaused);
   4439        return false;
   4440    }
   4441 
   4442    if (!ValidateProgramExecutableXFBBuffersPresent(
   4443            context, context->getState().getLinkedProgramExecutable(context)))
   4444    {
   4445        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
   4446        return false;
   4447    }
   4448 
   4449    return true;
   4450 }
   4451 
   4452 bool ValidateVertexAttribI4i(const Context *context,
   4453                             angle::EntryPoint entryPoint,
   4454                             GLuint index,
   4455                             GLint x,
   4456                             GLint y,
   4457                             GLint z,
   4458                             GLint w)
   4459 {
   4460    if (context->getClientMajorVersion() < 3)
   4461    {
   4462        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4463        return false;
   4464    }
   4465 
   4466    return ValidateVertexAttribIndex(context, entryPoint, index);
   4467 }
   4468 
   4469 bool ValidateVertexAttribI4ui(const Context *context,
   4470                              angle::EntryPoint entryPoint,
   4471                              GLuint index,
   4472                              GLuint x,
   4473                              GLuint y,
   4474                              GLuint z,
   4475                              GLuint w)
   4476 {
   4477    if (context->getClientMajorVersion() < 3)
   4478    {
   4479        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4480        return false;
   4481    }
   4482 
   4483    return ValidateVertexAttribIndex(context, entryPoint, index);
   4484 }
   4485 
   4486 bool ValidateVertexAttribI4iv(const Context *context,
   4487                              angle::EntryPoint entryPoint,
   4488                              GLuint index,
   4489                              const GLint *v)
   4490 {
   4491    if (context->getClientMajorVersion() < 3)
   4492    {
   4493        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4494        return false;
   4495    }
   4496 
   4497    return ValidateVertexAttribIndex(context, entryPoint, index);
   4498 }
   4499 
   4500 bool ValidateVertexAttribI4uiv(const Context *context,
   4501                               angle::EntryPoint entryPoint,
   4502                               GLuint index,
   4503                               const GLuint *v)
   4504 {
   4505    if (context->getClientMajorVersion() < 3)
   4506    {
   4507        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4508        return false;
   4509    }
   4510 
   4511    return ValidateVertexAttribIndex(context, entryPoint, index);
   4512 }
   4513 
   4514 bool ValidateGetFragDataLocation(const Context *context,
   4515                                 angle::EntryPoint entryPoint,
   4516                                 ShaderProgramID program,
   4517                                 const GLchar *name)
   4518 {
   4519    if (context->getClientMajorVersion() < 3)
   4520    {
   4521        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4522        return false;
   4523    }
   4524 
   4525    Program *programObject = GetValidProgram(context, entryPoint, program);
   4526    if (!programObject)
   4527    {
   4528        return false;
   4529    }
   4530 
   4531    if (!programObject->isLinked())
   4532    {
   4533        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   4534        return false;
   4535    }
   4536 
   4537    return true;
   4538 }
   4539 
   4540 bool ValidateGetUniformIndices(const Context *context,
   4541                               angle::EntryPoint entryPoint,
   4542                               ShaderProgramID program,
   4543                               GLsizei uniformCount,
   4544                               const GLchar *const *uniformNames,
   4545                               const GLuint *uniformIndices)
   4546 {
   4547    if (context->getClientMajorVersion() < 3)
   4548    {
   4549        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4550        return false;
   4551    }
   4552 
   4553    if (uniformCount < 0)
   4554    {
   4555        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   4556        return false;
   4557    }
   4558 
   4559    Program *programObject = GetValidProgram(context, entryPoint, program);
   4560    if (!programObject)
   4561    {
   4562        return false;
   4563    }
   4564 
   4565    return true;
   4566 }
   4567 
   4568 bool ValidateGetActiveUniformsiv(const Context *context,
   4569                                 angle::EntryPoint entryPoint,
   4570                                 ShaderProgramID program,
   4571                                 GLsizei uniformCount,
   4572                                 const GLuint *uniformIndices,
   4573                                 GLenum pname,
   4574                                 const GLint *params)
   4575 {
   4576    if (context->getClientMajorVersion() < 3)
   4577    {
   4578        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4579        return false;
   4580    }
   4581 
   4582    if (uniformCount < 0)
   4583    {
   4584        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   4585        return false;
   4586    }
   4587 
   4588    Program *programObject = GetValidProgram(context, entryPoint, program);
   4589    if (!programObject)
   4590    {
   4591        return false;
   4592    }
   4593 
   4594    switch (pname)
   4595    {
   4596        case GL_UNIFORM_TYPE:
   4597        case GL_UNIFORM_SIZE:
   4598            break;
   4599        case GL_UNIFORM_NAME_LENGTH:
   4600            if (context->getExtensions().webglCompatibilityANGLE)
   4601            {
   4602                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   4603                return false;
   4604            }
   4605            break;
   4606        case GL_UNIFORM_BLOCK_INDEX:
   4607        case GL_UNIFORM_OFFSET:
   4608        case GL_UNIFORM_ARRAY_STRIDE:
   4609        case GL_UNIFORM_MATRIX_STRIDE:
   4610        case GL_UNIFORM_IS_ROW_MAJOR:
   4611            break;
   4612 
   4613        default:
   4614            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   4615            return false;
   4616    }
   4617 
   4618    if (uniformCount > programObject->getActiveUniformCount())
   4619    {
   4620        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
   4621        return false;
   4622    }
   4623 
   4624    for (int uniformId = 0; uniformId < uniformCount; uniformId++)
   4625    {
   4626        const GLuint index = uniformIndices[uniformId];
   4627 
   4628        if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
   4629        {
   4630            context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
   4631            return false;
   4632        }
   4633    }
   4634 
   4635    return true;
   4636 }
   4637 
   4638 bool ValidateGetUniformBlockIndex(const Context *context,
   4639                                  angle::EntryPoint entryPoint,
   4640                                  ShaderProgramID program,
   4641                                  const GLchar *uniformBlockName)
   4642 {
   4643    if (context->getClientMajorVersion() < 3)
   4644    {
   4645        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4646        return false;
   4647    }
   4648 
   4649    Program *programObject = GetValidProgram(context, entryPoint, program);
   4650    if (!programObject)
   4651    {
   4652        return false;
   4653    }
   4654 
   4655    return true;
   4656 }
   4657 
   4658 bool ValidateGetActiveUniformBlockiv(const Context *context,
   4659                                     angle::EntryPoint entryPoint,
   4660                                     ShaderProgramID program,
   4661                                     UniformBlockIndex uniformBlockIndex,
   4662                                     GLenum pname,
   4663                                     const GLint *params)
   4664 {
   4665    return ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex,
   4666                                               pname, nullptr);
   4667 }
   4668 
   4669 bool ValidateGetActiveUniformBlockName(const Context *context,
   4670                                       angle::EntryPoint entryPoint,
   4671                                       ShaderProgramID program,
   4672                                       UniformBlockIndex uniformBlockIndex,
   4673                                       GLsizei bufSize,
   4674                                       const GLsizei *length,
   4675                                       const GLchar *uniformBlockName)
   4676 {
   4677    if (context->getClientMajorVersion() < 3)
   4678    {
   4679        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4680        return false;
   4681    }
   4682 
   4683    Program *programObject = GetValidProgram(context, entryPoint, program);
   4684    if (!programObject)
   4685    {
   4686        return false;
   4687    }
   4688 
   4689    if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
   4690    {
   4691        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniformBlock);
   4692        return false;
   4693    }
   4694 
   4695    return true;
   4696 }
   4697 
   4698 bool ValidateUniformBlockBinding(const Context *context,
   4699                                 angle::EntryPoint entryPoint,
   4700                                 ShaderProgramID program,
   4701                                 UniformBlockIndex uniformBlockIndex,
   4702                                 GLuint uniformBlockBinding)
   4703 {
   4704    if (context->getClientMajorVersion() < 3)
   4705    {
   4706        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4707        return false;
   4708    }
   4709 
   4710    if (uniformBlockBinding >= static_cast<GLuint>(context->getCaps().maxUniformBufferBindings))
   4711    {
   4712        context->validationError(entryPoint, GL_INVALID_VALUE,
   4713                                 kIndexExceedsMaxUniformBufferBindings);
   4714        return false;
   4715    }
   4716 
   4717    Program *programObject = GetValidProgram(context, entryPoint, program);
   4718    if (!programObject)
   4719    {
   4720        return false;
   4721    }
   4722 
   4723    // if never linked, there won't be any uniform blocks
   4724    if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
   4725    {
   4726        context->validationError(entryPoint, GL_INVALID_VALUE,
   4727                                 kIndexExceedsMaxUniformBufferBindings);
   4728        return false;
   4729    }
   4730 
   4731    return true;
   4732 }
   4733 
   4734 bool ValidateDrawArraysInstanced(const Context *context,
   4735                                 angle::EntryPoint entryPoint,
   4736                                 PrimitiveMode mode,
   4737                                 GLint first,
   4738                                 GLsizei count,
   4739                                 GLsizei primcount)
   4740 {
   4741    if (context->getClientMajorVersion() < 3)
   4742    {
   4743        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4744        return false;
   4745    }
   4746 
   4747    return ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount);
   4748 }
   4749 
   4750 bool ValidateFenceSync(const Context *context,
   4751                       angle::EntryPoint entryPoint,
   4752                       GLenum condition,
   4753                       GLbitfield flags)
   4754 {
   4755    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   4756    {
   4757        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4758        return false;
   4759    }
   4760 
   4761    if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
   4762    {
   4763        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFenceCondition);
   4764        return false;
   4765    }
   4766 
   4767    if (flags != 0)
   4768    {
   4769        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
   4770        return false;
   4771    }
   4772 
   4773    return true;
   4774 }
   4775 
   4776 bool ValidateIsSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync)
   4777 {
   4778    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   4779    {
   4780        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4781        return false;
   4782    }
   4783 
   4784    return true;
   4785 }
   4786 
   4787 bool ValidateDeleteSync(const Context *context, angle::EntryPoint entryPoint, GLsync sync)
   4788 {
   4789    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   4790    {
   4791        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4792        return false;
   4793    }
   4794 
   4795    if (sync != static_cast<GLsync>(0) && !context->getSync(sync))
   4796    {
   4797        context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
   4798        return false;
   4799    }
   4800 
   4801    return true;
   4802 }
   4803 
   4804 bool ValidateClientWaitSync(const Context *context,
   4805                            angle::EntryPoint entryPoint,
   4806                            GLsync sync,
   4807                            GLbitfield flags,
   4808                            GLuint64 timeout)
   4809 {
   4810    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   4811    {
   4812        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4813        return false;
   4814    }
   4815 
   4816    if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
   4817    {
   4818        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
   4819        return false;
   4820    }
   4821 
   4822    Sync *clientWaitSync = context->getSync(sync);
   4823    if (!clientWaitSync)
   4824    {
   4825        context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
   4826        return false;
   4827    }
   4828 
   4829    return true;
   4830 }
   4831 
   4832 bool ValidateWaitSync(const Context *context,
   4833                      angle::EntryPoint entryPoint,
   4834                      GLsync sync,
   4835                      GLbitfield flags,
   4836                      GLuint64 timeout)
   4837 {
   4838    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   4839    {
   4840        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4841        return false;
   4842    }
   4843 
   4844    if (flags != 0)
   4845    {
   4846        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlags);
   4847        return false;
   4848    }
   4849 
   4850    if (timeout != GL_TIMEOUT_IGNORED)
   4851    {
   4852        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTimeout);
   4853        return false;
   4854    }
   4855 
   4856    Sync *waitSync = context->getSync(sync);
   4857    if (!waitSync)
   4858    {
   4859        context->validationError(entryPoint, GL_INVALID_VALUE, kSyncMissing);
   4860        return false;
   4861    }
   4862 
   4863    return true;
   4864 }
   4865 
   4866 bool ValidateGetInteger64v(const Context *context,
   4867                           angle::EntryPoint entryPoint,
   4868                           GLenum pname,
   4869                           const GLint64 *params)
   4870 {
   4871    if ((context->getClientMajorVersion() < 3) && !context->getExtensions().syncARB)
   4872    {
   4873        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4874        return false;
   4875    }
   4876 
   4877    GLenum nativeType      = GL_NONE;
   4878    unsigned int numParams = 0;
   4879    if (!ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams))
   4880    {
   4881        return false;
   4882    }
   4883 
   4884    return true;
   4885 }
   4886 
   4887 bool ValidateIsSampler(const Context *context, angle::EntryPoint entryPoint, SamplerID sampler)
   4888 {
   4889    if (context->getClientMajorVersion() < 3)
   4890    {
   4891        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4892        return false;
   4893    }
   4894 
   4895    return true;
   4896 }
   4897 
   4898 bool ValidateBindSampler(const Context *context,
   4899                         angle::EntryPoint entryPoint,
   4900                         GLuint unit,
   4901                         SamplerID sampler)
   4902 {
   4903    if (context->getClientMajorVersion() < 3)
   4904    {
   4905        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4906        return false;
   4907    }
   4908 
   4909    if (GetIDValue(sampler) != 0 && !context->isSampler(sampler))
   4910    {
   4911        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
   4912        return false;
   4913    }
   4914 
   4915    if (unit >= static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits))
   4916    {
   4917        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCombinedImageUnit);
   4918        return false;
   4919    }
   4920 
   4921    return true;
   4922 }
   4923 
   4924 bool ValidateVertexAttribDivisor(const Context *context,
   4925                                 angle::EntryPoint entryPoint,
   4926                                 GLuint index,
   4927                                 GLuint divisor)
   4928 {
   4929    if (context->getClientMajorVersion() < 3)
   4930    {
   4931        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4932        return false;
   4933    }
   4934 
   4935    return ValidateVertexAttribIndex(context, entryPoint, index);
   4936 }
   4937 
   4938 bool ValidateTexStorage2D(const Context *context,
   4939                          angle::EntryPoint entryPoint,
   4940                          TextureType target,
   4941                          GLsizei levels,
   4942                          GLenum internalformat,
   4943                          GLsizei width,
   4944                          GLsizei height)
   4945 {
   4946    if (context->getClientMajorVersion() < 3)
   4947    {
   4948        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4949        return false;
   4950    }
   4951 
   4952    if (!ValidateES3TexStorage2DParameters(context, entryPoint, target, levels, internalformat,
   4953                                           width, height, 1))
   4954    {
   4955        return false;
   4956    }
   4957 
   4958    return true;
   4959 }
   4960 
   4961 bool ValidateTexStorage3D(const Context *context,
   4962                          angle::EntryPoint entryPoint,
   4963                          TextureType target,
   4964                          GLsizei levels,
   4965                          GLenum internalformat,
   4966                          GLsizei width,
   4967                          GLsizei height,
   4968                          GLsizei depth)
   4969 {
   4970    if (context->getClientMajorVersion() < 3)
   4971    {
   4972        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4973        return false;
   4974    }
   4975 
   4976    if (!ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
   4977                                           width, height, depth))
   4978    {
   4979        return false;
   4980    }
   4981 
   4982    return true;
   4983 }
   4984 
   4985 bool ValidateGetBufferParameteri64v(const Context *context,
   4986                                    angle::EntryPoint entryPoint,
   4987                                    BufferBinding target,
   4988                                    GLenum pname,
   4989                                    const GLint64 *params)
   4990 {
   4991    return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
   4992 }
   4993 
   4994 bool ValidateGetSamplerParameterfv(const Context *context,
   4995                                   angle::EntryPoint entryPoint,
   4996                                   SamplerID sampler,
   4997                                   GLenum pname,
   4998                                   const GLfloat *params)
   4999 {
   5000    return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
   5001 }
   5002 
   5003 bool ValidateGetSamplerParameteriv(const Context *context,
   5004                                   angle::EntryPoint entryPoint,
   5005                                   SamplerID sampler,
   5006                                   GLenum pname,
   5007                                   const GLint *params)
   5008 {
   5009    return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
   5010 }
   5011 
   5012 bool ValidateGetSamplerParameterIivOES(const Context *context,
   5013                                       angle::EntryPoint entryPoint,
   5014                                       SamplerID sampler,
   5015                                       GLenum pname,
   5016                                       const GLint *params)
   5017 {
   5018    if (context->getClientMajorVersion() < 3)
   5019    {
   5020        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5021        return false;
   5022    }
   5023    return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
   5024 }
   5025 
   5026 bool ValidateGetSamplerParameterIuivOES(const Context *context,
   5027                                        angle::EntryPoint entryPoint,
   5028                                        SamplerID sampler,
   5029                                        GLenum pname,
   5030                                        const GLuint *params)
   5031 {
   5032    if (context->getClientMajorVersion() < 3)
   5033    {
   5034        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5035        return false;
   5036    }
   5037    return ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, nullptr);
   5038 }
   5039 
   5040 bool ValidateSamplerParameterf(const Context *context,
   5041                               angle::EntryPoint entryPoint,
   5042                               SamplerID sampler,
   5043                               GLenum pname,
   5044                               GLfloat param)
   5045 {
   5046    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
   5047 }
   5048 
   5049 bool ValidateSamplerParameterfv(const Context *context,
   5050                                angle::EntryPoint entryPoint,
   5051                                SamplerID sampler,
   5052                                GLenum pname,
   5053                                const GLfloat *params)
   5054 {
   5055    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
   5056 }
   5057 
   5058 bool ValidateSamplerParameteri(const Context *context,
   5059                               angle::EntryPoint entryPoint,
   5060                               SamplerID sampler,
   5061                               GLenum pname,
   5062                               GLint param)
   5063 {
   5064    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, false, &param);
   5065 }
   5066 
   5067 bool ValidateSamplerParameteriv(const Context *context,
   5068                                angle::EntryPoint entryPoint,
   5069                                SamplerID sampler,
   5070                                GLenum pname,
   5071                                const GLint *params)
   5072 {
   5073    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
   5074 }
   5075 
   5076 bool ValidateSamplerParameterIivOES(const Context *context,
   5077                                    angle::EntryPoint entryPoint,
   5078                                    SamplerID sampler,
   5079                                    GLenum pname,
   5080                                    const GLint *params)
   5081 {
   5082    if (context->getClientMajorVersion() < 3)
   5083    {
   5084        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5085        return false;
   5086    }
   5087    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
   5088 }
   5089 
   5090 bool ValidateSamplerParameterIuivOES(const Context *context,
   5091                                     angle::EntryPoint entryPoint,
   5092                                     SamplerID sampler,
   5093                                     GLenum pname,
   5094                                     const GLuint *params)
   5095 {
   5096    if (context->getClientMajorVersion() < 3)
   5097    {
   5098        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5099        return false;
   5100    }
   5101    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, -1, true, params);
   5102 }
   5103 
   5104 bool ValidateGetVertexAttribIiv(const Context *context,
   5105                                angle::EntryPoint entryPoint,
   5106                                GLuint index,
   5107                                GLenum pname,
   5108                                const GLint *params)
   5109 {
   5110    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
   5111 }
   5112 
   5113 bool ValidateGetVertexAttribIuiv(const Context *context,
   5114                                 angle::EntryPoint entryPoint,
   5115                                 GLuint index,
   5116                                 GLenum pname,
   5117                                 const GLuint *params)
   5118 {
   5119    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, true);
   5120 }
   5121 
   5122 bool ValidateGetInternalformativ(const Context *context,
   5123                                 angle::EntryPoint entryPoint,
   5124                                 GLenum target,
   5125                                 GLenum internalformat,
   5126                                 GLenum pname,
   5127                                 GLsizei bufSize,
   5128                                 const GLint *params)
   5129 {
   5130    return ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
   5131                                           bufSize, nullptr);
   5132 }
   5133 
   5134 bool ValidateBindFragDataLocationIndexedEXT(const Context *context,
   5135                                            angle::EntryPoint entryPoint,
   5136                                            ShaderProgramID program,
   5137                                            GLuint colorNumber,
   5138                                            GLuint index,
   5139                                            const char *name)
   5140 {
   5141    if (!context->getExtensions().blendFuncExtendedEXT)
   5142    {
   5143        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   5144        return false;
   5145    }
   5146    if (context->getClientMajorVersion() < 3)
   5147    {
   5148        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5149        return false;
   5150    }
   5151    if (index > 1)
   5152    {
   5153        // This error is not explicitly specified but the spec does say that "<index> may be zero or
   5154        // one to specify that the color be used as either the first or second color input to the
   5155        // blend equation, respectively"
   5156        context->validationError(entryPoint, GL_INVALID_VALUE, kFragDataBindingIndexOutOfRange);
   5157        return false;
   5158    }
   5159    if (index == 1)
   5160    {
   5161        if (colorNumber >= context->getCaps().maxDualSourceDrawBuffers)
   5162        {
   5163            context->validationError(entryPoint, GL_INVALID_VALUE,
   5164                                     kColorNumberGreaterThanMaxDualSourceDrawBuffers);
   5165            return false;
   5166        }
   5167    }
   5168    else
   5169    {
   5170        if (colorNumber >= static_cast<GLuint>(context->getCaps().maxDrawBuffers))
   5171        {
   5172            context->validationError(entryPoint, GL_INVALID_VALUE,
   5173                                     kColorNumberGreaterThanMaxDrawBuffers);
   5174            return false;
   5175        }
   5176    }
   5177    Program *programObject = GetValidProgram(context, entryPoint, program);
   5178    if (!programObject)
   5179    {
   5180        return false;
   5181    }
   5182    return true;
   5183 }
   5184 
   5185 bool ValidateBindFragDataLocationEXT(const Context *context,
   5186                                     angle::EntryPoint entryPoint,
   5187                                     ShaderProgramID program,
   5188                                     GLuint colorNumber,
   5189                                     const char *name)
   5190 {
   5191    return ValidateBindFragDataLocationIndexedEXT(context, entryPoint, program, colorNumber, 0u,
   5192                                                  name);
   5193 }
   5194 
   5195 bool ValidateGetFragDataIndexEXT(const Context *context,
   5196                                 angle::EntryPoint entryPoint,
   5197                                 ShaderProgramID program,
   5198                                 const char *name)
   5199 {
   5200    if (!context->getExtensions().blendFuncExtendedEXT)
   5201    {
   5202        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   5203        return false;
   5204    }
   5205    if (context->getClientMajorVersion() < 3)
   5206    {
   5207        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5208        return false;
   5209    }
   5210    Program *programObject = GetValidProgram(context, entryPoint, program);
   5211    if (!programObject)
   5212    {
   5213        return false;
   5214    }
   5215    if (!programObject->isLinked())
   5216    {
   5217        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   5218        return false;
   5219    }
   5220    return true;
   5221 }
   5222 
   5223 bool ValidateTexStorage2DMultisampleANGLE(const Context *context,
   5224                                          angle::EntryPoint entryPoint,
   5225                                          TextureType target,
   5226                                          GLsizei samples,
   5227                                          GLenum internalFormat,
   5228                                          GLsizei width,
   5229                                          GLsizei height,
   5230                                          GLboolean fixedSampleLocations)
   5231 {
   5232    if (!context->getExtensions().textureMultisampleANGLE)
   5233    {
   5234        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5235                                 kMultisampleTextureExtensionOrES31Required);
   5236        return false;
   5237    }
   5238 
   5239    return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
   5240                                               width, height);
   5241 }
   5242 
   5243 bool ValidateGetTexLevelParameterfvANGLE(const Context *context,
   5244                                         angle::EntryPoint entryPoint,
   5245                                         TextureTarget target,
   5246                                         GLint level,
   5247                                         GLenum pname,
   5248                                         const GLfloat *params)
   5249 {
   5250    if (!context->getExtensions().textureMultisampleANGLE &&
   5251        !context->getExtensions().getTexLevelParameterANGLE)
   5252    {
   5253        context->validationError(
   5254            entryPoint, GL_INVALID_OPERATION,
   5255            kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
   5256        return false;
   5257    }
   5258 
   5259    return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
   5260 }
   5261 
   5262 bool ValidateGetTexLevelParameterivANGLE(const Context *context,
   5263                                         angle::EntryPoint entryPoint,
   5264                                         TextureTarget target,
   5265                                         GLint level,
   5266                                         GLenum pname,
   5267                                         const GLint *params)
   5268 {
   5269    if (!context->getExtensions().textureMultisampleANGLE &&
   5270        !context->getExtensions().getTexLevelParameterANGLE)
   5271    {
   5272        context->validationError(
   5273            entryPoint, GL_INVALID_OPERATION,
   5274            kMultisampleTextureExtensionOrGetTexLevelParameterExtensionOrES31Required);
   5275        return false;
   5276    }
   5277 
   5278    return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
   5279 }
   5280 
   5281 bool ValidateGetMultisamplefvANGLE(const Context *context,
   5282                                   angle::EntryPoint entryPoint,
   5283                                   GLenum pname,
   5284                                   GLuint index,
   5285                                   const GLfloat *val)
   5286 {
   5287    if (!context->getExtensions().textureMultisampleANGLE)
   5288    {
   5289        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5290                                 kMultisampleTextureExtensionOrES31Required);
   5291        return false;
   5292    }
   5293 
   5294    return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
   5295 }
   5296 
   5297 bool ValidateSampleMaskiANGLE(const Context *context,
   5298                              angle::EntryPoint entryPoint,
   5299                              GLuint maskNumber,
   5300                              GLbitfield mask)
   5301 {
   5302    if (!context->getExtensions().textureMultisampleANGLE)
   5303    {
   5304        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5305                                 kMultisampleTextureExtensionOrES31Required);
   5306        return false;
   5307    }
   5308 
   5309    return ValidateSampleMaskiBase(context, entryPoint, maskNumber, mask);
   5310 }
   5311 }  // namespace gl