tor-browser

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

validationES2.cpp (227287B)


      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 // validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters
      8 
      9 #include "libANGLE/validationES2_autogen.h"
     10 
     11 #include <cstdint>
     12 
     13 #include "common/mathutil.h"
     14 #include "common/string_utils.h"
     15 #include "common/utilities.h"
     16 #include "libANGLE/Context.h"
     17 #include "libANGLE/ErrorStrings.h"
     18 #include "libANGLE/Fence.h"
     19 #include "libANGLE/Framebuffer.h"
     20 #include "libANGLE/FramebufferAttachment.h"
     21 #include "libANGLE/MemoryObject.h"
     22 #include "libANGLE/Renderbuffer.h"
     23 #include "libANGLE/Shader.h"
     24 #include "libANGLE/Texture.h"
     25 #include "libANGLE/Uniform.h"
     26 #include "libANGLE/VertexArray.h"
     27 #include "libANGLE/formatutils.h"
     28 #include "libANGLE/validationES.h"
     29 #include "libANGLE/validationES2.h"
     30 #include "libANGLE/validationES3_autogen.h"
     31 
     32 namespace gl
     33 {
     34 using namespace err;
     35 
     36 namespace
     37 {
     38 
     39 bool IsPartialBlit(const Context *context,
     40                   const FramebufferAttachment *readBuffer,
     41                   const FramebufferAttachment *writeBuffer,
     42                   GLint srcX0,
     43                   GLint srcY0,
     44                   GLint srcX1,
     45                   GLint srcY1,
     46                   GLint dstX0,
     47                   GLint dstY0,
     48                   GLint dstX1,
     49                   GLint dstY1)
     50 {
     51    const Extents &writeSize = writeBuffer->getSize();
     52    const Extents &readSize  = readBuffer->getSize();
     53 
     54    if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || dstX1 != writeSize.width ||
     55        dstY1 != writeSize.height || srcX1 != readSize.width || srcY1 != readSize.height)
     56    {
     57        return true;
     58    }
     59 
     60    if (context->getState().isScissorTestEnabled())
     61    {
     62        const Rectangle &scissor = context->getState().getScissor();
     63        return scissor.x > 0 || scissor.y > 0 || scissor.width < writeSize.width ||
     64               scissor.height < writeSize.height;
     65    }
     66 
     67    return false;
     68 }
     69 
     70 bool IsValidCopyTextureSourceInternalFormatEnum(GLenum internalFormat)
     71 {
     72    // Table 1.1 from the CHROMIUM_copy_texture spec
     73    switch (GetUnsizedFormat(internalFormat))
     74    {
     75        case GL_RED:
     76        case GL_ALPHA:
     77        case GL_LUMINANCE:
     78        case GL_LUMINANCE_ALPHA:
     79        case GL_RGB:
     80        case GL_RGBA:
     81        case GL_RGB8:
     82        case GL_RGBA8:
     83        case GL_BGRA_EXT:
     84        case GL_BGRA8_EXT:
     85            return true;
     86 
     87        default:
     88            return false;
     89    }
     90 }
     91 
     92 bool IsValidCopySubTextureSourceInternalFormat(GLenum internalFormat)
     93 {
     94    return IsValidCopyTextureSourceInternalFormatEnum(internalFormat);
     95 }
     96 
     97 bool IsValidCopyTextureDestinationInternalFormatEnum(GLint internalFormat)
     98 {
     99    // Table 1.0 from the CHROMIUM_copy_texture spec
    100    switch (internalFormat)
    101    {
    102        case GL_ALPHA:
    103        case GL_BGRA8_EXT:
    104        case GL_BGRA_EXT:
    105        case GL_LUMINANCE:
    106        case GL_LUMINANCE_ALPHA:
    107        case GL_R11F_G11F_B10F:
    108        case GL_R16F:
    109        case GL_R32F:
    110        case GL_R8:
    111        case GL_R8UI:
    112        case GL_RG16F:
    113        case GL_RG32F:
    114        case GL_RG8:
    115        case GL_RG8UI:
    116        case GL_RGB:
    117        case GL_RGB10_A2:
    118        case GL_RGB16F:
    119        case GL_RGB32F:
    120        case GL_RGB565:
    121        case GL_RGB5_A1:
    122        case GL_RGB8:
    123        case GL_RGB8UI:
    124        case GL_RGB9_E5:
    125        case GL_RGBA:
    126        case GL_RGBA16F:
    127        case GL_RGBA32F:
    128        case GL_RGBA4:
    129        case GL_RGBA8:
    130        case GL_RGBA8UI:
    131        case GL_RGBX8_ANGLE:
    132        case GL_SRGB8:
    133        case GL_SRGB8_ALPHA8:
    134        case GL_SRGB_ALPHA_EXT:
    135        case GL_SRGB_EXT:
    136            return true;
    137 
    138        default:
    139            return false;
    140    }
    141 }
    142 
    143 bool IsValidCopySubTextureDestionationInternalFormat(GLenum internalFormat)
    144 {
    145    return IsValidCopyTextureDestinationInternalFormatEnum(internalFormat);
    146 }
    147 
    148 bool IsValidCopyTextureDestinationFormatType(const Context *context,
    149                                             angle::EntryPoint entryPoint,
    150                                             GLint internalFormat,
    151                                             GLenum type)
    152 {
    153    if (!IsValidCopyTextureDestinationInternalFormatEnum(internalFormat))
    154    {
    155        context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
    156                                  internalFormat);
    157        return false;
    158    }
    159 
    160    if (!ValidES3FormatCombination(GetUnsizedFormat(internalFormat), type, internalFormat))
    161    {
    162        context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
    163        return false;
    164    }
    165 
    166    const InternalFormat &internalFormatInfo = GetInternalFormatInfo(internalFormat, type);
    167    if (!internalFormatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
    168    {
    169        context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
    170                                  internalFormat);
    171        return false;
    172    }
    173 
    174    return true;
    175 }
    176 
    177 bool IsValidCopyTextureDestinationTargetEnum(const Context *context, TextureTarget target)
    178 {
    179    switch (target)
    180    {
    181        case TextureTarget::_2D:
    182        case TextureTarget::CubeMapNegativeX:
    183        case TextureTarget::CubeMapNegativeY:
    184        case TextureTarget::CubeMapNegativeZ:
    185        case TextureTarget::CubeMapPositiveX:
    186        case TextureTarget::CubeMapPositiveY:
    187        case TextureTarget::CubeMapPositiveZ:
    188            return true;
    189 
    190        case TextureTarget::Rectangle:
    191            return context->getExtensions().textureRectangleANGLE;
    192 
    193        default:
    194            return false;
    195    }
    196 }
    197 
    198 bool IsValidCopyTextureDestinationTarget(const Context *context,
    199                                         TextureType textureType,
    200                                         TextureTarget target)
    201 {
    202    return TextureTargetToType(target) == textureType;
    203 }
    204 
    205 bool IsValidCopyTextureSourceTarget(const Context *context, TextureType type)
    206 {
    207    switch (type)
    208    {
    209        case TextureType::_2D:
    210            return true;
    211        case TextureType::Rectangle:
    212            return context->getExtensions().textureRectangleANGLE;
    213        case TextureType::External:
    214            return context->getExtensions().EGLImageExternalOES;
    215        case TextureType::VideoImage:
    216            return context->getExtensions().videoTextureWEBGL;
    217        default:
    218            return false;
    219    }
    220 }
    221 
    222 bool IsValidCopyTextureSourceLevel(const Context *context, TextureType type, GLint level)
    223 {
    224    if (!ValidMipLevel(context, type, level))
    225    {
    226        return false;
    227    }
    228 
    229    if (level > 0 && context->getClientVersion() < ES_3_0)
    230    {
    231        return false;
    232    }
    233 
    234    return true;
    235 }
    236 
    237 bool IsValidCopyTextureDestinationLevel(const Context *context,
    238                                        angle::EntryPoint entryPoint,
    239                                        TextureType type,
    240                                        GLint level,
    241                                        GLsizei width,
    242                                        GLsizei height,
    243                                        bool isSubImage)
    244 {
    245    if (!ValidMipLevel(context, type, level))
    246    {
    247        return false;
    248    }
    249 
    250    if (!ValidImageSizeParameters(context, entryPoint, type, level, width, height, 1, isSubImage))
    251    {
    252        return false;
    253    }
    254 
    255    const Caps &caps = context->getCaps();
    256    switch (type)
    257    {
    258        case TextureType::_2D:
    259            return width <= (caps.max2DTextureSize >> level) &&
    260                   height <= (caps.max2DTextureSize >> level);
    261        case TextureType::Rectangle:
    262            ASSERT(level == 0);
    263            return width <= (caps.max2DTextureSize >> level) &&
    264                   height <= (caps.max2DTextureSize >> level);
    265 
    266        case TextureType::CubeMap:
    267            return width <= (caps.maxCubeMapTextureSize >> level) &&
    268                   height <= (caps.maxCubeMapTextureSize >> level);
    269        default:
    270            return true;
    271    }
    272 }
    273 
    274 bool IsValidStencilFunc(GLenum func)
    275 {
    276    switch (func)
    277    {
    278        case GL_NEVER:
    279        case GL_ALWAYS:
    280        case GL_LESS:
    281        case GL_LEQUAL:
    282        case GL_EQUAL:
    283        case GL_GEQUAL:
    284        case GL_GREATER:
    285        case GL_NOTEQUAL:
    286            return true;
    287 
    288        default:
    289            return false;
    290    }
    291 }
    292 
    293 bool IsValidStencilFace(GLenum face)
    294 {
    295    switch (face)
    296    {
    297        case GL_FRONT:
    298        case GL_BACK:
    299        case GL_FRONT_AND_BACK:
    300            return true;
    301 
    302        default:
    303            return false;
    304    }
    305 }
    306 
    307 bool IsValidStencilOp(GLenum op)
    308 {
    309    switch (op)
    310    {
    311        case GL_ZERO:
    312        case GL_KEEP:
    313        case GL_REPLACE:
    314        case GL_INCR:
    315        case GL_DECR:
    316        case GL_INVERT:
    317        case GL_INCR_WRAP:
    318        case GL_DECR_WRAP:
    319            return true;
    320 
    321        default:
    322            return false;
    323    }
    324 }
    325 
    326 static inline bool Valid1to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
    327 {
    328    return (context->getExtensions().textureFloatOES &&
    329            (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F ||
    330             format == GL_R32F)) ||
    331           (context->getExtensions().textureHalfFloatOES &&
    332            (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F ||
    333             format == GL_R16F));
    334 }
    335 
    336 static inline bool Valid2to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
    337 {
    338    return (context->getExtensions().textureFloatOES &&
    339            (format == GL_RGBA32F || format == GL_RGB32F || format == GL_RG32F)) ||
    340           (context->getExtensions().textureHalfFloatOES &&
    341            (format == GL_RGBA16F || format == GL_RGB16F || format == GL_RG16F));
    342 }
    343 
    344 static inline bool Valid3to4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
    345 {
    346    return (context->getExtensions().textureFloatOES &&
    347            (format == GL_RGBA32F || format == GL_RGB32F)) ||
    348           (context->getExtensions().textureHalfFloatOES &&
    349            (format == GL_RGBA16F || format == GL_RGB16F));
    350 }
    351 
    352 static inline bool Valid4ComponentFloatColorBufferFormat(const Context *context, GLenum format)
    353 {
    354    return (context->getExtensions().textureFloatOES && format == GL_RGBA32F) ||
    355           (context->getExtensions().textureHalfFloatOES && format == GL_RGBA16F);
    356 }
    357 
    358 bool ValidateES2CopyTexImageParameters(const Context *context,
    359                                       angle::EntryPoint entryPoint,
    360                                       TextureTarget target,
    361                                       GLint level,
    362                                       GLenum internalformat,
    363                                       bool isSubImage,
    364                                       GLint xoffset,
    365                                       GLint yoffset,
    366                                       GLint x,
    367                                       GLint y,
    368                                       GLsizei width,
    369                                       GLsizei height,
    370                                       GLint border)
    371 {
    372    if (!ValidTexture2DDestinationTarget(context, target))
    373    {
    374        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    375        return false;
    376    }
    377 
    378    TextureType texType = TextureTargetToType(target);
    379    if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1,
    380                                  isSubImage))
    381    {
    382        // Error is already handled.
    383        return false;
    384    }
    385 
    386    Format textureFormat = Format::Invalid();
    387    if (!ValidateCopyTexImageParametersBase(context, entryPoint, target, level, internalformat,
    388                                            isSubImage, xoffset, yoffset, 0, x, y, width, height,
    389                                            border, &textureFormat))
    390    {
    391        return false;
    392    }
    393 
    394    ASSERT(textureFormat.valid() || !isSubImage);
    395 
    396    const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
    397    GLenum colorbufferFormat =
    398        framebuffer->getReadColorAttachment()->getFormat().info->sizedInternalFormat;
    399    const auto &formatInfo = *textureFormat.info;
    400 
    401    // ValidateCopyTexImageParametersBase rejects compressed formats with GL_INVALID_OPERATION.
    402    ASSERT(!formatInfo.compressed);
    403    ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).compressed);
    404 
    405    // ValidateCopyTexImageParametersBase rejects depth formats with GL_INVALID_OPERATION.
    406    ASSERT(!formatInfo.depthBits);
    407    ASSERT(!GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE).depthBits);
    408 
    409    // [OpenGL ES 2.0.24] table 3.9
    410    if (isSubImage)
    411    {
    412        switch (formatInfo.format)
    413        {
    414            case GL_ALPHA:
    415                if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
    416                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
    417                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    418                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    419                {
    420                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    421                    return false;
    422                }
    423                break;
    424            case GL_LUMINANCE:
    425                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
    426                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
    427                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    428                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGRA8_EXT &&
    429                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    430                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    431                    !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    432                {
    433                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    434                    return false;
    435                }
    436                break;
    437            case GL_RED_EXT:
    438                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
    439                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
    440                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    441                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_R32F &&
    442                    colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
    443                    colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
    444                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    445                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    446                    !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    447                {
    448                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    449                    return false;
    450                }
    451                break;
    452            case GL_RG_EXT:
    453                if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
    454                    colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
    455                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES &&
    456                    colorbufferFormat != GL_RG32F && colorbufferFormat != GL_RGB32F &&
    457                    colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
    458                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    459                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    460                    !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    461                {
    462                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    463                    return false;
    464                }
    465                break;
    466            case GL_RGB:
    467                if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
    468                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    469                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGB32F &&
    470                    colorbufferFormat != GL_RGBA32F && colorbufferFormat != GL_BGRA8_EXT &&
    471                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    472                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    473                    !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    474                {
    475                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    476                    return false;
    477                }
    478                break;
    479            case GL_LUMINANCE_ALPHA:
    480            case GL_RGBA:
    481                if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    482                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_RGBA32F &&
    483                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    484                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    485                {
    486                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    487                    return false;
    488                }
    489                break;
    490            default:
    491                context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    492                return false;
    493        }
    494 
    495        if (formatInfo.type == GL_FLOAT && !context->getExtensions().textureFloatOES)
    496        {
    497            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    498            return false;
    499        }
    500    }
    501    else
    502    {
    503        switch (internalformat)
    504        {
    505            case GL_ALPHA:
    506                if (colorbufferFormat != GL_ALPHA8_EXT && colorbufferFormat != GL_RGBA4 &&
    507                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
    508                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    509                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    510                {
    511                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    512                    return false;
    513                }
    514                break;
    515            case GL_LUMINANCE:
    516            case GL_RED_EXT:
    517                if (colorbufferFormat != GL_R8_EXT && colorbufferFormat != GL_RG8_EXT &&
    518                    colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
    519                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    520                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
    521                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    522                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    523                    !Valid1to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    524                {
    525                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    526                    return false;
    527                }
    528                break;
    529            case GL_RG_EXT:
    530                if (colorbufferFormat != GL_RG8_EXT && colorbufferFormat != GL_RGB565 &&
    531                    colorbufferFormat != GL_RGB8_OES && colorbufferFormat != GL_RGBA4 &&
    532                    colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_BGRA8_EXT &&
    533                    colorbufferFormat != GL_RGBA8_OES && colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    534                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    535                    !Valid2to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    536                {
    537                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    538                    return false;
    539                }
    540                break;
    541            case GL_RGB:
    542                if (colorbufferFormat != GL_RGB565 && colorbufferFormat != GL_RGB8_OES &&
    543                    colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    544                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
    545                    colorbufferFormat != GL_BGR5_A1_ANGLEX &&
    546                    colorbufferFormat != GL_BGRX8_ANGLEX && colorbufferFormat != GL_RGBX8_ANGLE &&
    547                    !Valid3to4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    548                {
    549                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    550                    return false;
    551                }
    552                break;
    553            case GL_LUMINANCE_ALPHA:
    554            case GL_RGBA:
    555                if (colorbufferFormat != GL_RGBA4 && colorbufferFormat != GL_RGB5_A1 &&
    556                    colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES &&
    557                    colorbufferFormat != GL_BGR5_A1_ANGLEX && colorbufferFormat != GL_RGBA16F &&
    558                    !Valid4ComponentFloatColorBufferFormat(context, colorbufferFormat))
    559                {
    560                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
    561                    return false;
    562                }
    563                break;
    564            default:
    565                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
    566                                          internalformat);
    567                return false;
    568        }
    569    }
    570 
    571    // If width or height is zero, it is a no-op.  Return false without setting an error.
    572    return (width > 0 && height > 0);
    573 }
    574 
    575 bool ValidCap(const Context *context, GLenum cap, bool queryOnly)
    576 {
    577    switch (cap)
    578    {
    579        // EXT_multisample_compatibility
    580        case GL_MULTISAMPLE_EXT:
    581        case GL_SAMPLE_ALPHA_TO_ONE_EXT:
    582            return context->getExtensions().multisampleCompatibilityEXT;
    583 
    584        case GL_CULL_FACE:
    585        case GL_POLYGON_OFFSET_FILL:
    586        case GL_SAMPLE_ALPHA_TO_COVERAGE:
    587        case GL_SAMPLE_COVERAGE:
    588        case GL_SCISSOR_TEST:
    589        case GL_STENCIL_TEST:
    590        case GL_DEPTH_TEST:
    591        case GL_BLEND:
    592        case GL_DITHER:
    593            return true;
    594 
    595        case GL_PRIMITIVE_RESTART_FIXED_INDEX:
    596        case GL_RASTERIZER_DISCARD:
    597            return (context->getClientMajorVersion() >= 3);
    598 
    599        case GL_DEBUG_OUTPUT_SYNCHRONOUS:
    600        case GL_DEBUG_OUTPUT:
    601            return context->getExtensions().debugKHR;
    602 
    603        case GL_BIND_GENERATES_RESOURCE_CHROMIUM:
    604            return queryOnly && context->getExtensions().bindGeneratesResourceCHROMIUM;
    605 
    606        case GL_CLIENT_ARRAYS_ANGLE:
    607            return queryOnly && context->getExtensions().clientArraysANGLE;
    608 
    609        case GL_FRAMEBUFFER_SRGB_EXT:
    610            return context->getExtensions().sRGBWriteControlEXT;
    611 
    612        case GL_SAMPLE_MASK:
    613            return context->getClientVersion() >= Version(3, 1);
    614 
    615        case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
    616            return queryOnly && context->getExtensions().robustResourceInitializationANGLE;
    617 
    618        case GL_TEXTURE_RECTANGLE_ANGLE:
    619            return context->isWebGL();
    620 
    621        // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance
    622        case GL_CLIP_DISTANCE0_EXT:
    623        case GL_CLIP_DISTANCE1_EXT:
    624        case GL_CLIP_DISTANCE2_EXT:
    625        case GL_CLIP_DISTANCE3_EXT:
    626        case GL_CLIP_DISTANCE4_EXT:
    627        case GL_CLIP_DISTANCE5_EXT:
    628        case GL_CLIP_DISTANCE6_EXT:
    629        case GL_CLIP_DISTANCE7_EXT:
    630            if (context->getExtensions().clipDistanceAPPLE ||
    631                context->getExtensions().clipCullDistanceEXT)
    632            {
    633                return true;
    634            }
    635            break;
    636        case GL_SAMPLE_SHADING:
    637            return context->getExtensions().sampleShadingOES;
    638        case GL_SHADING_RATE_PRESERVE_ASPECT_RATIO_QCOM:
    639            return context->getExtensions().shadingRateQCOM;
    640 
    641        // COLOR_LOGIC_OP is in GLES1, but exposed through an ANGLE extension.
    642        case GL_COLOR_LOGIC_OP:
    643            return context->getClientVersion() < Version(2, 0) ||
    644                   context->getExtensions().logicOpANGLE;
    645 
    646        default:
    647            break;
    648    }
    649 
    650    // GLES1 emulation: GLES1-specific caps after this point
    651    if (context->getClientVersion().major != 1)
    652    {
    653        return false;
    654    }
    655 
    656    switch (cap)
    657    {
    658        case GL_ALPHA_TEST:
    659        case GL_VERTEX_ARRAY:
    660        case GL_NORMAL_ARRAY:
    661        case GL_COLOR_ARRAY:
    662        case GL_TEXTURE_COORD_ARRAY:
    663        case GL_TEXTURE_2D:
    664        case GL_LIGHTING:
    665        case GL_LIGHT0:
    666        case GL_LIGHT1:
    667        case GL_LIGHT2:
    668        case GL_LIGHT3:
    669        case GL_LIGHT4:
    670        case GL_LIGHT5:
    671        case GL_LIGHT6:
    672        case GL_LIGHT7:
    673        case GL_NORMALIZE:
    674        case GL_RESCALE_NORMAL:
    675        case GL_COLOR_MATERIAL:
    676        case GL_CLIP_PLANE0:
    677        case GL_CLIP_PLANE1:
    678        case GL_CLIP_PLANE2:
    679        case GL_CLIP_PLANE3:
    680        case GL_CLIP_PLANE4:
    681        case GL_CLIP_PLANE5:
    682        case GL_FOG:
    683        case GL_POINT_SMOOTH:
    684        case GL_LINE_SMOOTH:
    685            return context->getClientVersion() < Version(2, 0);
    686        case GL_POINT_SIZE_ARRAY_OES:
    687            return context->getClientVersion() < Version(2, 0) &&
    688                   context->getExtensions().pointSizeArrayOES;
    689        case GL_TEXTURE_CUBE_MAP:
    690            return context->getClientVersion() < Version(2, 0) &&
    691                   context->getExtensions().textureCubeMapOES;
    692        case GL_POINT_SPRITE_OES:
    693            return context->getClientVersion() < Version(2, 0) &&
    694                   context->getExtensions().pointSpriteOES;
    695        default:
    696            return false;
    697    }
    698 }
    699 
    700 // Return true if a character belongs to the ASCII subset as defined in GLSL ES 1.0 spec section
    701 // 3.1.
    702 bool IsValidESSLCharacter(unsigned char c)
    703 {
    704    // Printing characters are valid except " $ ` @ \ ' DEL.
    705    if (c >= 32 && c <= 126 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' &&
    706        c != '\'')
    707    {
    708        return true;
    709    }
    710 
    711    // Horizontal tab, line feed, vertical tab, form feed, carriage return are also valid.
    712    if (c >= 9 && c <= 13)
    713    {
    714        return true;
    715    }
    716 
    717    return false;
    718 }
    719 
    720 bool IsValidESSLString(const char *str, size_t len)
    721 {
    722    for (size_t i = 0; i < len; i++)
    723    {
    724        if (!IsValidESSLCharacter(str[i]))
    725        {
    726            return false;
    727        }
    728    }
    729 
    730    return true;
    731 }
    732 
    733 bool ValidateWebGLNamePrefix(const Context *context,
    734                             angle::EntryPoint entryPoint,
    735                             const GLchar *name)
    736 {
    737    ASSERT(context->isWebGL());
    738 
    739    // WebGL 1.0 [Section 6.16] GLSL Constructs
    740    // Identifiers starting with "webgl_" and "_webgl_" are reserved for use by WebGL.
    741    if (strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
    742    {
    743        context->validationError(entryPoint, GL_INVALID_OPERATION,
    744                                 kWebglBindAttribLocationReservedPrefix);
    745        return false;
    746    }
    747 
    748    return true;
    749 }
    750 
    751 bool ValidateWebGLNameLength(const Context *context, angle::EntryPoint entryPoint, size_t length)
    752 {
    753    ASSERT(context->isWebGL());
    754 
    755    if (context->isWebGL1() && length > 256)
    756    {
    757        // WebGL 1.0 [Section 6.21] Maxmimum Uniform and Attribute Location Lengths
    758        // WebGL imposes a limit of 256 characters on the lengths of uniform and attribute
    759        // locations.
    760        context->validationError(entryPoint, GL_INVALID_VALUE, kWebglNameLengthLimitExceeded);
    761 
    762        return false;
    763    }
    764    else if (length > 1024)
    765    {
    766        // WebGL 2.0 [Section 4.3.2] WebGL 2.0 imposes a limit of 1024 characters on the lengths of
    767        // uniform and attribute locations.
    768        context->validationError(entryPoint, GL_INVALID_VALUE, kWebgl2NameLengthLimitExceeded);
    769        return false;
    770    }
    771 
    772    return true;
    773 }
    774 
    775 bool ValidBlendFunc(const Context *context, GLenum val)
    776 {
    777    const Extensions &ext = context->getExtensions();
    778 
    779    // these are always valid for src and dst.
    780    switch (val)
    781    {
    782        case GL_ZERO:
    783        case GL_ONE:
    784        case GL_SRC_COLOR:
    785        case GL_ONE_MINUS_SRC_COLOR:
    786        case GL_DST_COLOR:
    787        case GL_ONE_MINUS_DST_COLOR:
    788        case GL_SRC_ALPHA:
    789        case GL_ONE_MINUS_SRC_ALPHA:
    790        case GL_DST_ALPHA:
    791        case GL_ONE_MINUS_DST_ALPHA:
    792        case GL_CONSTANT_COLOR:
    793        case GL_ONE_MINUS_CONSTANT_COLOR:
    794        case GL_CONSTANT_ALPHA:
    795        case GL_ONE_MINUS_CONSTANT_ALPHA:
    796            return true;
    797 
    798        // EXT_blend_func_extended.
    799        case GL_SRC1_COLOR_EXT:
    800        case GL_SRC1_ALPHA_EXT:
    801        case GL_ONE_MINUS_SRC1_COLOR_EXT:
    802        case GL_ONE_MINUS_SRC1_ALPHA_EXT:
    803        case GL_SRC_ALPHA_SATURATE_EXT:
    804            return ext.blendFuncExtendedEXT;
    805 
    806        default:
    807            return false;
    808    }
    809 }
    810 
    811 bool ValidSrcBlendFunc(const Context *context, GLenum val)
    812 {
    813    if (ValidBlendFunc(context, val))
    814        return true;
    815 
    816    if (val == GL_SRC_ALPHA_SATURATE)
    817        return true;
    818 
    819    return false;
    820 }
    821 
    822 bool ValidDstBlendFunc(const Context *context, GLenum val)
    823 {
    824    if (ValidBlendFunc(context, val))
    825        return true;
    826 
    827    if (val == GL_SRC_ALPHA_SATURATE)
    828    {
    829        if (context->getClientMajorVersion() >= 3)
    830            return true;
    831    }
    832 
    833    return false;
    834 }
    835 
    836 bool ValidateES2TexImageParameters(const Context *context,
    837                                   angle::EntryPoint entryPoint,
    838                                   TextureTarget target,
    839                                   GLint level,
    840                                   GLenum internalformat,
    841                                   bool isCompressed,
    842                                   bool isSubImage,
    843                                   GLint xoffset,
    844                                   GLint yoffset,
    845                                   GLsizei width,
    846                                   GLsizei height,
    847                                   GLint border,
    848                                   GLenum format,
    849                                   GLenum type,
    850                                   GLsizei imageSize,
    851                                   const void *pixels)
    852 {
    853    if (!ValidTexture2DDestinationTarget(context, target))
    854    {
    855        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    856        return false;
    857    }
    858 
    859    return ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
    860                                             isCompressed, isSubImage, xoffset, yoffset, width,
    861                                             height, border, format, type, imageSize, pixels);
    862 }
    863 
    864 }  // anonymous namespace
    865 
    866 bool ValidateES2TexImageParametersBase(const Context *context,
    867                                       angle::EntryPoint entryPoint,
    868                                       TextureTarget target,
    869                                       GLint level,
    870                                       GLenum internalformat,
    871                                       bool isCompressed,
    872                                       bool isSubImage,
    873                                       GLint xoffset,
    874                                       GLint yoffset,
    875                                       GLsizei width,
    876                                       GLsizei height,
    877                                       GLint border,
    878                                       GLenum format,
    879                                       GLenum type,
    880                                       GLsizei imageSize,
    881                                       const void *pixels)
    882 {
    883 
    884    TextureType texType = TextureTargetToType(target);
    885    if (!ValidImageSizeParameters(context, entryPoint, texType, level, width, height, 1,
    886                                  isSubImage))
    887    {
    888        // Error already handled.
    889        return false;
    890    }
    891 
    892    if (!ValidMipLevel(context, texType, level))
    893    {
    894        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
    895        return false;
    896    }
    897 
    898    if ((xoffset < 0 || std::numeric_limits<GLsizei>::max() - xoffset < width) ||
    899        (yoffset < 0 || std::numeric_limits<GLsizei>::max() - yoffset < height))
    900    {
    901        context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    902        return false;
    903    }
    904 
    905    const Caps &caps = context->getCaps();
    906 
    907    switch (texType)
    908    {
    909        case TextureType::_2D:
    910        case TextureType::External:
    911        case TextureType::VideoImage:
    912            if (width > (caps.max2DTextureSize >> level) ||
    913                height > (caps.max2DTextureSize >> level))
    914            {
    915                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    916                return false;
    917            }
    918            break;
    919 
    920        case TextureType::Rectangle:
    921            ASSERT(level == 0);
    922            if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
    923            {
    924                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    925                return false;
    926            }
    927            if (isCompressed)
    928            {
    929                context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
    930                return false;
    931            }
    932            break;
    933 
    934        case TextureType::CubeMap:
    935            if (!isSubImage && width != height)
    936            {
    937                context->validationError(entryPoint, GL_INVALID_VALUE,
    938                                         kCubemapFacesEqualDimensions);
    939                return false;
    940            }
    941 
    942            if (width > (caps.maxCubeMapTextureSize >> level) ||
    943                height > (caps.maxCubeMapTextureSize >> level))
    944            {
    945                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
    946                return false;
    947            }
    948            break;
    949 
    950        default:
    951            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
    952            return false;
    953    }
    954 
    955    Texture *texture = context->getTextureByType(texType);
    956    if (!texture)
    957    {
    958        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
    959        return false;
    960    }
    961 
    962    // Verify zero border
    963    if (border != 0)
    964    {
    965        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder);
    966        return false;
    967    }
    968 
    969    bool nonEqualFormatsAllowed = false;
    970 
    971    if (isCompressed)
    972    {
    973        GLenum actualInternalFormat =
    974            isSubImage ? texture->getFormat(target, level).info->sizedInternalFormat
    975                       : internalformat;
    976 
    977        const InternalFormat &internalFormatInfo = GetSizedInternalFormatInfo(actualInternalFormat);
    978 
    979        if (!internalFormatInfo.compressed && !internalFormatInfo.paletted)
    980        {
    981            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kInvalidInternalFormat,
    982                                      internalformat);
    983            return false;
    984        }
    985 
    986        if (!internalFormatInfo.textureSupport(context->getClientVersion(),
    987                                               context->getExtensions()))
    988        {
    989            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kInvalidInternalFormat,
    990                                      internalformat);
    991            return false;
    992        }
    993 
    994        if (isSubImage)
    995        {
    996            // From OpenGL ES Version 1.1.12, section 3.7.4 Compressed Paletted
    997            // Textures:
    998            //
    999            // Subimages may not be specified for compressed paletted textures.
   1000            // Calling CompressedTexSubImage2D with any of the PALETTE*
   1001            // arguments in table 3.11 will generate an INVALID OPERATION error.
   1002            if (internalFormatInfo.paletted)
   1003            {
   1004                context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
   1005                                          internalformat);
   1006                return false;
   1007            }
   1008 
   1009            // From the OES_compressed_ETC1_RGB8_texture spec:
   1010            //
   1011            // INVALID_OPERATION is generated by CompressedTexSubImage2D, TexSubImage2D, or
   1012            // CopyTexSubImage2D if the texture image <level> bound to <target> has internal format
   1013            // ETC1_RGB8_OES.
   1014            //
   1015            // This is relaxed if GL_EXT_compressed_ETC1_RGB8_sub_texture is supported.
   1016            if (IsETC1Format(actualInternalFormat) &&
   1017                !context->getExtensions().compressedETC1RGB8SubTextureEXT)
   1018            {
   1019                context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
   1020                                          internalformat);
   1021                return false;
   1022            }
   1023 
   1024            if (!ValidCompressedSubImageSize(context, actualInternalFormat, xoffset, yoffset, 0,
   1025                                             width, height, 1, texture->getWidth(target, level),
   1026                                             texture->getHeight(target, level),
   1027                                             texture->getDepth(target, level)))
   1028            {
   1029                context->validationError(entryPoint, GL_INVALID_OPERATION,
   1030                                         kInvalidCompressedImageSize);
   1031                return false;
   1032            }
   1033 
   1034            if (format != actualInternalFormat)
   1035            {
   1036                context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
   1037                return false;
   1038            }
   1039        }
   1040        else
   1041        {
   1042            if (!ValidCompressedImageSize(context, actualInternalFormat, level, width, height, 1))
   1043            {
   1044                context->validationError(entryPoint, GL_INVALID_OPERATION,
   1045                                         kInvalidCompressedImageSize);
   1046                return false;
   1047            }
   1048        }
   1049    }
   1050    else
   1051    {
   1052        // validate <type> by itself (used as secondary key below)
   1053        switch (type)
   1054        {
   1055            case GL_UNSIGNED_BYTE:
   1056            case GL_UNSIGNED_SHORT_5_6_5:
   1057            case GL_UNSIGNED_SHORT_4_4_4_4:
   1058            case GL_UNSIGNED_SHORT_5_5_5_1:
   1059            case GL_UNSIGNED_SHORT:
   1060            case GL_UNSIGNED_INT:
   1061            case GL_UNSIGNED_INT_24_8_OES:
   1062            case GL_HALF_FLOAT_OES:
   1063            case GL_FLOAT:
   1064                break;
   1065            case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
   1066                if (!context->getExtensions().textureType2101010REVEXT)
   1067                {
   1068                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type);
   1069                    return false;
   1070                }
   1071                break;
   1072            default:
   1073                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
   1074                return false;
   1075        }
   1076 
   1077        // validate <format> + <type> combinations
   1078        // - invalid <format> -> sets INVALID_ENUM
   1079        // - invalid <format>+<type> combination -> sets INVALID_OPERATION
   1080        switch (format)
   1081        {
   1082            case GL_ALPHA:
   1083            case GL_LUMINANCE:
   1084            case GL_LUMINANCE_ALPHA:
   1085                switch (type)
   1086                {
   1087                    case GL_UNSIGNED_BYTE:
   1088                    case GL_FLOAT:
   1089                    case GL_HALF_FLOAT_OES:
   1090                        break;
   1091                    default:
   1092                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1093                                                 kMismatchedTypeAndFormat);
   1094                        return false;
   1095                }
   1096                break;
   1097            case GL_RED:
   1098            case GL_RG:
   1099                if (!context->getExtensions().textureRgEXT)
   1100                {
   1101                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1102                                              format);
   1103                    return false;
   1104                }
   1105                switch (type)
   1106                {
   1107                    case GL_UNSIGNED_BYTE:
   1108                        break;
   1109                    case GL_FLOAT:
   1110                        if (!context->getExtensions().textureFloatOES)
   1111                        {
   1112                            context->validationErrorF(entryPoint, GL_INVALID_ENUM,
   1113                                                      kEnumNotSupported, type);
   1114                            return false;
   1115                        }
   1116                        break;
   1117                    case GL_HALF_FLOAT_OES:
   1118                        if (!context->getExtensions().textureFloatOES &&
   1119                            !context->getExtensions().textureHalfFloatOES)
   1120                        {
   1121                            context->validationErrorF(entryPoint, GL_INVALID_ENUM,
   1122                                                      kEnumNotSupported, type);
   1123                            return false;
   1124                        }
   1125                        break;
   1126                    case GL_SHORT:
   1127                    case GL_UNSIGNED_SHORT:
   1128                        if (!context->getExtensions().textureNorm16EXT)
   1129                        {
   1130                            context->validationErrorF(entryPoint, GL_INVALID_ENUM,
   1131                                                      kEnumNotSupported, type);
   1132                            return false;
   1133                        }
   1134                        break;
   1135                    default:
   1136                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1137                                                 kMismatchedTypeAndFormat);
   1138                        return false;
   1139                }
   1140                break;
   1141            case GL_RGB:
   1142                switch (type)
   1143                {
   1144                    case GL_UNSIGNED_BYTE:
   1145                    case GL_UNSIGNED_SHORT_5_6_5:
   1146                    case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
   1147                    case GL_FLOAT:
   1148                    case GL_HALF_FLOAT_OES:
   1149                        break;
   1150                    case GL_SHORT:
   1151                    case GL_UNSIGNED_SHORT:
   1152                        if (!context->getExtensions().textureNorm16EXT)
   1153                        {
   1154                            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1155                                                     kMismatchedTypeAndFormat);
   1156                            return false;
   1157                        }
   1158                        break;
   1159                    default:
   1160                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1161                                                 kMismatchedTypeAndFormat);
   1162                        return false;
   1163                }
   1164                break;
   1165            case GL_RGBA:
   1166                switch (type)
   1167                {
   1168                    case GL_UNSIGNED_BYTE:
   1169                    case GL_UNSIGNED_SHORT_4_4_4_4:
   1170                    case GL_UNSIGNED_SHORT_5_5_5_1:
   1171                    case GL_FLOAT:
   1172                    case GL_HALF_FLOAT_OES:
   1173                    case GL_UNSIGNED_INT_2_10_10_10_REV_EXT:
   1174                        break;
   1175                    case GL_SHORT:
   1176                    case GL_UNSIGNED_SHORT:
   1177                        if (!context->getExtensions().textureNorm16EXT)
   1178                        {
   1179                            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1180                                                     kMismatchedTypeAndFormat);
   1181                            return false;
   1182                        }
   1183                        break;
   1184                    default:
   1185                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1186                                                 kMismatchedTypeAndFormat);
   1187                        return false;
   1188                }
   1189                break;
   1190            case GL_BGRA_EXT:
   1191                if (!context->getExtensions().textureFormatBGRA8888EXT)
   1192                {
   1193                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1194                                              format);
   1195                    return false;
   1196                }
   1197                switch (type)
   1198                {
   1199                    case GL_UNSIGNED_BYTE:
   1200                        break;
   1201                    default:
   1202                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1203                                                 kMismatchedTypeAndFormat);
   1204                        return false;
   1205                }
   1206                break;
   1207            case GL_SRGB_EXT:
   1208            case GL_SRGB_ALPHA_EXT:
   1209                if (!context->getExtensions().sRGBEXT)
   1210                {
   1211                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1212                                              format);
   1213                    return false;
   1214                }
   1215                switch (type)
   1216                {
   1217                    case GL_UNSIGNED_BYTE:
   1218                        break;
   1219                    default:
   1220                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1221                                                 kMismatchedTypeAndFormat);
   1222                        return false;
   1223                }
   1224                break;
   1225            case GL_DEPTH_COMPONENT:
   1226                switch (type)
   1227                {
   1228                    case GL_UNSIGNED_SHORT:
   1229                    case GL_UNSIGNED_INT:
   1230                        break;
   1231                    case GL_FLOAT:
   1232                        if (!context->getExtensions().depthBufferFloat2NV)
   1233                        {
   1234                            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1235                                                     kMismatchedTypeAndFormat);
   1236                            return false;
   1237                        }
   1238                        break;
   1239                    default:
   1240                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1241                                                 kMismatchedTypeAndFormat);
   1242                        return false;
   1243                }
   1244                break;
   1245            case GL_DEPTH_STENCIL_OES:
   1246                switch (type)
   1247                {
   1248                    case GL_UNSIGNED_INT_24_8_OES:
   1249                        break;
   1250                    default:
   1251                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1252                                                 kMismatchedTypeAndFormat);
   1253                        return false;
   1254                }
   1255                break;
   1256            case GL_STENCIL_INDEX:
   1257                switch (type)
   1258                {
   1259                    case GL_UNSIGNED_BYTE:
   1260                        break;
   1261                    default:
   1262                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1263                                                 kMismatchedTypeAndFormat);
   1264                        return false;
   1265                }
   1266                break;
   1267            default:
   1268                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, format);
   1269                return false;
   1270        }
   1271 
   1272        switch (format)
   1273        {
   1274            case GL_DEPTH_COMPONENT:
   1275            case GL_DEPTH_STENCIL_OES:
   1276                if (!context->getExtensions().depthTextureANGLE &&
   1277                    !((context->getExtensions().packedDepthStencilOES ||
   1278                       context->getExtensions().depthTextureCubeMapOES) &&
   1279                      context->getExtensions().depthTextureOES))
   1280                {
   1281                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1282                                              format);
   1283                    return false;
   1284                }
   1285 
   1286                switch (target)
   1287                {
   1288                    case TextureTarget::_2D:
   1289                        break;
   1290                    case TextureTarget::CubeMapNegativeX:
   1291                    case TextureTarget::CubeMapNegativeY:
   1292                    case TextureTarget::CubeMapNegativeZ:
   1293                    case TextureTarget::CubeMapPositiveX:
   1294                    case TextureTarget::CubeMapPositiveY:
   1295                    case TextureTarget::CubeMapPositiveZ:
   1296                        if (!context->getExtensions().depthTextureCubeMapOES)
   1297                        {
   1298                            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1299                                                     kMismatchedTargetAndFormat);
   1300                            return false;
   1301                        }
   1302                        break;
   1303                    default:
   1304                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1305                                                 kMismatchedTargetAndFormat);
   1306                        return false;
   1307                }
   1308 
   1309                // OES_depth_texture supports loading depth data and multiple levels,
   1310                // but ANGLE_depth_texture does not
   1311                if (!context->getExtensions().depthTextureOES)
   1312                {
   1313                    if (pixels != nullptr)
   1314                    {
   1315                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1316                                                 kPixelDataNotNull);
   1317                        return false;
   1318                    }
   1319                    if (level != 0)
   1320                    {
   1321                        context->validationError(entryPoint, GL_INVALID_OPERATION, kLevelNotZero);
   1322                        return false;
   1323                    }
   1324                }
   1325                break;
   1326            case GL_STENCIL_INDEX:
   1327                if (!context->getExtensions().textureStencil8OES)
   1328                {
   1329                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
   1330                    return false;
   1331                }
   1332 
   1333                switch (target)
   1334                {
   1335                    case TextureTarget::_2D:
   1336                    case TextureTarget::_2DArray:
   1337                    case TextureTarget::CubeMapNegativeX:
   1338                    case TextureTarget::CubeMapNegativeY:
   1339                    case TextureTarget::CubeMapNegativeZ:
   1340                    case TextureTarget::CubeMapPositiveX:
   1341                    case TextureTarget::CubeMapPositiveY:
   1342                    case TextureTarget::CubeMapPositiveZ:
   1343                        break;
   1344                    default:
   1345                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1346                                                 kMismatchedTargetAndFormat);
   1347                        return false;
   1348                }
   1349 
   1350                if (internalformat != GL_STENCIL_INDEX8)
   1351                {
   1352                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   1353                                             kMismatchedTargetAndFormat);
   1354                    return false;
   1355                }
   1356                break;
   1357            default:
   1358                break;
   1359        }
   1360 
   1361        if (!isSubImage)
   1362        {
   1363            switch (internalformat)
   1364            {
   1365                // Core ES 2.0 formats
   1366                case GL_ALPHA:
   1367                case GL_LUMINANCE:
   1368                case GL_LUMINANCE_ALPHA:
   1369                case GL_RGB:
   1370                case GL_RGBA:
   1371                    break;
   1372 
   1373                case GL_RGBA32F:
   1374                    if (!context->getExtensions().colorBufferFloatRgbaCHROMIUM)
   1375                    {
   1376                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1377                        return false;
   1378                    }
   1379 
   1380                    nonEqualFormatsAllowed = true;
   1381 
   1382                    if (type != GL_FLOAT)
   1383                    {
   1384                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1385                                                 kMismatchedTypeAndFormat);
   1386                        return false;
   1387                    }
   1388                    if (format != GL_RGBA)
   1389                    {
   1390                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1391                                                 kMismatchedTypeAndFormat);
   1392                        return false;
   1393                    }
   1394                    break;
   1395 
   1396                case GL_RGB32F:
   1397                    if (!context->getExtensions().colorBufferFloatRgbCHROMIUM)
   1398                    {
   1399                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1400                        return false;
   1401                    }
   1402 
   1403                    nonEqualFormatsAllowed = true;
   1404 
   1405                    if (type != GL_FLOAT)
   1406                    {
   1407                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1408                                                 kMismatchedTypeAndFormat);
   1409                        return false;
   1410                    }
   1411                    if (format != GL_RGB)
   1412                    {
   1413                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1414                                                 kMismatchedTypeAndFormat);
   1415                        return false;
   1416                    }
   1417                    break;
   1418 
   1419                case GL_BGRA_EXT:
   1420                    if (!context->getExtensions().textureFormatBGRA8888EXT)
   1421                    {
   1422                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1423                        return false;
   1424                    }
   1425                    break;
   1426 
   1427                case GL_DEPTH_COMPONENT:
   1428                    if (!(context->getExtensions().depthTextureAny()))
   1429                    {
   1430                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1431                        return false;
   1432                    }
   1433                    break;
   1434 
   1435                case GL_DEPTH_STENCIL:
   1436                    if (!(context->getExtensions().depthTextureANGLE ||
   1437                          context->getExtensions().packedDepthStencilOES ||
   1438                          context->getExtensions().depthTextureCubeMapOES))
   1439                    {
   1440                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1441                        return false;
   1442                    }
   1443                    break;
   1444 
   1445                case GL_STENCIL_INDEX8:
   1446                    if (!context->getExtensions().textureStencil8OES)
   1447                    {
   1448                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1449                        return false;
   1450                    }
   1451                    break;
   1452 
   1453                case GL_RED:
   1454                case GL_RG:
   1455                    if (!context->getExtensions().textureRgEXT)
   1456                    {
   1457                        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1458                        return false;
   1459                    }
   1460                    break;
   1461 
   1462                case GL_SRGB_EXT:
   1463                case GL_SRGB_ALPHA_EXT:
   1464                    if (!context->getExtensions().sRGBEXT)
   1465                    {
   1466                        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1467                                                  internalformat);
   1468                        return false;
   1469                    }
   1470                    break;
   1471 
   1472                case GL_RGB10_A2_EXT:
   1473                    if (!context->getExtensions().textureType2101010REVEXT)
   1474                    {
   1475                        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1476                                                  internalformat);
   1477                        return false;
   1478                    }
   1479 
   1480                    if (type != GL_UNSIGNED_INT_2_10_10_10_REV_EXT || format != GL_RGBA)
   1481                    {
   1482                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1483                                                 kMismatchedTypeAndFormat);
   1484                        return false;
   1485                    }
   1486 
   1487                    nonEqualFormatsAllowed = true;
   1488 
   1489                    break;
   1490 
   1491                case GL_RGB5_A1:
   1492                    if (context->getExtensions().textureType2101010REVEXT &&
   1493                        type == GL_UNSIGNED_INT_2_10_10_10_REV_EXT && format == GL_RGBA)
   1494                    {
   1495                        nonEqualFormatsAllowed = true;
   1496                    }
   1497 
   1498                    break;
   1499 
   1500                case GL_RGBX8_ANGLE:
   1501                    if (context->getExtensions().rgbxInternalFormatANGLE &&
   1502                        type == GL_UNSIGNED_BYTE && format == GL_RGB)
   1503                    {
   1504                        nonEqualFormatsAllowed = true;
   1505                    }
   1506 
   1507                    break;
   1508 
   1509                case GL_R16_EXT:
   1510                case GL_RG16_EXT:
   1511                case GL_RGB16_EXT:
   1512                case GL_RGBA16_EXT:
   1513                case GL_R16_SNORM_EXT:
   1514                case GL_RG16_SNORM_EXT:
   1515                case GL_RGB16_SNORM_EXT:
   1516                case GL_RGBA16_SNORM_EXT:
   1517                    if (!context->getExtensions().textureNorm16EXT)
   1518                    {
   1519                        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1520                                                  internalformat);
   1521                        return false;
   1522                    }
   1523                    break;
   1524                default:
   1525                    // Compressed formats are not valid internal formats for glTexImage*D
   1526                    context->validationErrorF(entryPoint, GL_INVALID_VALUE, kInvalidInternalFormat,
   1527                                              internalformat);
   1528                    return false;
   1529            }
   1530        }
   1531 
   1532        if (type == GL_FLOAT)
   1533        {
   1534            if (!context->getExtensions().textureFloatOES)
   1535            {
   1536                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type);
   1537                return false;
   1538            }
   1539        }
   1540        else if (type == GL_HALF_FLOAT_OES)
   1541        {
   1542            if (!context->getExtensions().textureHalfFloatOES)
   1543            {
   1544                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, type);
   1545                return false;
   1546            }
   1547        }
   1548    }
   1549 
   1550    if (isSubImage)
   1551    {
   1552        const InternalFormat &textureInternalFormat = *texture->getFormat(target, level).info;
   1553        if (textureInternalFormat.internalFormat == GL_NONE)
   1554        {
   1555            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureLevel);
   1556            return false;
   1557        }
   1558 
   1559        if (format != textureInternalFormat.format)
   1560        {
   1561            context->validationError(entryPoint, GL_INVALID_OPERATION, err::kTextureFormatMismatch);
   1562            return false;
   1563        }
   1564 
   1565        if (context->isWebGL())
   1566        {
   1567            if (GetInternalFormatInfo(format, type).sizedInternalFormat !=
   1568                textureInternalFormat.sizedInternalFormat)
   1569            {
   1570                context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureTypeMismatch);
   1571                return false;
   1572            }
   1573        }
   1574 
   1575        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
   1576            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
   1577        {
   1578            context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
   1579            return false;
   1580        }
   1581 
   1582        if (width > 0 && height > 0 && pixels == nullptr &&
   1583            context->getState().getTargetBuffer(BufferBinding::PixelUnpack) == nullptr)
   1584        {
   1585            context->validationError(entryPoint, GL_INVALID_VALUE, kPixelDataNull);
   1586            return false;
   1587        }
   1588    }
   1589    else
   1590    {
   1591        if (texture->getImmutableFormat())
   1592        {
   1593            context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
   1594            return false;
   1595        }
   1596    }
   1597 
   1598    // From GL_CHROMIUM_color_buffer_float_rgb[a]:
   1599    // GL_RGB[A] / GL_RGB[A]32F becomes an allowable format / internalformat parameter pair for
   1600    // TexImage2D. The restriction in section 3.7.1 of the OpenGL ES 2.0 spec that the
   1601    // internalformat parameter and format parameter of TexImage2D must match is lifted for this
   1602    // case.
   1603    if (!isSubImage && !isCompressed && internalformat != format && !nonEqualFormatsAllowed)
   1604    {
   1605        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination);
   1606        return false;
   1607    }
   1608 
   1609    GLenum sizeCheckFormat = isSubImage ? format : internalformat;
   1610    return ValidImageDataSize(context, entryPoint, texType, width, height, 1, sizeCheckFormat, type,
   1611                              pixels, imageSize);
   1612 }
   1613 
   1614 bool ValidateES2TexStorageParametersBase(const Context *context,
   1615                                         angle::EntryPoint entryPoint,
   1616                                         TextureType target,
   1617                                         GLsizei levels,
   1618                                         GLenum internalformat,
   1619                                         GLsizei width,
   1620                                         GLsizei height)
   1621 {
   1622    if (target != TextureType::_2D && target != TextureType::CubeMap &&
   1623        target != TextureType::Rectangle)
   1624    {
   1625        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   1626        return false;
   1627    }
   1628 
   1629    if (width < 1 || height < 1 || levels < 1)
   1630    {
   1631        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
   1632        return false;
   1633    }
   1634 
   1635    if (target == TextureType::CubeMap && width != height)
   1636    {
   1637        context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
   1638        return false;
   1639    }
   1640 
   1641    if (levels != 1 && levels != log2(std::max(width, height)) + 1)
   1642    {
   1643        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
   1644        return false;
   1645    }
   1646 
   1647    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
   1648    if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE)
   1649    {
   1650        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1651        return false;
   1652    }
   1653 
   1654    const Caps &caps = context->getCaps();
   1655 
   1656    switch (target)
   1657    {
   1658        case TextureType::_2D:
   1659            if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
   1660            {
   1661                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1662                return false;
   1663            }
   1664            break;
   1665        case TextureType::Rectangle:
   1666            if (levels != 1)
   1667            {
   1668                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   1669                return false;
   1670            }
   1671 
   1672            if (width > caps.maxRectangleTextureSize || height > caps.maxRectangleTextureSize)
   1673            {
   1674                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1675                return false;
   1676            }
   1677            if (formatInfo.compressed)
   1678            {
   1679                context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
   1680                return false;
   1681            }
   1682            break;
   1683        case TextureType::CubeMap:
   1684            if (width > caps.maxCubeMapTextureSize || height > caps.maxCubeMapTextureSize)
   1685            {
   1686                context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   1687                return false;
   1688            }
   1689            break;
   1690        case TextureType::InvalidEnum:
   1691            context->validationError(entryPoint, GL_INVALID_ENUM, kEnumInvalid);
   1692            return false;
   1693        default:
   1694            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   1695                                      ToGLenum(target));
   1696            return false;
   1697    }
   1698 
   1699    if (levels != 1 && !context->getExtensions().textureNpotOES)
   1700    {
   1701        if (!isPow2(width) || !isPow2(height))
   1702        {
   1703            context->validationError(entryPoint, GL_INVALID_OPERATION, kDimensionsMustBePow2);
   1704            return false;
   1705        }
   1706    }
   1707 
   1708    if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
   1709    {
   1710        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   1711        return false;
   1712    }
   1713 
   1714    // Even with OES_texture_npot, some compressed formats may impose extra restrictions.
   1715    if (formatInfo.compressed)
   1716    {
   1717        if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, 1))
   1718        {
   1719            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidCompressedImageSize);
   1720            return false;
   1721        }
   1722    }
   1723 
   1724    switch (internalformat)
   1725    {
   1726        case GL_DEPTH_COMPONENT16:
   1727        case GL_DEPTH_COMPONENT32_OES:
   1728            switch (target)
   1729            {
   1730                case TextureType::_2D:
   1731                    break;
   1732                case TextureType::CubeMap:
   1733                    if (!context->getExtensions().depthTextureCubeMapOES)
   1734                    {
   1735                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1736                                                 kInvalidTextureTarget);
   1737                        return false;
   1738                    }
   1739                    break;
   1740                default:
   1741                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   1742                                             kInvalidTextureTarget);
   1743                    return false;
   1744            }
   1745 
   1746            // ANGLE_depth_texture only supports 1-level textures
   1747            if (!context->getExtensions().depthTextureOES)
   1748            {
   1749                if (levels != 1)
   1750                {
   1751                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
   1752                    return false;
   1753                }
   1754            }
   1755            break;
   1756        case GL_DEPTH24_STENCIL8_OES:
   1757            switch (target)
   1758            {
   1759                case TextureType::_2D:
   1760                    break;
   1761                case TextureType::CubeMap:
   1762                    if (!context->getExtensions().depthTextureCubeMapOES)
   1763                    {
   1764                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1765                                                 kInvalidTextureTarget);
   1766                        return false;
   1767                    }
   1768                    break;
   1769                default:
   1770                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   1771                                             kInvalidTextureTarget);
   1772                    return false;
   1773            }
   1774 
   1775            if (!context->getExtensions().packedDepthStencilOES &&
   1776                !context->getExtensions().depthTextureCubeMapOES)
   1777            {
   1778                // ANGLE_depth_texture only supports 1-level textures
   1779                if (levels != 1)
   1780                {
   1781                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidMipLevels);
   1782                    return false;
   1783                }
   1784            }
   1785            break;
   1786 
   1787        default:
   1788            break;
   1789    }
   1790 
   1791    Texture *texture = context->getTextureByType(target);
   1792    if (!texture || texture->id().value == 0)
   1793    {
   1794        context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
   1795        return false;
   1796    }
   1797 
   1798    if (texture->getImmutableFormat())
   1799    {
   1800        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
   1801        return false;
   1802    }
   1803 
   1804    return true;
   1805 }
   1806 
   1807 bool ValidateDiscardFramebufferEXT(const Context *context,
   1808                                   angle::EntryPoint entryPoint,
   1809                                   GLenum target,
   1810                                   GLsizei numAttachments,
   1811                                   const GLenum *attachments)
   1812 {
   1813    if (!context->getExtensions().discardFramebufferEXT)
   1814    {
   1815        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1816        return false;
   1817    }
   1818 
   1819    bool defaultFramebuffer = false;
   1820 
   1821    switch (target)
   1822    {
   1823        case GL_FRAMEBUFFER:
   1824            defaultFramebuffer =
   1825                (context->getState().getTargetFramebuffer(GL_FRAMEBUFFER)->isDefault());
   1826            break;
   1827        default:
   1828            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   1829            return false;
   1830    }
   1831 
   1832    return ValidateDiscardFramebufferBase(context, entryPoint, target, numAttachments, attachments,
   1833                                          defaultFramebuffer);
   1834 }
   1835 
   1836 bool ValidateBindVertexArrayOES(const Context *context,
   1837                                angle::EntryPoint entryPoint,
   1838                                VertexArrayID array)
   1839 {
   1840    if (!context->getExtensions().vertexArrayObjectOES)
   1841    {
   1842        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1843        return false;
   1844    }
   1845 
   1846    return ValidateBindVertexArrayBase(context, entryPoint, array);
   1847 }
   1848 
   1849 bool ValidateDeleteVertexArraysOES(const Context *context,
   1850                                   angle::EntryPoint entryPoint,
   1851                                   GLsizei n,
   1852                                   const VertexArrayID *arrays)
   1853 {
   1854    if (!context->getExtensions().vertexArrayObjectOES)
   1855    {
   1856        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1857        return false;
   1858    }
   1859 
   1860    return ValidateGenOrDelete(context, entryPoint, n);
   1861 }
   1862 
   1863 bool ValidateGenVertexArraysOES(const Context *context,
   1864                                angle::EntryPoint entryPoint,
   1865                                GLsizei n,
   1866                                const VertexArrayID *arrays)
   1867 {
   1868    if (!context->getExtensions().vertexArrayObjectOES)
   1869    {
   1870        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1871        return false;
   1872    }
   1873 
   1874    return ValidateGenOrDelete(context, entryPoint, n);
   1875 }
   1876 
   1877 bool ValidateIsVertexArrayOES(const Context *context,
   1878                              angle::EntryPoint entryPoint,
   1879                              VertexArrayID array)
   1880 {
   1881    if (!context->getExtensions().vertexArrayObjectOES)
   1882    {
   1883        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1884        return false;
   1885    }
   1886 
   1887    return true;
   1888 }
   1889 
   1890 bool ValidateProgramBinaryOES(const Context *context,
   1891                              angle::EntryPoint entryPoint,
   1892                              ShaderProgramID program,
   1893                              GLenum binaryFormat,
   1894                              const void *binary,
   1895                              GLint length)
   1896 {
   1897    if (!context->getExtensions().getProgramBinaryOES)
   1898    {
   1899        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1900        return false;
   1901    }
   1902 
   1903    return ValidateProgramBinaryBase(context, entryPoint, program, binaryFormat, binary, length);
   1904 }
   1905 
   1906 bool ValidateGetProgramBinaryOES(const Context *context,
   1907                                 angle::EntryPoint entryPoint,
   1908                                 ShaderProgramID program,
   1909                                 GLsizei bufSize,
   1910                                 const GLsizei *length,
   1911                                 const GLenum *binaryFormat,
   1912                                 const void *binary)
   1913 {
   1914    if (!context->getExtensions().getProgramBinaryOES)
   1915    {
   1916        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1917        return false;
   1918    }
   1919 
   1920    return ValidateGetProgramBinaryBase(context, entryPoint, program, bufSize, length, binaryFormat,
   1921                                        binary);
   1922 }
   1923 
   1924 static bool ValidDebugSource(GLenum source, bool mustBeThirdPartyOrApplication)
   1925 {
   1926    switch (source)
   1927    {
   1928        case GL_DEBUG_SOURCE_API:
   1929        case GL_DEBUG_SOURCE_SHADER_COMPILER:
   1930        case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
   1931        case GL_DEBUG_SOURCE_OTHER:
   1932            // Only THIRD_PARTY and APPLICATION sources are allowed to be manually inserted
   1933            return !mustBeThirdPartyOrApplication;
   1934 
   1935        case GL_DEBUG_SOURCE_THIRD_PARTY:
   1936        case GL_DEBUG_SOURCE_APPLICATION:
   1937            return true;
   1938 
   1939        default:
   1940            return false;
   1941    }
   1942 }
   1943 
   1944 static bool ValidDebugType(GLenum type)
   1945 {
   1946    switch (type)
   1947    {
   1948        case GL_DEBUG_TYPE_ERROR:
   1949        case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
   1950        case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
   1951        case GL_DEBUG_TYPE_PERFORMANCE:
   1952        case GL_DEBUG_TYPE_PORTABILITY:
   1953        case GL_DEBUG_TYPE_OTHER:
   1954        case GL_DEBUG_TYPE_MARKER:
   1955        case GL_DEBUG_TYPE_PUSH_GROUP:
   1956        case GL_DEBUG_TYPE_POP_GROUP:
   1957            return true;
   1958 
   1959        default:
   1960            return false;
   1961    }
   1962 }
   1963 
   1964 static bool ValidDebugSeverity(GLenum severity)
   1965 {
   1966    switch (severity)
   1967    {
   1968        case GL_DEBUG_SEVERITY_HIGH:
   1969        case GL_DEBUG_SEVERITY_MEDIUM:
   1970        case GL_DEBUG_SEVERITY_LOW:
   1971        case GL_DEBUG_SEVERITY_NOTIFICATION:
   1972            return true;
   1973 
   1974        default:
   1975            return false;
   1976    }
   1977 }
   1978 
   1979 bool ValidateDebugMessageControlKHR(const Context *context,
   1980                                    angle::EntryPoint entryPoint,
   1981                                    GLenum source,
   1982                                    GLenum type,
   1983                                    GLenum severity,
   1984                                    GLsizei count,
   1985                                    const GLuint *ids,
   1986                                    GLboolean enabled)
   1987 {
   1988    if (!context->getExtensions().debugKHR)
   1989    {
   1990        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1991        return false;
   1992    }
   1993 
   1994    if (!ValidDebugSource(source, false) && source != GL_DONT_CARE)
   1995    {
   1996        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
   1997        return false;
   1998    }
   1999 
   2000    if (!ValidDebugType(type) && type != GL_DONT_CARE)
   2001    {
   2002        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugType);
   2003        return false;
   2004    }
   2005 
   2006    if (!ValidDebugSeverity(severity) && severity != GL_DONT_CARE)
   2007    {
   2008        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSeverity);
   2009        return false;
   2010    }
   2011 
   2012    if (count > 0)
   2013    {
   2014        if (source == GL_DONT_CARE || type == GL_DONT_CARE)
   2015        {
   2016            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDebugSourceType);
   2017            return false;
   2018        }
   2019 
   2020        if (severity != GL_DONT_CARE)
   2021        {
   2022            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDebugSeverity);
   2023            return false;
   2024        }
   2025    }
   2026 
   2027    return true;
   2028 }
   2029 
   2030 bool ValidateDebugMessageInsertKHR(const Context *context,
   2031                                   angle::EntryPoint entryPoint,
   2032                                   GLenum source,
   2033                                   GLenum type,
   2034                                   GLuint id,
   2035                                   GLenum severity,
   2036                                   GLsizei length,
   2037                                   const GLchar *buf)
   2038 {
   2039    if (!context->getExtensions().debugKHR)
   2040    {
   2041        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2042        return false;
   2043    }
   2044 
   2045    if (!context->getState().getDebug().isOutputEnabled())
   2046    {
   2047        // If the DEBUG_OUTPUT state is disabled calls to DebugMessageInsert are discarded and do
   2048        // not generate an error.
   2049        return false;
   2050    }
   2051 
   2052    if (!ValidDebugSeverity(severity))
   2053    {
   2054        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
   2055        return false;
   2056    }
   2057 
   2058    if (!ValidDebugType(type))
   2059    {
   2060        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugType);
   2061        return false;
   2062    }
   2063 
   2064    if (!ValidDebugSource(source, true))
   2065    {
   2066        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
   2067        return false;
   2068    }
   2069 
   2070    size_t messageLength = (length < 0) ? strlen(buf) : length;
   2071    if (messageLength > context->getCaps().maxDebugMessageLength)
   2072    {
   2073        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
   2074        return false;
   2075    }
   2076 
   2077    return true;
   2078 }
   2079 
   2080 bool ValidateDebugMessageCallbackKHR(const Context *context,
   2081                                     angle::EntryPoint entryPoint,
   2082                                     GLDEBUGPROCKHR callback,
   2083                                     const void *userParam)
   2084 {
   2085    if (!context->getExtensions().debugKHR)
   2086    {
   2087        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2088        return false;
   2089    }
   2090 
   2091    return true;
   2092 }
   2093 
   2094 bool ValidateGetDebugMessageLogKHR(const Context *context,
   2095                                   angle::EntryPoint entryPoint,
   2096                                   GLuint count,
   2097                                   GLsizei bufSize,
   2098                                   const GLenum *sources,
   2099                                   const GLenum *types,
   2100                                   const GLuint *ids,
   2101                                   const GLenum *severities,
   2102                                   const GLsizei *lengths,
   2103                                   const GLchar *messageLog)
   2104 {
   2105    if (!context->getExtensions().debugKHR)
   2106    {
   2107        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2108        return false;
   2109    }
   2110 
   2111    if (bufSize < 0 && messageLog != nullptr)
   2112    {
   2113        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   2114        return false;
   2115    }
   2116 
   2117    return true;
   2118 }
   2119 
   2120 bool ValidatePushDebugGroupKHR(const Context *context,
   2121                               angle::EntryPoint entryPoint,
   2122                               GLenum source,
   2123                               GLuint id,
   2124                               GLsizei length,
   2125                               const GLchar *message)
   2126 {
   2127    if (!context->getExtensions().debugKHR)
   2128    {
   2129        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2130        return false;
   2131    }
   2132 
   2133    if (!ValidDebugSource(source, true))
   2134    {
   2135        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDebugSource);
   2136        return false;
   2137    }
   2138 
   2139    size_t messageLength = (length < 0) ? strlen(message) : length;
   2140    if (messageLength > context->getCaps().maxDebugMessageLength)
   2141    {
   2142        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxDebugMessageLength);
   2143        return false;
   2144    }
   2145 
   2146    size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
   2147    if (currentStackSize >= context->getCaps().maxDebugGroupStackDepth)
   2148    {
   2149        context->validationError(entryPoint, GL_STACK_OVERFLOW, kExceedsMaxDebugGroupStackDepth);
   2150        return false;
   2151    }
   2152 
   2153    return true;
   2154 }
   2155 
   2156 bool ValidatePopDebugGroupKHR(const Context *context, angle::EntryPoint entryPoint)
   2157 {
   2158    if (!context->getExtensions().debugKHR)
   2159    {
   2160        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2161        return false;
   2162    }
   2163 
   2164    size_t currentStackSize = context->getState().getDebug().getGroupStackDepth();
   2165    if (currentStackSize <= 1)
   2166    {
   2167        context->validationError(entryPoint, GL_STACK_UNDERFLOW, kCannotPopDefaultDebugGroup);
   2168        return false;
   2169    }
   2170 
   2171    return true;
   2172 }
   2173 
   2174 static bool ValidateObjectIdentifierAndName(const Context *context,
   2175                                            angle::EntryPoint entryPoint,
   2176                                            GLenum identifier,
   2177                                            GLuint name)
   2178 {
   2179    switch (identifier)
   2180    {
   2181        case GL_BUFFER:
   2182            if (context->getBuffer({name}) == nullptr)
   2183            {
   2184                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBufferName);
   2185                return false;
   2186            }
   2187            return true;
   2188 
   2189        case GL_SHADER:
   2190            if (context->getShader({name}) == nullptr)
   2191            {
   2192                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidShaderName);
   2193                return false;
   2194            }
   2195            return true;
   2196 
   2197        case GL_PROGRAM:
   2198            if (context->getProgramNoResolveLink({name}) == nullptr)
   2199            {
   2200                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
   2201                return false;
   2202            }
   2203            return true;
   2204 
   2205        case GL_VERTEX_ARRAY:
   2206            if (context->getVertexArray({name}) == nullptr)
   2207            {
   2208                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidVertexArrayName);
   2209                return false;
   2210            }
   2211            return true;
   2212 
   2213        case GL_QUERY:
   2214            if (context->getQuery({name}) == nullptr)
   2215            {
   2216                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidQueryName);
   2217                return false;
   2218            }
   2219            return true;
   2220 
   2221        case GL_TRANSFORM_FEEDBACK:
   2222            if (context->getTransformFeedback({name}) == nullptr)
   2223            {
   2224                context->validationError(entryPoint, GL_INVALID_VALUE,
   2225                                         kInvalidTransformFeedbackName);
   2226                return false;
   2227            }
   2228            return true;
   2229 
   2230        case GL_SAMPLER:
   2231            if (context->getSampler({name}) == nullptr)
   2232            {
   2233                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSamplerName);
   2234                return false;
   2235            }
   2236            return true;
   2237 
   2238        case GL_TEXTURE:
   2239            if (context->getTexture({name}) == nullptr)
   2240            {
   2241                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName);
   2242                return false;
   2243            }
   2244            return true;
   2245 
   2246        case GL_RENDERBUFFER:
   2247            if (!context->isRenderbuffer({name}))
   2248            {
   2249                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferName);
   2250                return false;
   2251            }
   2252            return true;
   2253 
   2254        case GL_FRAMEBUFFER:
   2255            if (context->getFramebuffer({name}) == nullptr)
   2256            {
   2257                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferName);
   2258                return false;
   2259            }
   2260            return true;
   2261 
   2262        case GL_PROGRAM_PIPELINE:
   2263            if (context->getProgramPipeline({name}) == nullptr)
   2264            {
   2265                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramPipelineName);
   2266                return false;
   2267            }
   2268            return true;
   2269 
   2270        default:
   2271            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidIndentifier);
   2272            return false;
   2273    }
   2274 }
   2275 
   2276 static bool ValidateLabelLength(const Context *context,
   2277                                angle::EntryPoint entryPoint,
   2278                                GLsizei length,
   2279                                const GLchar *label)
   2280 {
   2281    size_t labelLength = 0;
   2282 
   2283    if (length < 0)
   2284    {
   2285        if (label != nullptr)
   2286        {
   2287            labelLength = strlen(label);
   2288        }
   2289    }
   2290    else
   2291    {
   2292        labelLength = static_cast<size_t>(length);
   2293    }
   2294 
   2295    if (labelLength > context->getCaps().maxLabelLength)
   2296    {
   2297        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxLabelLength);
   2298        return false;
   2299    }
   2300 
   2301    return true;
   2302 }
   2303 
   2304 bool ValidateObjectLabelKHR(const Context *context,
   2305                            angle::EntryPoint entryPoint,
   2306                            GLenum identifier,
   2307                            GLuint name,
   2308                            GLsizei length,
   2309                            const GLchar *label)
   2310 {
   2311    if (!context->getExtensions().debugKHR)
   2312    {
   2313        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2314        return false;
   2315    }
   2316 
   2317    if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name))
   2318    {
   2319        return false;
   2320    }
   2321 
   2322    if (!ValidateLabelLength(context, entryPoint, length, label))
   2323    {
   2324        return false;
   2325    }
   2326 
   2327    return true;
   2328 }
   2329 
   2330 bool ValidateGetObjectLabelKHR(const Context *context,
   2331                               angle::EntryPoint entryPoint,
   2332                               GLenum identifier,
   2333                               GLuint name,
   2334                               GLsizei bufSize,
   2335                               const GLsizei *length,
   2336                               const GLchar *label)
   2337 {
   2338    if (!context->getExtensions().debugKHR)
   2339    {
   2340        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2341        return false;
   2342    }
   2343 
   2344    if (bufSize < 0)
   2345    {
   2346        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   2347        return false;
   2348    }
   2349 
   2350    if (!ValidateObjectIdentifierAndName(context, entryPoint, identifier, name))
   2351    {
   2352        return false;
   2353    }
   2354 
   2355    return true;
   2356 }
   2357 
   2358 static bool ValidateObjectPtrName(const Context *context,
   2359                                  angle::EntryPoint entryPoint,
   2360                                  const void *ptr)
   2361 {
   2362    if (context->getSync(reinterpret_cast<GLsync>(const_cast<void *>(ptr))) == nullptr)
   2363    {
   2364        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSyncPointer);
   2365        return false;
   2366    }
   2367 
   2368    return true;
   2369 }
   2370 
   2371 bool ValidateObjectPtrLabelKHR(const Context *context,
   2372                               angle::EntryPoint entryPoint,
   2373                               const void *ptr,
   2374                               GLsizei length,
   2375                               const GLchar *label)
   2376 {
   2377    if (!context->getExtensions().debugKHR)
   2378    {
   2379        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2380        return false;
   2381    }
   2382 
   2383    if (!ValidateObjectPtrName(context, entryPoint, ptr))
   2384    {
   2385        return false;
   2386    }
   2387 
   2388    if (!ValidateLabelLength(context, entryPoint, length, label))
   2389    {
   2390        return false;
   2391    }
   2392 
   2393    return true;
   2394 }
   2395 
   2396 bool ValidateGetObjectPtrLabelKHR(const Context *context,
   2397                                  angle::EntryPoint entryPoint,
   2398                                  const void *ptr,
   2399                                  GLsizei bufSize,
   2400                                  const GLsizei *length,
   2401                                  const GLchar *label)
   2402 {
   2403    if (!context->getExtensions().debugKHR)
   2404    {
   2405        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2406        return false;
   2407    }
   2408 
   2409    if (bufSize < 0)
   2410    {
   2411        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   2412        return false;
   2413    }
   2414 
   2415    if (!ValidateObjectPtrName(context, entryPoint, ptr))
   2416    {
   2417        return false;
   2418    }
   2419 
   2420    return true;
   2421 }
   2422 
   2423 bool ValidateGetPointervKHR(const Context *context,
   2424                            angle::EntryPoint entryPoint,
   2425                            GLenum pname,
   2426                            void *const *params)
   2427 {
   2428    if (!context->getExtensions().debugKHR)
   2429    {
   2430        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2431        return false;
   2432    }
   2433 
   2434    // TODO: represent this in Context::getQueryParameterInfo.
   2435    switch (pname)
   2436    {
   2437        case GL_DEBUG_CALLBACK_FUNCTION:
   2438        case GL_DEBUG_CALLBACK_USER_PARAM:
   2439            break;
   2440 
   2441        default:
   2442            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   2443            return false;
   2444    }
   2445 
   2446    return true;
   2447 }
   2448 
   2449 bool ValidateGetPointervRobustANGLERobustANGLE(const Context *context,
   2450                                               angle::EntryPoint entryPoint,
   2451                                               GLenum pname,
   2452                                               GLsizei bufSize,
   2453                                               const GLsizei *length,
   2454                                               void *const *params)
   2455 {
   2456    UNIMPLEMENTED();
   2457    return false;
   2458 }
   2459 
   2460 bool ValidateBlitFramebufferANGLE(const Context *context,
   2461                                  angle::EntryPoint entryPoint,
   2462                                  GLint srcX0,
   2463                                  GLint srcY0,
   2464                                  GLint srcX1,
   2465                                  GLint srcY1,
   2466                                  GLint dstX0,
   2467                                  GLint dstY0,
   2468                                  GLint dstX1,
   2469                                  GLint dstY1,
   2470                                  GLbitfield mask,
   2471                                  GLenum filter)
   2472 {
   2473    if (!context->getExtensions().framebufferBlitANGLE)
   2474    {
   2475        context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
   2476        return false;
   2477    }
   2478 
   2479    if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
   2480    {
   2481        // TODO(jmadill): Determine if this should be available on other implementations.
   2482        context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionScaleOrFlip);
   2483        return false;
   2484    }
   2485 
   2486    if (filter == GL_LINEAR)
   2487    {
   2488        context->validationError(entryPoint, GL_INVALID_ENUM, kBlitExtensionLinear);
   2489        return false;
   2490    }
   2491 
   2492    Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
   2493    Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
   2494 
   2495    if (mask & GL_COLOR_BUFFER_BIT)
   2496    {
   2497        const FramebufferAttachment *readColorAttachment =
   2498            readFramebuffer->getReadColorAttachment();
   2499        const FramebufferAttachment *drawColorAttachment =
   2500            drawFramebuffer->getFirstColorAttachment();
   2501 
   2502        if (readColorAttachment && drawColorAttachment)
   2503        {
   2504            if (!(readColorAttachment->type() == GL_TEXTURE &&
   2505                  (readColorAttachment->getTextureImageIndex().getType() == TextureType::_2D ||
   2506                   readColorAttachment->getTextureImageIndex().getType() ==
   2507                       TextureType::Rectangle)) &&
   2508                readColorAttachment->type() != GL_RENDERBUFFER &&
   2509                readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT)
   2510            {
   2511                context->validationError(entryPoint, GL_INVALID_OPERATION,
   2512                                         kBlitExtensionFromInvalidAttachmentType);
   2513                return false;
   2514            }
   2515 
   2516            for (size_t drawbufferIdx = 0;
   2517                 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
   2518            {
   2519                const FramebufferAttachment *attachment =
   2520                    drawFramebuffer->getDrawBuffer(drawbufferIdx);
   2521                if (attachment)
   2522                {
   2523                    if (!(attachment->type() == GL_TEXTURE &&
   2524                          (attachment->getTextureImageIndex().getType() == TextureType::_2D ||
   2525                           attachment->getTextureImageIndex().getType() ==
   2526                               TextureType::Rectangle)) &&
   2527                        attachment->type() != GL_RENDERBUFFER &&
   2528                        attachment->type() != GL_FRAMEBUFFER_DEFAULT)
   2529                    {
   2530                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   2531                                                 kBlitExtensionToInvalidAttachmentType);
   2532                        return false;
   2533                    }
   2534 
   2535                    // Return an error if the destination formats do not match
   2536                    if (!Format::EquivalentForBlit(attachment->getFormat(),
   2537                                                   readColorAttachment->getFormat()))
   2538                    {
   2539                        context->validationErrorF(
   2540                            entryPoint, GL_INVALID_OPERATION, kBlitExtensionFormatMismatch,
   2541                            readColorAttachment->getFormat().info->sizedInternalFormat,
   2542                            attachment->getFormat().info->sizedInternalFormat);
   2543                        return false;
   2544                    }
   2545                }
   2546            }
   2547 
   2548            GLint samples = readFramebuffer->getSamples(context);
   2549            if (samples != 0 &&
   2550                IsPartialBlit(context, readColorAttachment, drawColorAttachment, srcX0, srcY0,
   2551                              srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
   2552            {
   2553                context->validationError(entryPoint, GL_INVALID_OPERATION,
   2554                                         kBlitExtensionMultisampledWholeBufferBlit);
   2555                return false;
   2556            }
   2557        }
   2558    }
   2559 
   2560    GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
   2561    GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
   2562    for (size_t i = 0; i < 2; i++)
   2563    {
   2564        if (mask & masks[i])
   2565        {
   2566            const FramebufferAttachment *readBuffer =
   2567                readFramebuffer->getAttachment(context, attachments[i]);
   2568            const FramebufferAttachment *drawBuffer =
   2569                drawFramebuffer->getAttachment(context, attachments[i]);
   2570 
   2571            if (readBuffer && drawBuffer)
   2572            {
   2573                if (IsPartialBlit(context, readBuffer, drawBuffer, srcX0, srcY0, srcX1, srcY1,
   2574                                  dstX0, dstY0, dstX1, dstY1))
   2575                {
   2576                    // only whole-buffer copies are permitted
   2577                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   2578                                             kBlitExtensionDepthStencilWholeBufferBlit);
   2579                    return false;
   2580                }
   2581 
   2582                if (readBuffer->getResourceSamples() != 0 || drawBuffer->getResourceSamples() != 0)
   2583                {
   2584                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   2585                                             kBlitExtensionMultisampledDepthOrStencil);
   2586                    return false;
   2587                }
   2588            }
   2589        }
   2590    }
   2591 
   2592    return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
   2593                                             dstY0, dstX1, dstY1, mask, filter);
   2594 }
   2595 
   2596 bool ValidateBlitFramebufferNV(const Context *context,
   2597                               angle::EntryPoint entryPoint,
   2598                               GLint srcX0,
   2599                               GLint srcY0,
   2600                               GLint srcX1,
   2601                               GLint srcY1,
   2602                               GLint dstX0,
   2603                               GLint dstY0,
   2604                               GLint dstX1,
   2605                               GLint dstY1,
   2606                               GLbitfield mask,
   2607                               GLenum filter)
   2608 {
   2609    if (!context->getExtensions().framebufferBlitANGLE)
   2610    {
   2611        context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitExtensionNotAvailable);
   2612        return false;
   2613    }
   2614 
   2615    return ValidateBlitFramebufferParameters(context, entryPoint, srcX0, srcY0, srcX1, srcY1, dstX0,
   2616                                             dstY0, dstX1, dstY1, mask, filter);
   2617 }
   2618 
   2619 bool ValidateClear(const Context *context, angle::EntryPoint entryPoint, GLbitfield mask)
   2620 {
   2621    Framebuffer *fbo             = context->getState().getDrawFramebuffer();
   2622    const Extensions &extensions = context->getExtensions();
   2623 
   2624    if (!ValidateFramebufferComplete(context, entryPoint, fbo))
   2625    {
   2626        return false;
   2627    }
   2628 
   2629    if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
   2630    {
   2631        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidClearMask);
   2632        return false;
   2633    }
   2634 
   2635    if (extensions.webglCompatibilityANGLE && (mask & GL_COLOR_BUFFER_BIT) != 0)
   2636    {
   2637        constexpr GLenum validComponentTypes[] = {GL_FLOAT, GL_UNSIGNED_NORMALIZED,
   2638                                                  GL_SIGNED_NORMALIZED};
   2639 
   2640        for (GLuint drawBufferIdx = 0; drawBufferIdx < fbo->getDrawbufferStateCount();
   2641             drawBufferIdx++)
   2642        {
   2643            if (!ValidateWebGLFramebufferAttachmentClearType(context, entryPoint, drawBufferIdx,
   2644                                                             validComponentTypes,
   2645                                                             ArraySize(validComponentTypes)))
   2646            {
   2647                return false;
   2648            }
   2649        }
   2650    }
   2651 
   2652    if ((extensions.multiviewOVR || extensions.multiview2OVR) && extensions.disjointTimerQueryEXT)
   2653    {
   2654        const State &state       = context->getState();
   2655        Framebuffer *framebuffer = state.getDrawFramebuffer();
   2656        if (framebuffer->getNumViews() > 1 && state.isQueryActive(QueryType::TimeElapsed))
   2657        {
   2658            context->validationError(entryPoint, GL_INVALID_OPERATION, kMultiviewTimerQuery);
   2659            return false;
   2660        }
   2661    }
   2662 
   2663    return true;
   2664 }
   2665 
   2666 bool ValidateDrawBuffersEXT(const Context *context,
   2667                            angle::EntryPoint entryPoint,
   2668                            GLsizei n,
   2669                            const GLenum *bufs)
   2670 {
   2671    if (!context->getExtensions().drawBuffersEXT)
   2672    {
   2673        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2674        return false;
   2675    }
   2676 
   2677    return ValidateDrawBuffersBase(context, entryPoint, n, bufs);
   2678 }
   2679 
   2680 bool ValidateTexImage2D(const Context *context,
   2681                        angle::EntryPoint entryPoint,
   2682                        TextureTarget target,
   2683                        GLint level,
   2684                        GLint internalformat,
   2685                        GLsizei width,
   2686                        GLsizei height,
   2687                        GLint border,
   2688                        GLenum format,
   2689                        GLenum type,
   2690                        const void *pixels)
   2691 {
   2692    if (context->getClientMajorVersion() < 3)
   2693    {
   2694        return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat,
   2695                                             false, false, 0, 0, width, height, border, format,
   2696                                             type, -1, pixels);
   2697    }
   2698 
   2699    ASSERT(context->getClientMajorVersion() >= 3);
   2700    return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
   2701                                           false, false, 0, 0, 0, width, height, 1, border, format,
   2702                                           type, -1, pixels);
   2703 }
   2704 
   2705 bool ValidateTexImage2DRobustANGLE(const Context *context,
   2706                                   angle::EntryPoint entryPoint,
   2707                                   TextureTarget target,
   2708                                   GLint level,
   2709                                   GLint internalformat,
   2710                                   GLsizei width,
   2711                                   GLsizei height,
   2712                                   GLint border,
   2713                                   GLenum format,
   2714                                   GLenum type,
   2715                                   GLsizei bufSize,
   2716                                   const void *pixels)
   2717 {
   2718    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2719    {
   2720        return false;
   2721    }
   2722 
   2723    if (context->getClientMajorVersion() < 3)
   2724    {
   2725        return ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat,
   2726                                             false, false, 0, 0, width, height, border, format,
   2727                                             type, bufSize, pixels);
   2728    }
   2729 
   2730    ASSERT(context->getClientMajorVersion() >= 3);
   2731    return ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
   2732                                           false, false, 0, 0, 0, width, height, 1, border, format,
   2733                                           type, bufSize, pixels);
   2734 }
   2735 
   2736 bool ValidateTexSubImage2D(const Context *context,
   2737                           angle::EntryPoint entryPoint,
   2738                           TextureTarget target,
   2739                           GLint level,
   2740                           GLint xoffset,
   2741                           GLint yoffset,
   2742                           GLsizei width,
   2743                           GLsizei height,
   2744                           GLenum format,
   2745                           GLenum type,
   2746                           const void *pixels)
   2747 {
   2748 
   2749    if (context->getClientMajorVersion() < 3)
   2750    {
   2751        return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false,
   2752                                             true, xoffset, yoffset, width, height, 0, format, type,
   2753                                             -1, pixels);
   2754    }
   2755 
   2756    ASSERT(context->getClientMajorVersion() >= 3);
   2757    return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true,
   2758                                           xoffset, yoffset, 0, width, height, 1, 0, format, type,
   2759                                           -1, pixels);
   2760 }
   2761 
   2762 bool ValidateTexSubImage2DRobustANGLE(const Context *context,
   2763                                      angle::EntryPoint entryPoint,
   2764                                      TextureTarget target,
   2765                                      GLint level,
   2766                                      GLint xoffset,
   2767                                      GLint yoffset,
   2768                                      GLsizei width,
   2769                                      GLsizei height,
   2770                                      GLenum format,
   2771                                      GLenum type,
   2772                                      GLsizei bufSize,
   2773                                      const void *pixels)
   2774 {
   2775    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2776    {
   2777        return false;
   2778    }
   2779 
   2780    if (context->getClientMajorVersion() < 3)
   2781    {
   2782        return ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, false,
   2783                                             true, xoffset, yoffset, width, height, 0, format, type,
   2784                                             bufSize, pixels);
   2785    }
   2786 
   2787    ASSERT(context->getClientMajorVersion() >= 3);
   2788    return ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, false, true,
   2789                                           xoffset, yoffset, 0, width, height, 1, 0, format, type,
   2790                                           bufSize, pixels);
   2791 }
   2792 
   2793 bool ValidateTexSubImage3DOES(const Context *context,
   2794                              angle::EntryPoint entryPoint,
   2795                              TextureTarget target,
   2796                              GLint level,
   2797                              GLint xoffset,
   2798                              GLint yoffset,
   2799                              GLint zoffset,
   2800                              GLsizei width,
   2801                              GLsizei height,
   2802                              GLsizei depth,
   2803                              GLenum format,
   2804                              GLenum type,
   2805                              const void *pixels)
   2806 {
   2807    return ValidateTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset,
   2808                                 width, height, depth, format, type, pixels);
   2809 }
   2810 
   2811 bool ValidateCompressedTexImage2D(const Context *context,
   2812                                  angle::EntryPoint entryPoint,
   2813                                  TextureTarget target,
   2814                                  GLint level,
   2815                                  GLenum internalformat,
   2816                                  GLsizei width,
   2817                                  GLsizei height,
   2818                                  GLint border,
   2819                                  GLsizei imageSize,
   2820                                  const void *data)
   2821 {
   2822    if (context->getClientMajorVersion() < 3)
   2823    {
   2824        if (!ValidateES2TexImageParameters(context, entryPoint, target, level, internalformat, true,
   2825                                           false, 0, 0, width, height, border, GL_NONE, GL_NONE, -1,
   2826                                           data))
   2827        {
   2828            return false;
   2829        }
   2830    }
   2831    else
   2832    {
   2833        ASSERT(context->getClientMajorVersion() >= 3);
   2834        if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, internalformat,
   2835                                             true, false, 0, 0, 0, width, height, 1, border,
   2836                                             GL_NONE, GL_NONE, -1, data))
   2837        {
   2838            return false;
   2839        }
   2840    }
   2841 
   2842    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalformat);
   2843 
   2844    GLuint expectedImageSize = 0;
   2845    if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &expectedImageSize))
   2846    {
   2847        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   2848        return false;
   2849    }
   2850 
   2851    if (imageSize < 0 || static_cast<GLuint>(imageSize) != expectedImageSize)
   2852    {
   2853        context->validationError(entryPoint, GL_INVALID_VALUE,
   2854                                 kCompressedTextureDimensionsMustMatchData);
   2855        return false;
   2856    }
   2857 
   2858    if (target == TextureTarget::Rectangle)
   2859    {
   2860        context->validationError(entryPoint, GL_INVALID_ENUM, kRectangleTextureCompressed);
   2861        return false;
   2862    }
   2863 
   2864    return true;
   2865 }
   2866 
   2867 bool ValidateCompressedTexImage2DRobustANGLE(const Context *context,
   2868                                             angle::EntryPoint entryPoint,
   2869                                             TextureTarget target,
   2870                                             GLint level,
   2871                                             GLenum internalformat,
   2872                                             GLsizei width,
   2873                                             GLsizei height,
   2874                                             GLint border,
   2875                                             GLsizei imageSize,
   2876                                             GLsizei dataSize,
   2877                                             const void *data)
   2878 {
   2879    if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
   2880    {
   2881        return false;
   2882    }
   2883 
   2884    return ValidateCompressedTexImage2D(context, entryPoint, target, level, internalformat, width,
   2885                                        height, border, imageSize, data);
   2886 }
   2887 
   2888 bool ValidateCompressedTexImage3DOES(const Context *context,
   2889                                     angle::EntryPoint entryPoint,
   2890                                     TextureTarget target,
   2891                                     GLint level,
   2892                                     GLenum internalformat,
   2893                                     GLsizei width,
   2894                                     GLsizei height,
   2895                                     GLsizei depth,
   2896                                     GLint border,
   2897                                     GLsizei imageSize,
   2898                                     const void *data)
   2899 {
   2900    return ValidateCompressedTexImage3D(context, entryPoint, target, level, internalformat, width,
   2901                                        height, depth, border, imageSize, data);
   2902 }
   2903 
   2904 bool ValidateCompressedTexSubImage2DRobustANGLE(const Context *context,
   2905                                                angle::EntryPoint entryPoint,
   2906                                                TextureTarget target,
   2907                                                GLint level,
   2908                                                GLint xoffset,
   2909                                                GLint yoffset,
   2910                                                GLsizei width,
   2911                                                GLsizei height,
   2912                                                GLenum format,
   2913                                                GLsizei imageSize,
   2914                                                GLsizei dataSize,
   2915                                                const void *data)
   2916 {
   2917    if (!ValidateRobustCompressedTexImageBase(context, entryPoint, imageSize, dataSize))
   2918    {
   2919        return false;
   2920    }
   2921 
   2922    return ValidateCompressedTexSubImage2D(context, entryPoint, target, level, xoffset, yoffset,
   2923                                           width, height, format, imageSize, data);
   2924 }
   2925 
   2926 bool ValidateCompressedTexSubImage2D(const Context *context,
   2927                                     angle::EntryPoint entryPoint,
   2928                                     TextureTarget target,
   2929                                     GLint level,
   2930                                     GLint xoffset,
   2931                                     GLint yoffset,
   2932                                     GLsizei width,
   2933                                     GLsizei height,
   2934                                     GLenum format,
   2935                                     GLsizei imageSize,
   2936                                     const void *data)
   2937 {
   2938    if (context->getClientMajorVersion() < 3)
   2939    {
   2940        if (!ValidateES2TexImageParameters(context, entryPoint, target, level, GL_NONE, true, true,
   2941                                           xoffset, yoffset, width, height, 0, format, GL_NONE, -1,
   2942                                           data))
   2943        {
   2944            return false;
   2945        }
   2946    }
   2947    else
   2948    {
   2949        ASSERT(context->getClientMajorVersion() >= 3);
   2950        if (!ValidateES3TexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
   2951                                             true, xoffset, yoffset, 0, width, height, 1, 0, format,
   2952                                             GL_NONE, -1, data))
   2953        {
   2954            return false;
   2955        }
   2956    }
   2957 
   2958    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(format);
   2959    GLuint blockSize                 = 0;
   2960    if (!formatInfo.computeCompressedImageSize(Extents(width, height, 1), &blockSize))
   2961    {
   2962        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   2963        return false;
   2964    }
   2965 
   2966    if (imageSize < 0 || static_cast<GLuint>(imageSize) != blockSize)
   2967    {
   2968        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedImageSize);
   2969        return false;
   2970    }
   2971 
   2972    return true;
   2973 }
   2974 
   2975 bool ValidateCompressedTexSubImage3DOES(const Context *context,
   2976                                        angle::EntryPoint entryPoint,
   2977                                        TextureTarget target,
   2978                                        GLint level,
   2979                                        GLint xoffset,
   2980                                        GLint yoffset,
   2981                                        GLint zoffset,
   2982                                        GLsizei width,
   2983                                        GLsizei height,
   2984                                        GLsizei depth,
   2985                                        GLenum format,
   2986                                        GLsizei imageSize,
   2987                                        const void *data)
   2988 {
   2989    return ValidateCompressedTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset,
   2990                                           zoffset, width, height, depth, format, imageSize, data);
   2991 }
   2992 
   2993 bool ValidateGetBufferPointervOES(const Context *context,
   2994                                  angle::EntryPoint entryPoint,
   2995                                  BufferBinding target,
   2996                                  GLenum pname,
   2997                                  void *const *params)
   2998 {
   2999    if (!context->getExtensions().mapbufferOES)
   3000    {
   3001        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3002        return false;
   3003    }
   3004 
   3005    return ValidateGetBufferPointervBase(context, entryPoint, target, pname, nullptr, params);
   3006 }
   3007 
   3008 bool ValidateMapBufferOES(const Context *context,
   3009                          angle::EntryPoint entryPoint,
   3010                          BufferBinding target,
   3011                          GLenum access)
   3012 {
   3013    if (!context->getExtensions().mapbufferOES)
   3014    {
   3015        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3016        return false;
   3017    }
   3018 
   3019    if (!context->isValidBufferBinding(target))
   3020    {
   3021        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   3022        return false;
   3023    }
   3024 
   3025    Buffer *buffer = context->getState().getTargetBuffer(target);
   3026 
   3027    if (buffer == nullptr)
   3028    {
   3029        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable);
   3030        return false;
   3031    }
   3032 
   3033    if (access != GL_WRITE_ONLY_OES)
   3034    {
   3035        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAccessBits);
   3036        return false;
   3037    }
   3038 
   3039    // Though there is no explicit mention of an interaction between GL_EXT_buffer_storage
   3040    // and GL_OES_mapbuffer extension, allow it as long as the access type of glmapbufferOES
   3041    // is compatible with the buffer's usage flags specified during glBufferStorageEXT
   3042    if (buffer->isImmutable() && (buffer->getStorageExtUsageFlags() & GL_MAP_WRITE_BIT) == 0)
   3043    {
   3044        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable);
   3045        return false;
   3046    }
   3047 
   3048    if (buffer->isMapped())
   3049    {
   3050        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferAlreadyMapped);
   3051        return false;
   3052    }
   3053 
   3054    return ValidateMapBufferBase(context, entryPoint, target);
   3055 }
   3056 
   3057 bool ValidateUnmapBufferOES(const Context *context,
   3058                            angle::EntryPoint entryPoint,
   3059                            BufferBinding target)
   3060 {
   3061    if (!context->getExtensions().mapbufferOES)
   3062    {
   3063        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3064        return false;
   3065    }
   3066 
   3067    return ValidateUnmapBufferBase(context, entryPoint, target);
   3068 }
   3069 
   3070 bool ValidateMapBufferRangeEXT(const Context *context,
   3071                               angle::EntryPoint entryPoint,
   3072                               BufferBinding target,
   3073                               GLintptr offset,
   3074                               GLsizeiptr length,
   3075                               GLbitfield access)
   3076 {
   3077    if (!context->getExtensions().mapBufferRangeEXT)
   3078    {
   3079        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3080        return false;
   3081    }
   3082 
   3083    return ValidateMapBufferRangeBase(context, entryPoint, target, offset, length, access);
   3084 }
   3085 
   3086 bool ValidateMapBufferBase(const Context *context,
   3087                           angle::EntryPoint entryPoint,
   3088                           BufferBinding target)
   3089 {
   3090    Buffer *buffer = context->getState().getTargetBuffer(target);
   3091    ASSERT(buffer != nullptr);
   3092 
   3093    // Check if this buffer is currently being used as a transform feedback output buffer
   3094    if (context->getState().isTransformFeedbackActive())
   3095    {
   3096        TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
   3097        for (size_t i = 0; i < transformFeedback->getIndexedBufferCount(); i++)
   3098        {
   3099            const auto &transformFeedbackBuffer = transformFeedback->getIndexedBuffer(i);
   3100            if (transformFeedbackBuffer.get() == buffer)
   3101            {
   3102                context->validationError(entryPoint, GL_INVALID_OPERATION,
   3103                                         kBufferBoundForTransformFeedback);
   3104                return false;
   3105            }
   3106        }
   3107    }
   3108 
   3109    if (buffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   3110    {
   3111        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3112                                 kBufferBoundForTransformFeedback);
   3113        return false;
   3114    }
   3115 
   3116    return true;
   3117 }
   3118 
   3119 bool ValidateFlushMappedBufferRangeEXT(const Context *context,
   3120                                       angle::EntryPoint entryPoint,
   3121                                       BufferBinding target,
   3122                                       GLintptr offset,
   3123                                       GLsizeiptr length)
   3124 {
   3125    if (!context->getExtensions().mapBufferRangeEXT)
   3126    {
   3127        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3128        return false;
   3129    }
   3130 
   3131    return ValidateFlushMappedBufferRangeBase(context, entryPoint, target, offset, length);
   3132 }
   3133 
   3134 bool ValidateBindUniformLocationCHROMIUM(const Context *context,
   3135                                         angle::EntryPoint entryPoint,
   3136                                         ShaderProgramID program,
   3137                                         UniformLocation location,
   3138                                         const GLchar *name)
   3139 {
   3140    if (!context->getExtensions().bindUniformLocationCHROMIUM)
   3141    {
   3142        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3143        return false;
   3144    }
   3145 
   3146    Program *programObject = GetValidProgram(context, entryPoint, program);
   3147    if (!programObject)
   3148    {
   3149        return false;
   3150    }
   3151 
   3152    if (location.value < 0)
   3153    {
   3154        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLocation);
   3155        return false;
   3156    }
   3157 
   3158    const Caps &caps = context->getCaps();
   3159    if (static_cast<long>(location.value) >=
   3160        (caps.maxVertexUniformVectors + caps.maxFragmentUniformVectors) * 4)
   3161    {
   3162        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBindUniformLocation);
   3163        return false;
   3164    }
   3165 
   3166    // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
   3167    // shader-related entry points
   3168    if (context->isWebGL() && !IsValidESSLString(name, strlen(name)))
   3169    {
   3170        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
   3171        return false;
   3172    }
   3173 
   3174    if (strncmp(name, "gl_", 3) == 0)
   3175    {
   3176        context->validationError(entryPoint, GL_INVALID_VALUE, kNameBeginsWithGL);
   3177        return false;
   3178    }
   3179 
   3180    return true;
   3181 }
   3182 
   3183 bool ValidateCoverageModulationCHROMIUM(const Context *context,
   3184                                        angle::EntryPoint entryPoint,
   3185                                        GLenum components)
   3186 {
   3187    if (!context->getExtensions().framebufferMixedSamplesCHROMIUM)
   3188    {
   3189        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3190        return false;
   3191    }
   3192    switch (components)
   3193    {
   3194        case GL_RGB:
   3195        case GL_RGBA:
   3196        case GL_ALPHA:
   3197        case GL_NONE:
   3198            break;
   3199        default:
   3200            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCoverageComponents);
   3201            return false;
   3202    }
   3203 
   3204    return true;
   3205 }
   3206 
   3207 bool ValidateCopyTextureCHROMIUM(const Context *context,
   3208                                 angle::EntryPoint entryPoint,
   3209                                 TextureID sourceId,
   3210                                 GLint sourceLevel,
   3211                                 TextureTarget destTarget,
   3212                                 TextureID destId,
   3213                                 GLint destLevel,
   3214                                 GLint internalFormat,
   3215                                 GLenum destType,
   3216                                 GLboolean unpackFlipY,
   3217                                 GLboolean unpackPremultiplyAlpha,
   3218                                 GLboolean unpackUnmultiplyAlpha)
   3219 {
   3220    if (!context->getExtensions().copyTextureCHROMIUM)
   3221    {
   3222        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3223        return false;
   3224    }
   3225 
   3226    const Texture *source = context->getTexture(sourceId);
   3227    if (source == nullptr)
   3228    {
   3229        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
   3230        return false;
   3231    }
   3232 
   3233    if (!IsValidCopyTextureSourceTarget(context, source->getType()))
   3234    {
   3235        context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
   3236                                  internalFormat);
   3237        return false;
   3238    }
   3239 
   3240    TextureType sourceType = source->getType();
   3241    ASSERT(sourceType != TextureType::CubeMap);
   3242    TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
   3243 
   3244    if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
   3245    {
   3246        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel);
   3247        return false;
   3248    }
   3249 
   3250    GLsizei sourceWidth  = static_cast<GLsizei>(source->getWidth(sourceTarget, sourceLevel));
   3251    GLsizei sourceHeight = static_cast<GLsizei>(source->getHeight(sourceTarget, sourceLevel));
   3252    if (sourceWidth == 0 || sourceHeight == 0)
   3253    {
   3254        context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
   3255                                  internalFormat);
   3256        return false;
   3257    }
   3258 
   3259    const InternalFormat &sourceFormat = *source->getFormat(sourceTarget, sourceLevel).info;
   3260    if (!IsValidCopyTextureSourceInternalFormatEnum(sourceFormat.internalFormat))
   3261    {
   3262        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3263                                 kInvalidSourceTextureInternalFormat);
   3264        return false;
   3265    }
   3266 
   3267    if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
   3268    {
   3269        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   3270        return false;
   3271    }
   3272 
   3273    const Texture *dest = context->getTexture(destId);
   3274    if (dest == nullptr)
   3275    {
   3276        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
   3277        return false;
   3278    }
   3279 
   3280    const InternalFormat &destInternalFormatInfo = GetInternalFormatInfo(internalFormat, destType);
   3281    if (sourceType == TextureType::External && destInternalFormatInfo.isInt() &&
   3282        !context->getExtensions().EGLImageExternalEssl3OES)
   3283    {
   3284        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3285                                 kANGLECopyTextureMissingRequiredExtension);
   3286        return false;
   3287    }
   3288 
   3289    if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
   3290    {
   3291        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
   3292        return false;
   3293    }
   3294 
   3295    if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel,
   3296                                            sourceWidth, sourceHeight, false))
   3297    {
   3298        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   3299        return false;
   3300    }
   3301 
   3302    if (!IsValidCopyTextureDestinationFormatType(context, entryPoint, internalFormat, destType))
   3303    {
   3304        return false;
   3305    }
   3306 
   3307    if (dest->getType() == TextureType::CubeMap && sourceWidth != sourceHeight)
   3308    {
   3309        context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapFacesEqualDimensions);
   3310        return false;
   3311    }
   3312 
   3313    if (dest->getImmutableFormat())
   3314    {
   3315        context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable);
   3316        return false;
   3317    }
   3318 
   3319    return true;
   3320 }
   3321 
   3322 bool ValidateCopySubTextureCHROMIUM(const Context *context,
   3323                                    angle::EntryPoint entryPoint,
   3324                                    TextureID sourceId,
   3325                                    GLint sourceLevel,
   3326                                    TextureTarget destTarget,
   3327                                    TextureID destId,
   3328                                    GLint destLevel,
   3329                                    GLint xoffset,
   3330                                    GLint yoffset,
   3331                                    GLint x,
   3332                                    GLint y,
   3333                                    GLsizei width,
   3334                                    GLsizei height,
   3335                                    GLboolean unpackFlipY,
   3336                                    GLboolean unpackPremultiplyAlpha,
   3337                                    GLboolean unpackUnmultiplyAlpha)
   3338 {
   3339    if (!context->getExtensions().copyTextureCHROMIUM)
   3340    {
   3341        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3342        return false;
   3343    }
   3344 
   3345    const Texture *source = context->getTexture(sourceId);
   3346    if (source == nullptr)
   3347    {
   3348        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
   3349        return false;
   3350    }
   3351 
   3352    if (!IsValidCopyTextureSourceTarget(context, source->getType()))
   3353    {
   3354        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureType);
   3355        return false;
   3356    }
   3357 
   3358    TextureType sourceType = source->getType();
   3359    ASSERT(sourceType != TextureType::CubeMap);
   3360    TextureTarget sourceTarget = NonCubeTextureTypeToTarget(sourceType);
   3361 
   3362    if (!IsValidCopyTextureSourceLevel(context, sourceType, sourceLevel))
   3363    {
   3364        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   3365        return false;
   3366    }
   3367 
   3368    if (source->getWidth(sourceTarget, sourceLevel) == 0 ||
   3369        source->getHeight(sourceTarget, sourceLevel) == 0)
   3370    {
   3371        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureLevel);
   3372        return false;
   3373    }
   3374 
   3375    if (x < 0 || y < 0)
   3376    {
   3377        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   3378        return false;
   3379    }
   3380 
   3381    if (width < 0 || height < 0)
   3382    {
   3383        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   3384        return false;
   3385    }
   3386 
   3387    if (static_cast<size_t>(x + width) > source->getWidth(sourceTarget, sourceLevel) ||
   3388        static_cast<size_t>(y + height) > source->getHeight(sourceTarget, sourceLevel))
   3389    {
   3390        context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
   3391        return false;
   3392    }
   3393 
   3394    const Format &sourceFormat = source->getFormat(sourceTarget, sourceLevel);
   3395    if (!IsValidCopySubTextureSourceInternalFormat(sourceFormat.info->internalFormat))
   3396    {
   3397        context->validationErrorF(entryPoint, GL_INVALID_OPERATION, kInvalidInternalFormat,
   3398                                  sourceFormat.info->internalFormat);
   3399        return false;
   3400    }
   3401 
   3402    if (!IsValidCopyTextureDestinationTargetEnum(context, destTarget))
   3403    {
   3404        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   3405        return false;
   3406    }
   3407 
   3408    const Texture *dest = context->getTexture(destId);
   3409    if (dest == nullptr)
   3410    {
   3411        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
   3412        return false;
   3413    }
   3414 
   3415    if (!IsValidCopyTextureDestinationTarget(context, dest->getType(), destTarget))
   3416    {
   3417        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
   3418        return false;
   3419    }
   3420 
   3421    if (!IsValidCopyTextureDestinationLevel(context, entryPoint, dest->getType(), destLevel, width,
   3422                                            height, true))
   3423    {
   3424        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   3425        return false;
   3426    }
   3427 
   3428    if (dest->getWidth(destTarget, destLevel) == 0 || dest->getHeight(destTarget, destLevel) == 0)
   3429    {
   3430        context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationLevelNotDefined);
   3431        return false;
   3432    }
   3433 
   3434    const InternalFormat &destFormat = *dest->getFormat(destTarget, destLevel).info;
   3435    if (!IsValidCopySubTextureDestionationInternalFormat(destFormat.internalFormat))
   3436    {
   3437        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormatCombination);
   3438        return false;
   3439    }
   3440 
   3441    if (sourceType == TextureType::External && destFormat.isInt() &&
   3442        !context->getExtensions().EGLImageExternalEssl3OES)
   3443    {
   3444        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3445                                 kANGLECopyTextureMissingRequiredExtension);
   3446        return false;
   3447    }
   3448 
   3449    if (xoffset < 0 || yoffset < 0)
   3450    {
   3451        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   3452        return false;
   3453    }
   3454 
   3455    if (static_cast<size_t>(xoffset + width) > dest->getWidth(destTarget, destLevel) ||
   3456        static_cast<size_t>(yoffset + height) > dest->getHeight(destTarget, destLevel))
   3457    {
   3458        context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
   3459        return false;
   3460    }
   3461 
   3462    return true;
   3463 }
   3464 
   3465 bool ValidateCompressedCopyTextureCHROMIUM(const Context *context,
   3466                                           angle::EntryPoint entryPoint,
   3467                                           TextureID sourceId,
   3468                                           TextureID destId)
   3469 {
   3470    if (!context->getExtensions().copyCompressedTextureCHROMIUM)
   3471    {
   3472        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3473        return false;
   3474    }
   3475 
   3476    const Texture *source = context->getTexture(sourceId);
   3477    if (source == nullptr)
   3478    {
   3479        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTexture);
   3480        return false;
   3481    }
   3482 
   3483    if (source->getType() != TextureType::_2D)
   3484    {
   3485        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSourceTextureType);
   3486        return false;
   3487    }
   3488 
   3489    if (source->getWidth(TextureTarget::_2D, 0) == 0 ||
   3490        source->getHeight(TextureTarget::_2D, 0) == 0)
   3491    {
   3492        context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureLevelZeroDefined);
   3493        return false;
   3494    }
   3495 
   3496    const Format &sourceFormat = source->getFormat(TextureTarget::_2D, 0);
   3497    if (!sourceFormat.info->compressed)
   3498    {
   3499        context->validationError(entryPoint, GL_INVALID_OPERATION, kSourceTextureMustBeCompressed);
   3500        return false;
   3501    }
   3502 
   3503    const Texture *dest = context->getTexture(destId);
   3504    if (dest == nullptr)
   3505    {
   3506        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTexture);
   3507        return false;
   3508    }
   3509 
   3510    if (dest->getType() != TextureType::_2D)
   3511    {
   3512        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDestinationTextureType);
   3513        return false;
   3514    }
   3515 
   3516    if (dest->getImmutableFormat())
   3517    {
   3518        context->validationError(entryPoint, GL_INVALID_OPERATION, kDestinationImmutable);
   3519        return false;
   3520    }
   3521 
   3522    return true;
   3523 }
   3524 
   3525 bool ValidateCreateShader(const Context *context, angle::EntryPoint entryPoint, ShaderType type)
   3526 {
   3527    switch (type)
   3528    {
   3529        case ShaderType::Vertex:
   3530        case ShaderType::Fragment:
   3531            break;
   3532 
   3533        case ShaderType::Compute:
   3534            if (context->getClientVersion() < ES_3_1)
   3535            {
   3536                context->validationError(entryPoint, GL_INVALID_ENUM, kES31Required);
   3537                return false;
   3538            }
   3539            break;
   3540 
   3541        case ShaderType::Geometry:
   3542            if (!context->getExtensions().geometryShaderAny() &&
   3543                context->getClientVersion() < ES_3_2)
   3544            {
   3545                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   3546                return false;
   3547            }
   3548            break;
   3549 
   3550        case ShaderType::TessControl:
   3551            if (!context->getExtensions().tessellationShaderEXT &&
   3552                context->getClientVersion() < ES_3_2)
   3553            {
   3554                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   3555                return false;
   3556            }
   3557            break;
   3558 
   3559        case ShaderType::TessEvaluation:
   3560            if (!context->getExtensions().tessellationShaderEXT &&
   3561                context->getClientVersion() < ES_3_2)
   3562            {
   3563                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   3564                return false;
   3565            }
   3566            break;
   3567 
   3568        default:
   3569            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   3570            return false;
   3571    }
   3572 
   3573    return true;
   3574 }
   3575 
   3576 bool ValidateBufferData(const Context *context,
   3577                        angle::EntryPoint entryPoint,
   3578                        BufferBinding target,
   3579                        GLsizeiptr size,
   3580                        const void *data,
   3581                        BufferUsage usage)
   3582 {
   3583    if (size < 0)
   3584    {
   3585        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   3586        return false;
   3587    }
   3588 
   3589    switch (usage)
   3590    {
   3591        case BufferUsage::StreamDraw:
   3592        case BufferUsage::StaticDraw:
   3593        case BufferUsage::DynamicDraw:
   3594            break;
   3595 
   3596        case BufferUsage::StreamRead:
   3597        case BufferUsage::StaticRead:
   3598        case BufferUsage::DynamicRead:
   3599        case BufferUsage::StreamCopy:
   3600        case BufferUsage::StaticCopy:
   3601        case BufferUsage::DynamicCopy:
   3602            if (context->getClientMajorVersion() < 3)
   3603            {
   3604                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferUsage);
   3605                return false;
   3606            }
   3607            break;
   3608 
   3609        default:
   3610            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferUsage);
   3611            return false;
   3612    }
   3613 
   3614    if (!context->isValidBufferBinding(target))
   3615    {
   3616        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   3617        return false;
   3618    }
   3619 
   3620    Buffer *buffer = context->getState().getTargetBuffer(target);
   3621 
   3622    if (!buffer)
   3623    {
   3624        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
   3625        return false;
   3626    }
   3627 
   3628    if (buffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   3629    {
   3630        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3631                                 kBufferBoundForTransformFeedback);
   3632        return false;
   3633    }
   3634 
   3635    if (buffer->isImmutable())
   3636    {
   3637        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferImmutable);
   3638        return false;
   3639    }
   3640 
   3641    return true;
   3642 }
   3643 
   3644 bool ValidateBufferSubData(const Context *context,
   3645                           angle::EntryPoint entryPoint,
   3646                           BufferBinding target,
   3647                           GLintptr offset,
   3648                           GLsizeiptr size,
   3649                           const void *data)
   3650 {
   3651    if (size < 0)
   3652    {
   3653        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   3654        return false;
   3655    }
   3656 
   3657    if (offset < 0)
   3658    {
   3659        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   3660        return false;
   3661    }
   3662 
   3663    if (!context->isValidBufferBinding(target))
   3664    {
   3665        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   3666        return false;
   3667    }
   3668 
   3669    Buffer *buffer = context->getState().getTargetBuffer(target);
   3670 
   3671    if (!buffer)
   3672    {
   3673        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
   3674        return false;
   3675    }
   3676 
   3677    // EXT_buffer_storage allows persistently mapped buffers to be updated via glBufferSubData
   3678    bool isPersistent = (buffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) != 0;
   3679 
   3680    // Verify that buffer is not currently mapped unless persistent
   3681    if (buffer->isMapped() && !isPersistent)
   3682    {
   3683        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
   3684        return false;
   3685    }
   3686 
   3687    if (buffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   3688    {
   3689        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3690                                 kBufferBoundForTransformFeedback);
   3691        return false;
   3692    }
   3693 
   3694    if (buffer->isImmutable() &&
   3695        (buffer->getStorageExtUsageFlags() & GL_DYNAMIC_STORAGE_BIT_EXT) == 0)
   3696    {
   3697        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotUpdatable);
   3698        return false;
   3699    }
   3700 
   3701    // Check for possible overflow of size + offset
   3702    angle::CheckedNumeric<decltype(size + offset)> checkedSize(size);
   3703    checkedSize += offset;
   3704    if (!checkedSize.IsValid())
   3705    {
   3706        context->validationError(entryPoint, GL_INVALID_VALUE, kParamOverflow);
   3707        return false;
   3708    }
   3709 
   3710    if (size + offset > buffer->getSize())
   3711    {
   3712        context->validationError(entryPoint, GL_INVALID_VALUE, kInsufficientBufferSize);
   3713        return false;
   3714    }
   3715 
   3716    return true;
   3717 }
   3718 
   3719 bool ValidateRequestExtensionANGLE(const Context *context,
   3720                                   angle::EntryPoint entryPoint,
   3721                                   const GLchar *name)
   3722 {
   3723    if (!context->getExtensions().requestExtensionANGLE)
   3724    {
   3725        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3726        return false;
   3727    }
   3728 
   3729    if (!context->isExtensionRequestable(name))
   3730    {
   3731        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotRequestable);
   3732        return false;
   3733    }
   3734 
   3735    return true;
   3736 }
   3737 
   3738 bool ValidateDisableExtensionANGLE(const Context *context,
   3739                                   angle::EntryPoint entryPoint,
   3740                                   const GLchar *name)
   3741 {
   3742    if (!context->getExtensions().requestExtensionANGLE)
   3743    {
   3744        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   3745        return false;
   3746    }
   3747 
   3748    if (!context->isExtensionDisablable(name))
   3749    {
   3750        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotDisablable);
   3751        return false;
   3752    }
   3753 
   3754    return true;
   3755 }
   3756 
   3757 bool ValidateActiveTexture(const Context *context, angle::EntryPoint entryPoint, GLenum texture)
   3758 {
   3759    if (context->getClientMajorVersion() < 2)
   3760    {
   3761        return ValidateMultitextureUnit(context, entryPoint, texture);
   3762    }
   3763 
   3764    if (texture < GL_TEXTURE0 ||
   3765        texture >
   3766            GL_TEXTURE0 + static_cast<GLuint>(context->getCaps().maxCombinedTextureImageUnits) - 1)
   3767    {
   3768        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCombinedImageUnit);
   3769        return false;
   3770    }
   3771 
   3772    return true;
   3773 }
   3774 
   3775 bool ValidateAttachShader(const Context *context,
   3776                          angle::EntryPoint entryPoint,
   3777                          ShaderProgramID program,
   3778                          ShaderProgramID shader)
   3779 {
   3780    Program *programObject = GetValidProgram(context, entryPoint, program);
   3781    if (!programObject)
   3782    {
   3783        return false;
   3784    }
   3785 
   3786    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
   3787    if (!shaderObject)
   3788    {
   3789        return false;
   3790    }
   3791 
   3792    if (programObject->getAttachedShader(shaderObject->getType()))
   3793    {
   3794        context->validationError(entryPoint, GL_INVALID_OPERATION, kShaderAttachmentHasShader);
   3795        return false;
   3796    }
   3797 
   3798    return true;
   3799 }
   3800 
   3801 bool ValidateBindAttribLocation(const Context *context,
   3802                                angle::EntryPoint entryPoint,
   3803                                ShaderProgramID program,
   3804                                GLuint index,
   3805                                const GLchar *name)
   3806 {
   3807    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
   3808    {
   3809        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   3810        return false;
   3811    }
   3812 
   3813    if (strncmp(name, "gl_", 3) == 0)
   3814    {
   3815        context->validationError(entryPoint, GL_INVALID_OPERATION, kNameBeginsWithGL);
   3816        return false;
   3817    }
   3818 
   3819    if (context->isWebGL())
   3820    {
   3821        const size_t length = strlen(name);
   3822 
   3823        if (!IsValidESSLString(name, length))
   3824        {
   3825            // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
   3826            // for shader-related entry points
   3827            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
   3828            return false;
   3829        }
   3830 
   3831        if (!ValidateWebGLNameLength(context, entryPoint, length) ||
   3832            !ValidateWebGLNamePrefix(context, entryPoint, name))
   3833        {
   3834            return false;
   3835        }
   3836    }
   3837 
   3838    return GetValidProgram(context, entryPoint, program) != nullptr;
   3839 }
   3840 
   3841 bool ValidateBindFramebuffer(const Context *context,
   3842                             angle::EntryPoint entryPoint,
   3843                             GLenum target,
   3844                             FramebufferID framebuffer)
   3845 {
   3846    return ValidateBindFramebufferBase(context, entryPoint, target, framebuffer);
   3847 }
   3848 
   3849 bool ValidateBindRenderbuffer(const Context *context,
   3850                              angle::EntryPoint entryPoint,
   3851                              GLenum target,
   3852                              RenderbufferID renderbuffer)
   3853 {
   3854    return ValidateBindRenderbufferBase(context, entryPoint, target, renderbuffer);
   3855 }
   3856 
   3857 static bool ValidBlendEquationMode(const Context *context, GLenum mode)
   3858 {
   3859    switch (mode)
   3860    {
   3861        case GL_FUNC_ADD:
   3862        case GL_FUNC_SUBTRACT:
   3863        case GL_FUNC_REVERSE_SUBTRACT:
   3864            return true;
   3865 
   3866        case GL_MIN:
   3867        case GL_MAX:
   3868            return context->getClientVersion() >= ES_3_0 || context->getExtensions().blendMinmaxEXT;
   3869 
   3870        default:
   3871            return false;
   3872    }
   3873 }
   3874 
   3875 static bool ValidAdvancedBlendEquationMode(const Context *context, GLenum mode)
   3876 {
   3877    switch (mode)
   3878    {
   3879        case GL_MULTIPLY_KHR:
   3880        case GL_SCREEN_KHR:
   3881        case GL_OVERLAY_KHR:
   3882        case GL_DARKEN_KHR:
   3883        case GL_LIGHTEN_KHR:
   3884        case GL_COLORDODGE_KHR:
   3885        case GL_COLORBURN_KHR:
   3886        case GL_HARDLIGHT_KHR:
   3887        case GL_SOFTLIGHT_KHR:
   3888        case GL_DIFFERENCE_KHR:
   3889        case GL_EXCLUSION_KHR:
   3890        case GL_HSL_HUE_KHR:
   3891        case GL_HSL_SATURATION_KHR:
   3892        case GL_HSL_COLOR_KHR:
   3893        case GL_HSL_LUMINOSITY_KHR:
   3894            return context->getClientVersion() >= ES_3_2 ||
   3895                   context->getExtensions().blendEquationAdvancedKHR;
   3896 
   3897        default:
   3898            return false;
   3899    }
   3900 }
   3901 
   3902 bool ValidateBlendColor(const Context *context,
   3903                        angle::EntryPoint entryPoint,
   3904                        GLfloat red,
   3905                        GLfloat green,
   3906                        GLfloat blue,
   3907                        GLfloat alpha)
   3908 {
   3909    return true;
   3910 }
   3911 
   3912 bool ValidateBlendEquation(const Context *context, angle::EntryPoint entryPoint, GLenum mode)
   3913 {
   3914    if (!ValidBlendEquationMode(context, mode) && !ValidAdvancedBlendEquationMode(context, mode))
   3915    {
   3916        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
   3917        return false;
   3918    }
   3919 
   3920    return true;
   3921 }
   3922 
   3923 bool ValidateBlendEquationSeparate(const Context *context,
   3924                                   angle::EntryPoint entryPoint,
   3925                                   GLenum modeRGB,
   3926                                   GLenum modeAlpha)
   3927 {
   3928    if (!ValidBlendEquationMode(context, modeRGB))
   3929    {
   3930        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
   3931        return false;
   3932    }
   3933 
   3934    if (!ValidBlendEquationMode(context, modeAlpha))
   3935    {
   3936        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendEquation);
   3937        return false;
   3938    }
   3939 
   3940    return true;
   3941 }
   3942 
   3943 bool ValidateBlendFunc(const Context *context,
   3944                       angle::EntryPoint entryPoint,
   3945                       GLenum sfactor,
   3946                       GLenum dfactor)
   3947 {
   3948    return ValidateBlendFuncSeparate(context, entryPoint, sfactor, dfactor, sfactor, dfactor);
   3949 }
   3950 
   3951 bool ValidateBlendFuncSeparate(const Context *context,
   3952                               angle::EntryPoint entryPoint,
   3953                               GLenum srcRGB,
   3954                               GLenum dstRGB,
   3955                               GLenum srcAlpha,
   3956                               GLenum dstAlpha)
   3957 {
   3958    if (!ValidSrcBlendFunc(context, srcRGB))
   3959    {
   3960        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
   3961        return false;
   3962    }
   3963 
   3964    if (!ValidDstBlendFunc(context, dstRGB))
   3965    {
   3966        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
   3967        return false;
   3968    }
   3969 
   3970    if (!ValidSrcBlendFunc(context, srcAlpha))
   3971    {
   3972        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
   3973        return false;
   3974    }
   3975 
   3976    if (!ValidDstBlendFunc(context, dstAlpha))
   3977    {
   3978        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBlendFunction);
   3979        return false;
   3980    }
   3981 
   3982    if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
   3983        context->isWebGL())
   3984    {
   3985        bool constantColorUsed =
   3986            (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
   3987             dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
   3988 
   3989        bool constantAlphaUsed =
   3990            (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
   3991             dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
   3992 
   3993        if (constantColorUsed && constantAlphaUsed)
   3994        {
   3995            if (context->isWebGL())
   3996            {
   3997                context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidConstantColor);
   3998                return false;
   3999            }
   4000 
   4001            WARN() << kConstantColorAlphaLimitation;
   4002            context->validationError(entryPoint, GL_INVALID_OPERATION,
   4003                                     kConstantColorAlphaLimitation);
   4004            return false;
   4005        }
   4006    }
   4007 
   4008    return true;
   4009 }
   4010 
   4011 bool ValidateGetString(const Context *context, angle::EntryPoint entryPoint, GLenum name)
   4012 {
   4013    switch (name)
   4014    {
   4015        case GL_VENDOR:
   4016        case GL_RENDERER:
   4017        case GL_VERSION:
   4018        case GL_SHADING_LANGUAGE_VERSION:
   4019        case GL_EXTENSIONS:
   4020            break;
   4021 
   4022        case GL_REQUESTABLE_EXTENSIONS_ANGLE:
   4023            if (!context->getExtensions().requestExtensionANGLE)
   4024            {
   4025                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
   4026                return false;
   4027            }
   4028            break;
   4029 
   4030        case GL_SERIALIZED_CONTEXT_STRING_ANGLE:
   4031            if (!context->getExtensions().getSerializedContextStringANGLE)
   4032            {
   4033                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
   4034                return false;
   4035            }
   4036            break;
   4037 
   4038        default:
   4039            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidName);
   4040            return false;
   4041    }
   4042 
   4043    return true;
   4044 }
   4045 
   4046 bool ValidateLineWidth(const Context *context, angle::EntryPoint entryPoint, GLfloat width)
   4047 {
   4048    if (width <= 0.0f || isNaN(width))
   4049    {
   4050        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidWidth);
   4051        return false;
   4052    }
   4053 
   4054    return true;
   4055 }
   4056 
   4057 bool ValidateDepthRangef(const Context *context,
   4058                         angle::EntryPoint entryPoint,
   4059                         GLfloat zNear,
   4060                         GLfloat zFar)
   4061 {
   4062    if (context->isWebGL() && zNear > zFar)
   4063    {
   4064        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDepthRange);
   4065        return false;
   4066    }
   4067 
   4068    return true;
   4069 }
   4070 
   4071 bool ValidateRenderbufferStorage(const Context *context,
   4072                                 angle::EntryPoint entryPoint,
   4073                                 GLenum target,
   4074                                 GLenum internalformat,
   4075                                 GLsizei width,
   4076                                 GLsizei height)
   4077 {
   4078    return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, 0, internalformat,
   4079                                                     width, height);
   4080 }
   4081 
   4082 bool ValidateRenderbufferStorageMultisampleANGLE(const Context *context,
   4083                                                 angle::EntryPoint entryPoint,
   4084                                                 GLenum target,
   4085                                                 GLsizei samples,
   4086                                                 GLenum internalformat,
   4087                                                 GLsizei width,
   4088                                                 GLsizei height)
   4089 {
   4090    if (!context->getExtensions().framebufferMultisampleANGLE)
   4091    {
   4092        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4093        return false;
   4094    }
   4095 
   4096    // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
   4097    // to MAX_SAMPLES_ANGLE (Context::getCaps().maxSamples) otherwise GL_INVALID_VALUE is
   4098    // generated.
   4099    if (samples > context->getCaps().maxSamples)
   4100    {
   4101        context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange);
   4102        return false;
   4103    }
   4104 
   4105    // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
   4106    // the specified storage. This is different than ES 3.0 in which a sample number higher
   4107    // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
   4108    // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
   4109    if (context->getClientMajorVersion() >= 3)
   4110    {
   4111        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
   4112        if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
   4113        {
   4114            context->validationError(entryPoint, GL_OUT_OF_MEMORY, kSamplesOutOfRange);
   4115            return false;
   4116        }
   4117    }
   4118 
   4119    return ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
   4120                                                     internalformat, width, height);
   4121 }
   4122 
   4123 bool ValidateCheckFramebufferStatus(const Context *context,
   4124                                    angle::EntryPoint entryPoint,
   4125                                    GLenum target)
   4126 {
   4127    if (!ValidFramebufferTarget(context, target))
   4128    {
   4129        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   4130        return false;
   4131    }
   4132 
   4133    return true;
   4134 }
   4135 
   4136 bool ValidateClearColor(const Context *context,
   4137                        angle::EntryPoint entryPoint,
   4138                        GLfloat red,
   4139                        GLfloat green,
   4140                        GLfloat blue,
   4141                        GLfloat alpha)
   4142 {
   4143    return true;
   4144 }
   4145 
   4146 bool ValidateClearDepthf(const Context *context, angle::EntryPoint entryPoint, GLfloat depth)
   4147 {
   4148    return true;
   4149 }
   4150 
   4151 bool ValidateClearStencil(const Context *context, angle::EntryPoint entryPoint, GLint s)
   4152 {
   4153    return true;
   4154 }
   4155 
   4156 bool ValidateColorMask(const Context *context,
   4157                       angle::EntryPoint entryPoint,
   4158                       GLboolean red,
   4159                       GLboolean green,
   4160                       GLboolean blue,
   4161                       GLboolean alpha)
   4162 {
   4163    return true;
   4164 }
   4165 
   4166 bool ValidateCompileShader(const Context *context,
   4167                           angle::EntryPoint entryPoint,
   4168                           ShaderProgramID shader)
   4169 {
   4170    return true;
   4171 }
   4172 
   4173 bool ValidateCreateProgram(const Context *context, angle::EntryPoint entryPoint)
   4174 {
   4175    return true;
   4176 }
   4177 
   4178 bool ValidateCullFace(const Context *context, angle::EntryPoint entryPoint, CullFaceMode mode)
   4179 {
   4180    switch (mode)
   4181    {
   4182        case CullFaceMode::Front:
   4183        case CullFaceMode::Back:
   4184        case CullFaceMode::FrontAndBack:
   4185            break;
   4186 
   4187        default:
   4188            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidCullMode);
   4189            return false;
   4190    }
   4191 
   4192    return true;
   4193 }
   4194 
   4195 bool ValidateDeleteProgram(const Context *context,
   4196                           angle::EntryPoint entryPoint,
   4197                           ShaderProgramID program)
   4198 {
   4199    if (program.value == 0)
   4200    {
   4201        return false;
   4202    }
   4203 
   4204    if (!context->getProgramResolveLink(program))
   4205    {
   4206        if (context->getShader(program))
   4207        {
   4208            context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
   4209            return false;
   4210        }
   4211        else
   4212        {
   4213            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
   4214            return false;
   4215        }
   4216    }
   4217 
   4218    return true;
   4219 }
   4220 
   4221 bool ValidateDeleteShader(const Context *context,
   4222                          angle::EntryPoint entryPoint,
   4223                          ShaderProgramID shader)
   4224 {
   4225    if (shader.value == 0)
   4226    {
   4227        return false;
   4228    }
   4229 
   4230    if (!context->getShader(shader))
   4231    {
   4232        if (context->getProgramResolveLink(shader))
   4233        {
   4234            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName);
   4235            return false;
   4236        }
   4237        else
   4238        {
   4239            context->validationError(entryPoint, GL_INVALID_VALUE, kExpectedShaderName);
   4240            return false;
   4241        }
   4242    }
   4243 
   4244    return true;
   4245 }
   4246 
   4247 bool ValidateDepthFunc(const Context *context, angle::EntryPoint entryPoint, GLenum func)
   4248 {
   4249    switch (func)
   4250    {
   4251        case GL_NEVER:
   4252        case GL_ALWAYS:
   4253        case GL_LESS:
   4254        case GL_LEQUAL:
   4255        case GL_EQUAL:
   4256        case GL_GREATER:
   4257        case GL_GEQUAL:
   4258        case GL_NOTEQUAL:
   4259            break;
   4260 
   4261        default:
   4262            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, func);
   4263            return false;
   4264    }
   4265 
   4266    return true;
   4267 }
   4268 
   4269 bool ValidateDepthMask(const Context *context, angle::EntryPoint entryPoint, GLboolean flag)
   4270 {
   4271    return true;
   4272 }
   4273 
   4274 bool ValidateDetachShader(const Context *context,
   4275                          angle::EntryPoint entryPoint,
   4276                          ShaderProgramID program,
   4277                          ShaderProgramID shader)
   4278 {
   4279    Program *programObject = GetValidProgram(context, entryPoint, program);
   4280    if (!programObject)
   4281    {
   4282        return false;
   4283    }
   4284 
   4285    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
   4286    if (!shaderObject)
   4287    {
   4288        return false;
   4289    }
   4290 
   4291    const Shader *attachedShader = programObject->getAttachedShader(shaderObject->getType());
   4292    if (attachedShader != shaderObject)
   4293    {
   4294        context->validationError(entryPoint, GL_INVALID_OPERATION, kShaderToDetachMustBeAttached);
   4295        return false;
   4296    }
   4297 
   4298    return true;
   4299 }
   4300 
   4301 bool ValidateDisableVertexAttribArray(const Context *context,
   4302                                      angle::EntryPoint entryPoint,
   4303                                      GLuint index)
   4304 {
   4305    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
   4306    {
   4307        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   4308        return false;
   4309    }
   4310 
   4311    return true;
   4312 }
   4313 
   4314 bool ValidateEnableVertexAttribArray(const Context *context,
   4315                                     angle::EntryPoint entryPoint,
   4316                                     GLuint index)
   4317 {
   4318    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
   4319    {
   4320        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   4321        return false;
   4322    }
   4323 
   4324    return true;
   4325 }
   4326 
   4327 bool ValidateFinish(const Context *context, angle::EntryPoint entryPoint)
   4328 {
   4329    return true;
   4330 }
   4331 
   4332 bool ValidateFlush(const Context *context, angle::EntryPoint entryPoint)
   4333 {
   4334    return true;
   4335 }
   4336 
   4337 bool ValidateFrontFace(const Context *context, angle::EntryPoint entryPoint, GLenum mode)
   4338 {
   4339    switch (mode)
   4340    {
   4341        case GL_CW:
   4342        case GL_CCW:
   4343            break;
   4344        default:
   4345            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode);
   4346            return false;
   4347    }
   4348 
   4349    return true;
   4350 }
   4351 
   4352 bool ValidateGetActiveAttrib(const Context *context,
   4353                             angle::EntryPoint entryPoint,
   4354                             ShaderProgramID program,
   4355                             GLuint index,
   4356                             GLsizei bufsize,
   4357                             const GLsizei *length,
   4358                             const GLint *size,
   4359                             const GLenum *type,
   4360                             const GLchar *name)
   4361 {
   4362    if (bufsize < 0)
   4363    {
   4364        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   4365        return false;
   4366    }
   4367 
   4368    Program *programObject = GetValidProgram(context, entryPoint, program);
   4369 
   4370    if (!programObject)
   4371    {
   4372        return false;
   4373    }
   4374 
   4375    if (index >= static_cast<GLuint>(programObject->getActiveAttributeCount()))
   4376    {
   4377        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
   4378        return false;
   4379    }
   4380 
   4381    return true;
   4382 }
   4383 
   4384 bool ValidateGetActiveUniform(const Context *context,
   4385                              angle::EntryPoint entryPoint,
   4386                              ShaderProgramID program,
   4387                              GLuint index,
   4388                              GLsizei bufsize,
   4389                              const GLsizei *length,
   4390                              const GLint *size,
   4391                              const GLenum *type,
   4392                              const GLchar *name)
   4393 {
   4394    if (bufsize < 0)
   4395    {
   4396        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   4397        return false;
   4398    }
   4399 
   4400    Program *programObject = GetValidProgram(context, entryPoint, program);
   4401 
   4402    if (!programObject)
   4403    {
   4404        return false;
   4405    }
   4406 
   4407    if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
   4408    {
   4409        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxActiveUniform);
   4410        return false;
   4411    }
   4412 
   4413    return true;
   4414 }
   4415 
   4416 bool ValidateGetAttachedShaders(const Context *context,
   4417                                angle::EntryPoint entryPoint,
   4418                                ShaderProgramID program,
   4419                                GLsizei maxcount,
   4420                                const GLsizei *count,
   4421                                const ShaderProgramID *shaders)
   4422 {
   4423    if (maxcount < 0)
   4424    {
   4425        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeMaxCount);
   4426        return false;
   4427    }
   4428 
   4429    Program *programObject = GetValidProgram(context, entryPoint, program);
   4430 
   4431    if (!programObject)
   4432    {
   4433        return false;
   4434    }
   4435 
   4436    return true;
   4437 }
   4438 
   4439 bool ValidateGetAttribLocation(const Context *context,
   4440                               angle::EntryPoint entryPoint,
   4441                               ShaderProgramID program,
   4442                               const GLchar *name)
   4443 {
   4444    if (strncmp(name, "gl_", 3) == 0)
   4445    {
   4446        return false;
   4447    }
   4448 
   4449    if (context->isWebGL())
   4450    {
   4451        const size_t length = strlen(name);
   4452 
   4453        if (!IsValidESSLString(name, length))
   4454        {
   4455            // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters
   4456            // for shader-related entry points
   4457            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
   4458            return false;
   4459        }
   4460 
   4461        if (!ValidateWebGLNameLength(context, entryPoint, length) ||
   4462            strncmp(name, "webgl_", 6) == 0 || strncmp(name, "_webgl_", 7) == 0)
   4463        {
   4464            return false;
   4465        }
   4466    }
   4467 
   4468    Program *programObject = GetValidProgram(context, entryPoint, program);
   4469 
   4470    if (!programObject)
   4471    {
   4472        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotBound);
   4473        return false;
   4474    }
   4475 
   4476    if (!programObject->isLinked())
   4477    {
   4478        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   4479        return false;
   4480    }
   4481 
   4482    return true;
   4483 }
   4484 
   4485 bool ValidateGetBooleanv(const Context *context,
   4486                         angle::EntryPoint entryPoint,
   4487                         GLenum pname,
   4488                         const GLboolean *params)
   4489 {
   4490    GLenum nativeType;
   4491    unsigned int numParams = 0;
   4492    return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
   4493 }
   4494 
   4495 bool ValidateGetError(const Context *context, angle::EntryPoint entryPoint)
   4496 {
   4497    return true;
   4498 }
   4499 
   4500 bool ValidateGetFloatv(const Context *context,
   4501                       angle::EntryPoint entryPoint,
   4502                       GLenum pname,
   4503                       const GLfloat *params)
   4504 {
   4505    GLenum nativeType;
   4506    unsigned int numParams = 0;
   4507    return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
   4508 }
   4509 
   4510 bool ValidateGetIntegerv(const Context *context,
   4511                         angle::EntryPoint entryPoint,
   4512                         GLenum pname,
   4513                         const GLint *params)
   4514 {
   4515    GLenum nativeType;
   4516    unsigned int numParams = 0;
   4517    return ValidateStateQuery(context, entryPoint, pname, &nativeType, &numParams);
   4518 }
   4519 
   4520 bool ValidateGetProgramInfoLog(const Context *context,
   4521                               angle::EntryPoint entryPoint,
   4522                               ShaderProgramID program,
   4523                               GLsizei bufsize,
   4524                               const GLsizei *length,
   4525                               const GLchar *infolog)
   4526 {
   4527    if (bufsize < 0)
   4528    {
   4529        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   4530        return false;
   4531    }
   4532 
   4533    Program *programObject = GetValidProgram(context, entryPoint, program);
   4534    if (!programObject)
   4535    {
   4536        return false;
   4537    }
   4538 
   4539    return true;
   4540 }
   4541 
   4542 bool ValidateGetShaderInfoLog(const Context *context,
   4543                              angle::EntryPoint entryPoint,
   4544                              ShaderProgramID shader,
   4545                              GLsizei bufsize,
   4546                              const GLsizei *length,
   4547                              const GLchar *infolog)
   4548 {
   4549    if (bufsize < 0)
   4550    {
   4551        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   4552        return false;
   4553    }
   4554 
   4555    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
   4556    if (!shaderObject)
   4557    {
   4558        return false;
   4559    }
   4560 
   4561    return true;
   4562 }
   4563 
   4564 bool ValidateGetShaderPrecisionFormat(const Context *context,
   4565                                      angle::EntryPoint entryPoint,
   4566                                      GLenum shadertype,
   4567                                      GLenum precisiontype,
   4568                                      const GLint *range,
   4569                                      const GLint *precision)
   4570 {
   4571    switch (shadertype)
   4572    {
   4573        case GL_VERTEX_SHADER:
   4574        case GL_FRAGMENT_SHADER:
   4575            break;
   4576        case GL_COMPUTE_SHADER:
   4577            context->validationError(entryPoint, GL_INVALID_OPERATION,
   4578                                     kUnimplementedComputeShaderPrecision);
   4579            return false;
   4580        default:
   4581            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   4582            return false;
   4583    }
   4584 
   4585    switch (precisiontype)
   4586    {
   4587        case GL_LOW_FLOAT:
   4588        case GL_MEDIUM_FLOAT:
   4589        case GL_HIGH_FLOAT:
   4590        case GL_LOW_INT:
   4591        case GL_MEDIUM_INT:
   4592        case GL_HIGH_INT:
   4593            break;
   4594 
   4595        default:
   4596            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPrecision);
   4597            return false;
   4598    }
   4599 
   4600    return true;
   4601 }
   4602 
   4603 bool ValidateGetShaderSource(const Context *context,
   4604                             angle::EntryPoint entryPoint,
   4605                             ShaderProgramID shader,
   4606                             GLsizei bufsize,
   4607                             const GLsizei *length,
   4608                             const GLchar *source)
   4609 {
   4610    if (bufsize < 0)
   4611    {
   4612        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   4613        return false;
   4614    }
   4615 
   4616    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
   4617    if (!shaderObject)
   4618    {
   4619        return false;
   4620    }
   4621 
   4622    return true;
   4623 }
   4624 
   4625 bool ValidateGetUniformLocation(const Context *context,
   4626                                angle::EntryPoint entryPoint,
   4627                                ShaderProgramID program,
   4628                                const GLchar *name)
   4629 {
   4630    if (strstr(name, "gl_") == name)
   4631    {
   4632        return false;
   4633    }
   4634 
   4635    // The WebGL spec (section 6.20) disallows strings containing invalid ESSL characters for
   4636    // shader-related entry points
   4637    if (context->isWebGL() && !IsValidESSLString(name, strlen(name)))
   4638    {
   4639        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidNameCharacters);
   4640        return false;
   4641    }
   4642 
   4643    Program *programObject = GetValidProgram(context, entryPoint, program);
   4644 
   4645    if (!programObject)
   4646    {
   4647        return false;
   4648    }
   4649 
   4650    if (!programObject->isLinked())
   4651    {
   4652        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   4653        return false;
   4654    }
   4655 
   4656    return true;
   4657 }
   4658 
   4659 bool ValidateHint(const Context *context, angle::EntryPoint entryPoint, GLenum target, GLenum mode)
   4660 {
   4661    switch (mode)
   4662    {
   4663        case GL_FASTEST:
   4664        case GL_NICEST:
   4665        case GL_DONT_CARE:
   4666            break;
   4667 
   4668        default:
   4669            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, mode);
   4670            return false;
   4671    }
   4672 
   4673    switch (target)
   4674    {
   4675        case GL_GENERATE_MIPMAP_HINT:
   4676            break;
   4677 
   4678        case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
   4679            if (!context->getExtensions().textureFilteringHintCHROMIUM)
   4680            {
   4681                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
   4682                return false;
   4683            }
   4684            break;
   4685 
   4686        case GL_FRAGMENT_SHADER_DERIVATIVE_HINT:
   4687            if (context->getClientVersion() < ES_3_0 &&
   4688                !context->getExtensions().standardDerivativesOES)
   4689            {
   4690                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
   4691                return false;
   4692            }
   4693            break;
   4694 
   4695        case GL_PERSPECTIVE_CORRECTION_HINT:
   4696        case GL_POINT_SMOOTH_HINT:
   4697        case GL_LINE_SMOOTH_HINT:
   4698        case GL_FOG_HINT:
   4699            if (context->getClientMajorVersion() >= 2)
   4700            {
   4701                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
   4702                return false;
   4703            }
   4704            break;
   4705 
   4706        default:
   4707            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, target);
   4708            return false;
   4709    }
   4710 
   4711    return true;
   4712 }
   4713 
   4714 bool ValidateIsBuffer(const Context *context, angle::EntryPoint entryPoint, BufferID buffer)
   4715 {
   4716    return true;
   4717 }
   4718 
   4719 bool ValidateIsFramebuffer(const Context *context,
   4720                           angle::EntryPoint entryPoint,
   4721                           FramebufferID framebuffer)
   4722 {
   4723    return true;
   4724 }
   4725 
   4726 bool ValidateIsProgram(const Context *context,
   4727                       angle::EntryPoint entryPoint,
   4728                       ShaderProgramID program)
   4729 {
   4730    return true;
   4731 }
   4732 
   4733 bool ValidateIsRenderbuffer(const Context *context,
   4734                            angle::EntryPoint entryPoint,
   4735                            RenderbufferID renderbuffer)
   4736 {
   4737    return true;
   4738 }
   4739 
   4740 bool ValidateIsShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID shader)
   4741 {
   4742    return true;
   4743 }
   4744 
   4745 bool ValidateIsTexture(const Context *context, angle::EntryPoint entryPoint, TextureID texture)
   4746 {
   4747    return true;
   4748 }
   4749 
   4750 bool ValidatePixelStorei(const Context *context,
   4751                         angle::EntryPoint entryPoint,
   4752                         GLenum pname,
   4753                         GLint param)
   4754 {
   4755    if (context->getClientMajorVersion() < 3)
   4756    {
   4757        switch (pname)
   4758        {
   4759            case GL_UNPACK_IMAGE_HEIGHT:
   4760            case GL_UNPACK_SKIP_IMAGES:
   4761                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   4762                return false;
   4763 
   4764            case GL_UNPACK_ROW_LENGTH:
   4765            case GL_UNPACK_SKIP_ROWS:
   4766            case GL_UNPACK_SKIP_PIXELS:
   4767                if (!context->getExtensions().unpackSubimageEXT)
   4768                {
   4769                    context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   4770                    return false;
   4771                }
   4772                break;
   4773 
   4774            case GL_PACK_ROW_LENGTH:
   4775            case GL_PACK_SKIP_ROWS:
   4776            case GL_PACK_SKIP_PIXELS:
   4777                if (!context->getExtensions().packSubimageNV)
   4778                {
   4779                    context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   4780                    return false;
   4781                }
   4782                break;
   4783        }
   4784    }
   4785 
   4786    if (param < 0)
   4787    {
   4788        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeParam);
   4789        return false;
   4790    }
   4791 
   4792    switch (pname)
   4793    {
   4794        case GL_UNPACK_ALIGNMENT:
   4795            if (param != 1 && param != 2 && param != 4 && param != 8)
   4796            {
   4797                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidUnpackAlignment);
   4798                return false;
   4799            }
   4800            break;
   4801 
   4802        case GL_PACK_ALIGNMENT:
   4803            if (param != 1 && param != 2 && param != 4 && param != 8)
   4804            {
   4805                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidUnpackAlignment);
   4806                return false;
   4807            }
   4808            break;
   4809 
   4810        case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
   4811            if (!context->getExtensions().packReverseRowOrderANGLE)
   4812            {
   4813                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   4814            }
   4815            break;
   4816 
   4817        case GL_UNPACK_ROW_LENGTH:
   4818        case GL_UNPACK_IMAGE_HEIGHT:
   4819        case GL_UNPACK_SKIP_IMAGES:
   4820        case GL_UNPACK_SKIP_ROWS:
   4821        case GL_UNPACK_SKIP_PIXELS:
   4822        case GL_PACK_ROW_LENGTH:
   4823        case GL_PACK_SKIP_ROWS:
   4824        case GL_PACK_SKIP_PIXELS:
   4825            break;
   4826 
   4827        default:
   4828            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   4829            return false;
   4830    }
   4831 
   4832    return true;
   4833 }
   4834 
   4835 bool ValidatePolygonOffset(const Context *context,
   4836                           angle::EntryPoint entryPoint,
   4837                           GLfloat factor,
   4838                           GLfloat units)
   4839 {
   4840    return true;
   4841 }
   4842 
   4843 bool ValidateReleaseShaderCompiler(const Context *context, angle::EntryPoint entryPoint)
   4844 {
   4845    return true;
   4846 }
   4847 
   4848 bool ValidateSampleCoverage(const Context *context,
   4849                            angle::EntryPoint entryPoint,
   4850                            GLfloat value,
   4851                            GLboolean invert)
   4852 {
   4853    return true;
   4854 }
   4855 
   4856 bool ValidateScissor(const Context *context,
   4857                     angle::EntryPoint entryPoint,
   4858                     GLint x,
   4859                     GLint y,
   4860                     GLsizei width,
   4861                     GLsizei height)
   4862 {
   4863    if (width < 0 || height < 0)
   4864    {
   4865        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   4866        return false;
   4867    }
   4868 
   4869    return true;
   4870 }
   4871 
   4872 bool ValidateShaderBinary(const Context *context,
   4873                          angle::EntryPoint entryPoint,
   4874                          GLsizei n,
   4875                          const ShaderProgramID *shaders,
   4876                          GLenum binaryformat,
   4877                          const void *binary,
   4878                          GLsizei length)
   4879 {
   4880    const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
   4881    if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) ==
   4882        shaderBinaryFormats.end())
   4883    {
   4884        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderBinaryFormat);
   4885        return false;
   4886    }
   4887 
   4888    return true;
   4889 }
   4890 
   4891 bool ValidateShaderSource(const Context *context,
   4892                          angle::EntryPoint entryPoint,
   4893                          ShaderProgramID shader,
   4894                          GLsizei count,
   4895                          const GLchar *const *string,
   4896                          const GLint *length)
   4897 {
   4898    if (count < 0)
   4899    {
   4900        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   4901        return false;
   4902    }
   4903 
   4904    Shader *shaderObject = GetValidShader(context, entryPoint, shader);
   4905    if (!shaderObject)
   4906    {
   4907        return false;
   4908    }
   4909 
   4910    return true;
   4911 }
   4912 
   4913 bool ValidateStencilFunc(const Context *context,
   4914                         angle::EntryPoint entryPoint,
   4915                         GLenum func,
   4916                         GLint ref,
   4917                         GLuint mask)
   4918 {
   4919    if (!IsValidStencilFunc(func))
   4920    {
   4921        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4922        return false;
   4923    }
   4924 
   4925    return true;
   4926 }
   4927 
   4928 bool ValidateStencilFuncSeparate(const Context *context,
   4929                                 angle::EntryPoint entryPoint,
   4930                                 GLenum face,
   4931                                 GLenum func,
   4932                                 GLint ref,
   4933                                 GLuint mask)
   4934 {
   4935    if (!IsValidStencilFace(face))
   4936    {
   4937        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4938        return false;
   4939    }
   4940 
   4941    if (!IsValidStencilFunc(func))
   4942    {
   4943        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4944        return false;
   4945    }
   4946 
   4947    return true;
   4948 }
   4949 
   4950 bool ValidateStencilMask(const Context *context, angle::EntryPoint entryPoint, GLuint mask)
   4951 {
   4952    return true;
   4953 }
   4954 
   4955 bool ValidateStencilMaskSeparate(const Context *context,
   4956                                 angle::EntryPoint entryPoint,
   4957                                 GLenum face,
   4958                                 GLuint mask)
   4959 {
   4960    if (!IsValidStencilFace(face))
   4961    {
   4962        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4963        return false;
   4964    }
   4965 
   4966    return true;
   4967 }
   4968 
   4969 bool ValidateStencilOp(const Context *context,
   4970                       angle::EntryPoint entryPoint,
   4971                       GLenum fail,
   4972                       GLenum zfail,
   4973                       GLenum zpass)
   4974 {
   4975    if (!IsValidStencilOp(fail))
   4976    {
   4977        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4978        return false;
   4979    }
   4980 
   4981    if (!IsValidStencilOp(zfail))
   4982    {
   4983        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4984        return false;
   4985    }
   4986 
   4987    if (!IsValidStencilOp(zpass))
   4988    {
   4989        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   4990        return false;
   4991    }
   4992 
   4993    return true;
   4994 }
   4995 
   4996 bool ValidateStencilOpSeparate(const Context *context,
   4997                               angle::EntryPoint entryPoint,
   4998                               GLenum face,
   4999                               GLenum fail,
   5000                               GLenum zfail,
   5001                               GLenum zpass)
   5002 {
   5003    if (!IsValidStencilFace(face))
   5004    {
   5005        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidStencil);
   5006        return false;
   5007    }
   5008 
   5009    return ValidateStencilOp(context, entryPoint, fail, zfail, zpass);
   5010 }
   5011 
   5012 bool ValidateUniform1f(const Context *context,
   5013                       angle::EntryPoint entryPoint,
   5014                       UniformLocation location,
   5015                       GLfloat x)
   5016 {
   5017    return ValidateUniform(context, entryPoint, GL_FLOAT, location, 1);
   5018 }
   5019 
   5020 bool ValidateUniform1fv(const Context *context,
   5021                        angle::EntryPoint entryPoint,
   5022                        UniformLocation location,
   5023                        GLsizei count,
   5024                        const GLfloat *v)
   5025 {
   5026    return ValidateUniform(context, entryPoint, GL_FLOAT, location, count);
   5027 }
   5028 
   5029 bool ValidateUniform1i(const Context *context,
   5030                       angle::EntryPoint entryPoint,
   5031                       UniformLocation location,
   5032                       GLint x)
   5033 {
   5034    return ValidateUniform1iv(context, entryPoint, location, 1, &x);
   5035 }
   5036 
   5037 bool ValidateUniform2fv(const Context *context,
   5038                        angle::EntryPoint entryPoint,
   5039                        UniformLocation location,
   5040                        GLsizei count,
   5041                        const GLfloat *v)
   5042 {
   5043    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC2, location, count);
   5044 }
   5045 
   5046 bool ValidateUniform2i(const Context *context,
   5047                       angle::EntryPoint entryPoint,
   5048                       UniformLocation location,
   5049                       GLint x,
   5050                       GLint y)
   5051 {
   5052    return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, 1);
   5053 }
   5054 
   5055 bool ValidateUniform2iv(const Context *context,
   5056                        angle::EntryPoint entryPoint,
   5057                        UniformLocation location,
   5058                        GLsizei count,
   5059                        const GLint *v)
   5060 {
   5061    return ValidateUniform(context, entryPoint, GL_INT_VEC2, location, count);
   5062 }
   5063 
   5064 bool ValidateUniform3f(const Context *context,
   5065                       angle::EntryPoint entryPoint,
   5066                       UniformLocation location,
   5067                       GLfloat x,
   5068                       GLfloat y,
   5069                       GLfloat z)
   5070 {
   5071    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, 1);
   5072 }
   5073 
   5074 bool ValidateUniform3fv(const Context *context,
   5075                        angle::EntryPoint entryPoint,
   5076                        UniformLocation location,
   5077                        GLsizei count,
   5078                        const GLfloat *v)
   5079 {
   5080    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC3, location, count);
   5081 }
   5082 
   5083 bool ValidateUniform3i(const Context *context,
   5084                       angle::EntryPoint entryPoint,
   5085                       UniformLocation location,
   5086                       GLint x,
   5087                       GLint y,
   5088                       GLint z)
   5089 {
   5090    return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, 1);
   5091 }
   5092 
   5093 bool ValidateUniform3iv(const Context *context,
   5094                        angle::EntryPoint entryPoint,
   5095                        UniformLocation location,
   5096                        GLsizei count,
   5097                        const GLint *v)
   5098 {
   5099    return ValidateUniform(context, entryPoint, GL_INT_VEC3, location, count);
   5100 }
   5101 
   5102 bool ValidateUniform4f(const Context *context,
   5103                       angle::EntryPoint entryPoint,
   5104                       UniformLocation location,
   5105                       GLfloat x,
   5106                       GLfloat y,
   5107                       GLfloat z,
   5108                       GLfloat w)
   5109 {
   5110    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, 1);
   5111 }
   5112 
   5113 bool ValidateUniform4fv(const Context *context,
   5114                        angle::EntryPoint entryPoint,
   5115                        UniformLocation location,
   5116                        GLsizei count,
   5117                        const GLfloat *v)
   5118 {
   5119    return ValidateUniform(context, entryPoint, GL_FLOAT_VEC4, location, count);
   5120 }
   5121 
   5122 bool ValidateUniform4i(const Context *context,
   5123                       angle::EntryPoint entryPoint,
   5124                       UniformLocation location,
   5125                       GLint x,
   5126                       GLint y,
   5127                       GLint z,
   5128                       GLint w)
   5129 {
   5130    return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, 1);
   5131 }
   5132 
   5133 bool ValidateUniform4iv(const Context *context,
   5134                        angle::EntryPoint entryPoint,
   5135                        UniformLocation location,
   5136                        GLsizei count,
   5137                        const GLint *v)
   5138 {
   5139    return ValidateUniform(context, entryPoint, GL_INT_VEC4, location, count);
   5140 }
   5141 
   5142 bool ValidateUniformMatrix2fv(const Context *context,
   5143                              angle::EntryPoint entryPoint,
   5144                              UniformLocation location,
   5145                              GLsizei count,
   5146                              GLboolean transpose,
   5147                              const GLfloat *value)
   5148 {
   5149    return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT2, location, count, transpose);
   5150 }
   5151 
   5152 bool ValidateUniformMatrix3fv(const Context *context,
   5153                              angle::EntryPoint entryPoint,
   5154                              UniformLocation location,
   5155                              GLsizei count,
   5156                              GLboolean transpose,
   5157                              const GLfloat *value)
   5158 {
   5159    return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT3, location, count, transpose);
   5160 }
   5161 
   5162 bool ValidateUniformMatrix4fv(const Context *context,
   5163                              angle::EntryPoint entryPoint,
   5164                              UniformLocation location,
   5165                              GLsizei count,
   5166                              GLboolean transpose,
   5167                              const GLfloat *value)
   5168 {
   5169    return ValidateUniformMatrix(context, entryPoint, GL_FLOAT_MAT4, location, count, transpose);
   5170 }
   5171 
   5172 bool ValidateValidateProgram(const Context *context,
   5173                             angle::EntryPoint entryPoint,
   5174                             ShaderProgramID program)
   5175 {
   5176    Program *programObject = GetValidProgram(context, entryPoint, program);
   5177 
   5178    if (!programObject)
   5179    {
   5180        return false;
   5181    }
   5182 
   5183    return true;
   5184 }
   5185 
   5186 bool ValidateVertexAttrib1f(const Context *context,
   5187                            angle::EntryPoint entryPoint,
   5188                            GLuint index,
   5189                            GLfloat x)
   5190 {
   5191    return ValidateVertexAttribIndex(context, entryPoint, index);
   5192 }
   5193 
   5194 bool ValidateVertexAttrib1fv(const Context *context,
   5195                             angle::EntryPoint entryPoint,
   5196                             GLuint index,
   5197                             const GLfloat *values)
   5198 {
   5199    return ValidateVertexAttribIndex(context, entryPoint, index);
   5200 }
   5201 
   5202 bool ValidateVertexAttrib2f(const Context *context,
   5203                            angle::EntryPoint entryPoint,
   5204                            GLuint index,
   5205                            GLfloat x,
   5206                            GLfloat y)
   5207 {
   5208    return ValidateVertexAttribIndex(context, entryPoint, index);
   5209 }
   5210 
   5211 bool ValidateVertexAttrib2fv(const Context *context,
   5212                             angle::EntryPoint entryPoint,
   5213                             GLuint index,
   5214                             const GLfloat *values)
   5215 {
   5216    return ValidateVertexAttribIndex(context, entryPoint, index);
   5217 }
   5218 
   5219 bool ValidateVertexAttrib3f(const Context *context,
   5220                            angle::EntryPoint entryPoint,
   5221                            GLuint index,
   5222                            GLfloat x,
   5223                            GLfloat y,
   5224                            GLfloat z)
   5225 {
   5226    return ValidateVertexAttribIndex(context, entryPoint, index);
   5227 }
   5228 
   5229 bool ValidateVertexAttrib3fv(const Context *context,
   5230                             angle::EntryPoint entryPoint,
   5231                             GLuint index,
   5232                             const GLfloat *values)
   5233 {
   5234    return ValidateVertexAttribIndex(context, entryPoint, index);
   5235 }
   5236 
   5237 bool ValidateVertexAttrib4f(const Context *context,
   5238                            angle::EntryPoint entryPoint,
   5239                            GLuint index,
   5240                            GLfloat x,
   5241                            GLfloat y,
   5242                            GLfloat z,
   5243                            GLfloat w)
   5244 {
   5245    return ValidateVertexAttribIndex(context, entryPoint, index);
   5246 }
   5247 
   5248 bool ValidateVertexAttrib4fv(const Context *context,
   5249                             angle::EntryPoint entryPoint,
   5250                             GLuint index,
   5251                             const GLfloat *values)
   5252 {
   5253    return ValidateVertexAttribIndex(context, entryPoint, index);
   5254 }
   5255 
   5256 bool ValidateViewport(const Context *context,
   5257                      angle::EntryPoint entryPoint,
   5258                      GLint x,
   5259                      GLint y,
   5260                      GLsizei width,
   5261                      GLsizei height)
   5262 {
   5263    if (width < 0 || height < 0)
   5264    {
   5265        context->validationError(entryPoint, GL_INVALID_VALUE, kViewportNegativeSize);
   5266        return false;
   5267    }
   5268 
   5269    return true;
   5270 }
   5271 
   5272 bool ValidateGetFramebufferAttachmentParameteriv(const Context *context,
   5273                                                 angle::EntryPoint entryPoint,
   5274                                                 GLenum target,
   5275                                                 GLenum attachment,
   5276                                                 GLenum pname,
   5277                                                 const GLint *params)
   5278 {
   5279    return ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
   5280                                                           pname, nullptr);
   5281 }
   5282 
   5283 bool ValidateGetProgramiv(const Context *context,
   5284                          angle::EntryPoint entryPoint,
   5285                          ShaderProgramID program,
   5286                          GLenum pname,
   5287                          const GLint *params)
   5288 {
   5289    return ValidateGetProgramivBase(context, entryPoint, program, pname, nullptr);
   5290 }
   5291 
   5292 bool ValidateCopyTexImage2D(const Context *context,
   5293                            angle::EntryPoint entryPoint,
   5294                            TextureTarget target,
   5295                            GLint level,
   5296                            GLenum internalformat,
   5297                            GLint x,
   5298                            GLint y,
   5299                            GLsizei width,
   5300                            GLsizei height,
   5301                            GLint border)
   5302 {
   5303    if (context->getClientMajorVersion() < 3)
   5304    {
   5305        return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, internalformat,
   5306                                                 false, 0, 0, x, y, width, height, border);
   5307    }
   5308 
   5309    ASSERT(context->getClientMajorVersion() == 3);
   5310    return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, internalformat,
   5311                                               false, 0, 0, 0, x, y, width, height, border);
   5312 }
   5313 
   5314 bool ValidateCopyTexSubImage2D(const Context *context,
   5315                               angle::EntryPoint entryPoint,
   5316                               TextureTarget target,
   5317                               GLint level,
   5318                               GLint xoffset,
   5319                               GLint yoffset,
   5320                               GLint x,
   5321                               GLint y,
   5322                               GLsizei width,
   5323                               GLsizei height)
   5324 {
   5325    if (context->getClientMajorVersion() < 3)
   5326    {
   5327        return ValidateES2CopyTexImageParameters(context, entryPoint, target, level, GL_NONE, true,
   5328                                                 xoffset, yoffset, x, y, width, height, 0);
   5329    }
   5330 
   5331    return ValidateES3CopyTexImage2DParameters(context, entryPoint, target, level, GL_NONE, true,
   5332                                               xoffset, yoffset, 0, x, y, width, height, 0);
   5333 }
   5334 
   5335 bool ValidateCopyTexSubImage3DOES(const Context *context,
   5336                                  angle::EntryPoint entryPoint,
   5337                                  TextureTarget target,
   5338                                  GLint level,
   5339                                  GLint xoffset,
   5340                                  GLint yoffset,
   5341                                  GLint zoffset,
   5342                                  GLint x,
   5343                                  GLint y,
   5344                                  GLsizei width,
   5345                                  GLsizei height)
   5346 {
   5347    return ValidateCopyTexSubImage3D(context, entryPoint, target, level, xoffset, yoffset, zoffset,
   5348                                     x, y, width, height);
   5349 }
   5350 
   5351 bool ValidateDeleteBuffers(const Context *context,
   5352                           angle::EntryPoint entryPoint,
   5353                           GLint n,
   5354                           const BufferID *buffers)
   5355 {
   5356    return ValidateGenOrDelete(context, entryPoint, n);
   5357 }
   5358 
   5359 bool ValidateDeleteFramebuffers(const Context *context,
   5360                                angle::EntryPoint entryPoint,
   5361                                GLint n,
   5362                                const FramebufferID *framebuffers)
   5363 {
   5364    return ValidateGenOrDelete(context, entryPoint, n);
   5365 }
   5366 
   5367 bool ValidateDeleteRenderbuffers(const Context *context,
   5368                                 angle::EntryPoint entryPoint,
   5369                                 GLint n,
   5370                                 const RenderbufferID *renderbuffers)
   5371 {
   5372    return ValidateGenOrDelete(context, entryPoint, n);
   5373 }
   5374 
   5375 bool ValidateDeleteTextures(const Context *context,
   5376                            angle::EntryPoint entryPoint,
   5377                            GLint n,
   5378                            const TextureID *textures)
   5379 {
   5380    return ValidateGenOrDelete(context, entryPoint, n);
   5381 }
   5382 
   5383 bool ValidateDisable(const Context *context, angle::EntryPoint entryPoint, GLenum cap)
   5384 {
   5385    if (!ValidCap(context, cap, false))
   5386    {
   5387        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
   5388        return false;
   5389    }
   5390 
   5391    return true;
   5392 }
   5393 
   5394 bool ValidateEnable(const Context *context, angle::EntryPoint entryPoint, GLenum cap)
   5395 {
   5396    if (!ValidCap(context, cap, false))
   5397    {
   5398        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
   5399        return false;
   5400    }
   5401 
   5402    if (context->getLimitations().noSampleAlphaToCoverageSupport &&
   5403        cap == GL_SAMPLE_ALPHA_TO_COVERAGE)
   5404    {
   5405        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5406                                 kNoSampleAlphaToCoveragesLimitation);
   5407 
   5408        // We also output an error message to the debugger window if tracing is active, so that
   5409        // developers can see the error message.
   5410        ERR() << kNoSampleAlphaToCoveragesLimitation;
   5411        return false;
   5412    }
   5413 
   5414    return true;
   5415 }
   5416 
   5417 bool ValidateFramebufferRenderbuffer(const Context *context,
   5418                                     angle::EntryPoint entryPoint,
   5419                                     GLenum target,
   5420                                     GLenum attachment,
   5421                                     GLenum renderbuffertarget,
   5422                                     RenderbufferID renderbuffer)
   5423 {
   5424    return ValidateFramebufferRenderbufferBase(context, entryPoint, target, attachment,
   5425                                               renderbuffertarget, renderbuffer);
   5426 }
   5427 
   5428 bool ValidateFramebufferTexture2D(const Context *context,
   5429                                  angle::EntryPoint entryPoint,
   5430                                  GLenum target,
   5431                                  GLenum attachment,
   5432                                  TextureTarget textarget,
   5433                                  TextureID texture,
   5434                                  GLint level)
   5435 {
   5436    // Attachments are required to be bound to level 0 without ES3 or the GL_OES_fbo_render_mipmap
   5437    // extension
   5438    if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
   5439        level != 0)
   5440    {
   5441        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
   5442        return false;
   5443    }
   5444 
   5445    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
   5446    {
   5447        return false;
   5448    }
   5449 
   5450    if (texture.value != 0)
   5451    {
   5452        Texture *tex = context->getTexture(texture);
   5453        ASSERT(tex);
   5454 
   5455        const Caps &caps = context->getCaps();
   5456 
   5457        switch (textarget)
   5458        {
   5459            case TextureTarget::_2D:
   5460            {
   5461                if (level > log2(caps.max2DTextureSize))
   5462                {
   5463                    context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   5464                    return false;
   5465                }
   5466                if (tex->getType() != TextureType::_2D)
   5467                {
   5468                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5469                                             kInvalidTextureTarget);
   5470                    return false;
   5471                }
   5472            }
   5473            break;
   5474 
   5475            case TextureTarget::Rectangle:
   5476            {
   5477                if (level != 0)
   5478                {
   5479                    context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   5480                    return false;
   5481                }
   5482                if (tex->getType() != TextureType::Rectangle)
   5483                {
   5484                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5485                                             kTextureTargetMismatch);
   5486                    return false;
   5487                }
   5488            }
   5489            break;
   5490 
   5491            case TextureTarget::CubeMapNegativeX:
   5492            case TextureTarget::CubeMapNegativeY:
   5493            case TextureTarget::CubeMapNegativeZ:
   5494            case TextureTarget::CubeMapPositiveX:
   5495            case TextureTarget::CubeMapPositiveY:
   5496            case TextureTarget::CubeMapPositiveZ:
   5497            {
   5498                if (level > log2(caps.maxCubeMapTextureSize))
   5499                {
   5500                    context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   5501                    return false;
   5502                }
   5503                if (tex->getType() != TextureType::CubeMap)
   5504                {
   5505                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5506                                             kTextureTargetMismatch);
   5507                    return false;
   5508                }
   5509            }
   5510            break;
   5511 
   5512            case TextureTarget::_2DMultisample:
   5513            {
   5514                if (context->getClientVersion() < ES_3_1 &&
   5515                    !context->getExtensions().textureMultisampleANGLE)
   5516                {
   5517                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5518                                             kMultisampleTextureExtensionOrES31Required);
   5519                    return false;
   5520                }
   5521 
   5522                if (level != 0)
   5523                {
   5524                    context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero);
   5525                    return false;
   5526                }
   5527                if (tex->getType() != TextureType::_2DMultisample)
   5528                {
   5529                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5530                                             kTextureTargetMismatch);
   5531                    return false;
   5532                }
   5533            }
   5534            break;
   5535 
   5536            case TextureTarget::External:
   5537            {
   5538                if (!context->getExtensions().YUVTargetEXT)
   5539                {
   5540                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5541                                             kYUVTargetExtensionRequired);
   5542                    return false;
   5543                }
   5544 
   5545                if (attachment != GL_COLOR_ATTACHMENT0)
   5546                {
   5547                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
   5548                    return false;
   5549                }
   5550 
   5551                if (tex->getType() != TextureType::External)
   5552                {
   5553                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5554                                             kTextureTargetMismatch);
   5555                    return false;
   5556                }
   5557            }
   5558            break;
   5559 
   5560            default:
   5561                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   5562                return false;
   5563        }
   5564    }
   5565 
   5566    return true;
   5567 }
   5568 
   5569 bool ValidateFramebufferTexture3DOES(const Context *context,
   5570                                     angle::EntryPoint entryPoint,
   5571                                     GLenum target,
   5572                                     GLenum attachment,
   5573                                     TextureTarget textargetPacked,
   5574                                     TextureID texture,
   5575                                     GLint level,
   5576                                     GLint zoffset)
   5577 {
   5578    // We don't call into a base ValidateFramebufferTexture3D here because
   5579    // it doesn't exist for OpenGL ES. This function is replaced by
   5580    // FramebufferTextureLayer in ES 3.x, which has broader support.
   5581    if (!context->getExtensions().texture3DOES)
   5582    {
   5583        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   5584        return false;
   5585    }
   5586 
   5587    // Attachments are required to be bound to level 0 without ES3 or the
   5588    // GL_OES_fbo_render_mipmap extension
   5589    if (context->getClientMajorVersion() < 3 && !context->getExtensions().fboRenderMipmapOES &&
   5590        level != 0)
   5591    {
   5592        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferTextureLevel);
   5593        return false;
   5594    }
   5595 
   5596    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
   5597    {
   5598        return false;
   5599    }
   5600 
   5601    if (texture.value != 0)
   5602    {
   5603        Texture *tex = context->getTexture(texture);
   5604        ASSERT(tex);
   5605 
   5606        const Caps &caps = context->getCaps();
   5607 
   5608        switch (textargetPacked)
   5609        {
   5610            case TextureTarget::_3D:
   5611            {
   5612                if (level > log2(caps.max3DTextureSize))
   5613                {
   5614                    context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   5615                    return false;
   5616                }
   5617                if (zoffset >= caps.max3DTextureSize)
   5618                {
   5619                    context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidZOffset);
   5620                    return false;
   5621                }
   5622                if (tex->getType() != TextureType::_3D)
   5623                {
   5624                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureType);
   5625                    return false;
   5626                }
   5627            }
   5628            break;
   5629 
   5630            default:
   5631                context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget);
   5632                return false;
   5633        }
   5634    }
   5635 
   5636    return true;
   5637 }
   5638 
   5639 bool ValidateGenBuffers(const Context *context,
   5640                        angle::EntryPoint entryPoint,
   5641                        GLint n,
   5642                        const BufferID *buffers)
   5643 {
   5644    return ValidateGenOrDelete(context, entryPoint, n);
   5645 }
   5646 
   5647 bool ValidateGenFramebuffers(const Context *context,
   5648                             angle::EntryPoint entryPoint,
   5649                             GLint n,
   5650                             const FramebufferID *framebuffers)
   5651 {
   5652    return ValidateGenOrDelete(context, entryPoint, n);
   5653 }
   5654 
   5655 bool ValidateGenRenderbuffers(const Context *context,
   5656                              angle::EntryPoint entryPoint,
   5657                              GLint n,
   5658                              const RenderbufferID *renderbuffers)
   5659 {
   5660    return ValidateGenOrDelete(context, entryPoint, n);
   5661 }
   5662 
   5663 bool ValidateGenTextures(const Context *context,
   5664                         angle::EntryPoint entryPoint,
   5665                         GLint n,
   5666                         const TextureID *textures)
   5667 {
   5668    return ValidateGenOrDelete(context, entryPoint, n);
   5669 }
   5670 
   5671 bool ValidateGenerateMipmap(const Context *context,
   5672                            angle::EntryPoint entryPoint,
   5673                            TextureType target)
   5674 {
   5675    return ValidateGenerateMipmapBase(context, entryPoint, target);
   5676 }
   5677 
   5678 bool ValidateGetBufferParameteriv(const Context *context,
   5679                                  angle::EntryPoint entryPoint,
   5680                                  BufferBinding target,
   5681                                  GLenum pname,
   5682                                  const GLint *params)
   5683 {
   5684    return ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, nullptr);
   5685 }
   5686 
   5687 bool ValidateGetRenderbufferParameteriv(const Context *context,
   5688                                        angle::EntryPoint entryPoint,
   5689                                        GLenum target,
   5690                                        GLenum pname,
   5691                                        const GLint *params)
   5692 {
   5693    return ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, nullptr);
   5694 }
   5695 
   5696 bool ValidateGetShaderiv(const Context *context,
   5697                         angle::EntryPoint entryPoint,
   5698                         ShaderProgramID shader,
   5699                         GLenum pname,
   5700                         const GLint *params)
   5701 {
   5702    return ValidateGetShaderivBase(context, entryPoint, shader, pname, nullptr);
   5703 }
   5704 
   5705 bool ValidateGetTexParameterfv(const Context *context,
   5706                               angle::EntryPoint entryPoint,
   5707                               TextureType target,
   5708                               GLenum pname,
   5709                               const GLfloat *params)
   5710 {
   5711    return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
   5712 }
   5713 
   5714 bool ValidateGetTexParameteriv(const Context *context,
   5715                               angle::EntryPoint entryPoint,
   5716                               TextureType target,
   5717                               GLenum pname,
   5718                               const GLint *params)
   5719 {
   5720    return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
   5721 }
   5722 
   5723 bool ValidateGetTexParameterIivOES(const Context *context,
   5724                                   angle::EntryPoint entryPoint,
   5725                                   TextureType target,
   5726                                   GLenum pname,
   5727                                   const GLint *params)
   5728 {
   5729    if (context->getClientMajorVersion() < 3)
   5730    {
   5731        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5732        return false;
   5733    }
   5734    return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
   5735 }
   5736 
   5737 bool ValidateGetTexParameterIuivOES(const Context *context,
   5738                                    angle::EntryPoint entryPoint,
   5739                                    TextureType target,
   5740                                    GLenum pname,
   5741                                    const GLuint *params)
   5742 {
   5743    if (context->getClientMajorVersion() < 3)
   5744    {
   5745        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5746        return false;
   5747    }
   5748    return ValidateGetTexParameterBase(context, entryPoint, target, pname, nullptr);
   5749 }
   5750 
   5751 bool ValidateGetUniformfv(const Context *context,
   5752                          angle::EntryPoint entryPoint,
   5753                          ShaderProgramID program,
   5754                          UniformLocation location,
   5755                          const GLfloat *params)
   5756 {
   5757    return ValidateGetUniformBase(context, entryPoint, program, location);
   5758 }
   5759 
   5760 bool ValidateGetUniformiv(const Context *context,
   5761                          angle::EntryPoint entryPoint,
   5762                          ShaderProgramID program,
   5763                          UniformLocation location,
   5764                          const GLint *params)
   5765 {
   5766    return ValidateGetUniformBase(context, entryPoint, program, location);
   5767 }
   5768 
   5769 bool ValidateGetVertexAttribfv(const Context *context,
   5770                               angle::EntryPoint entryPoint,
   5771                               GLuint index,
   5772                               GLenum pname,
   5773                               const GLfloat *params)
   5774 {
   5775    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false);
   5776 }
   5777 
   5778 bool ValidateGetVertexAttribiv(const Context *context,
   5779                               angle::EntryPoint entryPoint,
   5780                               GLuint index,
   5781                               GLenum pname,
   5782                               const GLint *params)
   5783 {
   5784    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, false, false);
   5785 }
   5786 
   5787 bool ValidateGetVertexAttribPointerv(const Context *context,
   5788                                     angle::EntryPoint entryPoint,
   5789                                     GLuint index,
   5790                                     GLenum pname,
   5791                                     void *const *pointer)
   5792 {
   5793    return ValidateGetVertexAttribBase(context, entryPoint, index, pname, nullptr, true, false);
   5794 }
   5795 
   5796 bool ValidateIsEnabled(const Context *context, angle::EntryPoint entryPoint, GLenum cap)
   5797 {
   5798    if (!ValidCap(context, cap, true))
   5799    {
   5800        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, cap);
   5801        return false;
   5802    }
   5803 
   5804    return true;
   5805 }
   5806 
   5807 bool ValidateLinkProgram(const Context *context,
   5808                         angle::EntryPoint entryPoint,
   5809                         ShaderProgramID program)
   5810 {
   5811    if (context->hasActiveTransformFeedback(program))
   5812    {
   5813        // ES 3.0.4 section 2.15 page 91
   5814        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5815                                 kTransformFeedbackActiveDuringLink);
   5816        return false;
   5817    }
   5818 
   5819    Program *programObject = GetValidProgram(context, entryPoint, program);
   5820    if (!programObject)
   5821    {
   5822        return false;
   5823    }
   5824 
   5825    return true;
   5826 }
   5827 
   5828 bool ValidateReadPixels(const Context *context,
   5829                        angle::EntryPoint entryPoint,
   5830                        GLint x,
   5831                        GLint y,
   5832                        GLsizei width,
   5833                        GLsizei height,
   5834                        GLenum format,
   5835                        GLenum type,
   5836                        const void *pixels)
   5837 {
   5838    return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, -1,
   5839                                  nullptr, nullptr, nullptr, pixels);
   5840 }
   5841 
   5842 bool ValidateTexParameterf(const Context *context,
   5843                           angle::EntryPoint entryPoint,
   5844                           TextureType target,
   5845                           GLenum pname,
   5846                           GLfloat param)
   5847 {
   5848    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, &param);
   5849 }
   5850 
   5851 bool ValidateTexParameterfv(const Context *context,
   5852                            angle::EntryPoint entryPoint,
   5853                            TextureType target,
   5854                            GLenum pname,
   5855                            const GLfloat *params)
   5856 {
   5857    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
   5858 }
   5859 
   5860 bool ValidateTexParameteri(const Context *context,
   5861                           angle::EntryPoint entryPoint,
   5862                           TextureType target,
   5863                           GLenum pname,
   5864                           GLint param)
   5865 {
   5866    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, false, &param);
   5867 }
   5868 
   5869 bool ValidateTexParameteriv(const Context *context,
   5870                            angle::EntryPoint entryPoint,
   5871                            TextureType target,
   5872                            GLenum pname,
   5873                            const GLint *params)
   5874 {
   5875    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
   5876 }
   5877 
   5878 bool ValidateTexParameterIivOES(const Context *context,
   5879                                angle::EntryPoint entryPoint,
   5880                                TextureType target,
   5881                                GLenum pname,
   5882                                const GLint *params)
   5883 {
   5884    if (context->getClientMajorVersion() < 3)
   5885    {
   5886        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5887        return false;
   5888    }
   5889    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
   5890 }
   5891 
   5892 bool ValidateTexParameterIuivOES(const Context *context,
   5893                                 angle::EntryPoint entryPoint,
   5894                                 TextureType target,
   5895                                 GLenum pname,
   5896                                 const GLuint *params)
   5897 {
   5898    if (context->getClientMajorVersion() < 3)
   5899    {
   5900        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   5901        return false;
   5902    }
   5903    return ValidateTexParameterBase(context, entryPoint, target, pname, -1, true, params);
   5904 }
   5905 
   5906 bool ValidateUseProgram(const Context *context,
   5907                        angle::EntryPoint entryPoint,
   5908                        ShaderProgramID program)
   5909 {
   5910    if (program.value != 0)
   5911    {
   5912        Program *programObject = context->getProgramResolveLink(program);
   5913        if (!programObject)
   5914        {
   5915            // ES 3.1.0 section 7.3 page 72
   5916            if (context->getShader(program))
   5917            {
   5918                context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
   5919                return false;
   5920            }
   5921            else
   5922            {
   5923                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
   5924                return false;
   5925            }
   5926        }
   5927        if (!programObject->isLinked())
   5928        {
   5929            context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   5930            return false;
   5931        }
   5932    }
   5933    if (context->getState().isTransformFeedbackActiveUnpaused())
   5934    {
   5935        // ES 3.0.4 section 2.15 page 91
   5936        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackUseProgram);
   5937        return false;
   5938    }
   5939 
   5940    return true;
   5941 }
   5942 
   5943 bool ValidateDeleteFencesNV(const Context *context,
   5944                            angle::EntryPoint entryPoint,
   5945                            GLsizei n,
   5946                            const FenceNVID *fences)
   5947 {
   5948    if (!context->getExtensions().fenceNV)
   5949    {
   5950        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   5951        return false;
   5952    }
   5953 
   5954    if (n < 0)
   5955    {
   5956        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   5957        return false;
   5958    }
   5959 
   5960    return true;
   5961 }
   5962 
   5963 bool ValidateFinishFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
   5964 {
   5965    if (!context->getExtensions().fenceNV)
   5966    {
   5967        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   5968        return false;
   5969    }
   5970 
   5971    FenceNV *fenceObject = context->getFenceNV(fence);
   5972 
   5973    if (fenceObject == nullptr)
   5974    {
   5975        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
   5976        return false;
   5977    }
   5978 
   5979    if (!fenceObject->isSet())
   5980    {
   5981        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState);
   5982        return false;
   5983    }
   5984 
   5985    return true;
   5986 }
   5987 
   5988 bool ValidateGenFencesNV(const Context *context,
   5989                         angle::EntryPoint entryPoint,
   5990                         GLsizei n,
   5991                         const FenceNVID *fences)
   5992 {
   5993    if (!context->getExtensions().fenceNV)
   5994    {
   5995        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   5996        return false;
   5997    }
   5998 
   5999    if (n < 0)
   6000    {
   6001        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   6002        return false;
   6003    }
   6004 
   6005    return true;
   6006 }
   6007 
   6008 bool ValidateGetFenceivNV(const Context *context,
   6009                          angle::EntryPoint entryPoint,
   6010                          FenceNVID fence,
   6011                          GLenum pname,
   6012                          const GLint *params)
   6013 {
   6014    if (!context->getExtensions().fenceNV)
   6015    {
   6016        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   6017        return false;
   6018    }
   6019 
   6020    FenceNV *fenceObject = context->getFenceNV(fence);
   6021 
   6022    if (fenceObject == nullptr)
   6023    {
   6024        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
   6025        return false;
   6026    }
   6027 
   6028    if (!fenceObject->isSet())
   6029    {
   6030        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState);
   6031        return false;
   6032    }
   6033 
   6034    switch (pname)
   6035    {
   6036        case GL_FENCE_STATUS_NV:
   6037        case GL_FENCE_CONDITION_NV:
   6038            break;
   6039 
   6040        default:
   6041            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   6042            return false;
   6043    }
   6044 
   6045    return true;
   6046 }
   6047 
   6048 bool ValidateGetGraphicsResetStatusEXT(const Context *context, angle::EntryPoint entryPoint)
   6049 {
   6050    if (!context->getExtensions().robustnessEXT)
   6051    {
   6052        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6053        return false;
   6054    }
   6055 
   6056    return true;
   6057 }
   6058 
   6059 bool ValidateGetTranslatedShaderSourceANGLE(const Context *context,
   6060                                            angle::EntryPoint entryPoint,
   6061                                            ShaderProgramID shader,
   6062                                            GLsizei bufsize,
   6063                                            const GLsizei *length,
   6064                                            const GLchar *source)
   6065 {
   6066    if (!context->getExtensions().translatedShaderSourceANGLE)
   6067    {
   6068        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6069        return false;
   6070    }
   6071 
   6072    if (bufsize < 0)
   6073    {
   6074        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   6075        return false;
   6076    }
   6077 
   6078    Shader *shaderObject = context->getShader(shader);
   6079 
   6080    if (!shaderObject)
   6081    {
   6082        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidShaderName);
   6083        return false;
   6084    }
   6085 
   6086    return true;
   6087 }
   6088 
   6089 bool ValidateIsFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
   6090 {
   6091    if (!context->getExtensions().fenceNV)
   6092    {
   6093        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   6094        return false;
   6095    }
   6096 
   6097    return true;
   6098 }
   6099 
   6100 bool ValidateSetFenceNV(const Context *context,
   6101                        angle::EntryPoint entryPoint,
   6102                        FenceNVID fence,
   6103                        GLenum condition)
   6104 {
   6105    if (!context->getExtensions().fenceNV)
   6106    {
   6107        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   6108        return false;
   6109    }
   6110 
   6111    if (condition != GL_ALL_COMPLETED_NV)
   6112    {
   6113        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFenceCondition);
   6114        return false;
   6115    }
   6116 
   6117    FenceNV *fenceObject = context->getFenceNV(fence);
   6118 
   6119    if (fenceObject == nullptr)
   6120    {
   6121        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
   6122        return false;
   6123    }
   6124 
   6125    return true;
   6126 }
   6127 
   6128 bool ValidateTestFenceNV(const Context *context, angle::EntryPoint entryPoint, FenceNVID fence)
   6129 {
   6130    if (!context->getExtensions().fenceNV)
   6131    {
   6132        context->validationError(entryPoint, GL_INVALID_OPERATION, kNVFenceNotSupported);
   6133        return false;
   6134    }
   6135 
   6136    FenceNV *fenceObject = context->getFenceNV(fence);
   6137 
   6138    if (fenceObject == nullptr)
   6139    {
   6140        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFence);
   6141        return false;
   6142    }
   6143 
   6144    if (fenceObject->isSet() != GL_TRUE)
   6145    {
   6146        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFenceState);
   6147        return false;
   6148    }
   6149 
   6150    return true;
   6151 }
   6152 
   6153 bool ValidateTexStorage2DEXT(const Context *context,
   6154                             angle::EntryPoint entryPoint,
   6155                             TextureType type,
   6156                             GLsizei levels,
   6157                             GLenum internalformat,
   6158                             GLsizei width,
   6159                             GLsizei height)
   6160 {
   6161    if (!context->getExtensions().textureStorageEXT)
   6162    {
   6163        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6164        return false;
   6165    }
   6166 
   6167    if (context->getClientMajorVersion() < 3)
   6168    {
   6169        return ValidateES2TexStorageParametersBase(context, entryPoint, type, levels,
   6170                                                   internalformat, width, height);
   6171    }
   6172 
   6173    ASSERT(context->getClientMajorVersion() >= 3);
   6174    return ValidateES3TexStorage2DParameters(context, entryPoint, type, levels, internalformat,
   6175                                             width, height, 1);
   6176 }
   6177 
   6178 bool ValidateVertexAttribDivisorANGLE(const Context *context,
   6179                                      angle::EntryPoint entryPoint,
   6180                                      GLuint index,
   6181                                      GLuint divisor)
   6182 {
   6183    if (!context->getExtensions().instancedArraysANGLE)
   6184    {
   6185        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6186        return false;
   6187    }
   6188 
   6189    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
   6190    {
   6191        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   6192        return false;
   6193    }
   6194 
   6195    if (context->getLimitations().attributeZeroRequiresZeroDivisorInEXT)
   6196    {
   6197        if (index == 0 && divisor != 0)
   6198        {
   6199            context->validationError(entryPoint, GL_INVALID_OPERATION,
   6200                                     kAttributeZeroRequiresDivisorLimitation);
   6201 
   6202            // We also output an error message to the debugger window if tracing is active, so
   6203            // that developers can see the error message.
   6204            ERR() << kAttributeZeroRequiresDivisorLimitation;
   6205            return false;
   6206        }
   6207    }
   6208 
   6209    return true;
   6210 }
   6211 
   6212 bool ValidateVertexAttribDivisorEXT(const Context *context,
   6213                                    angle::EntryPoint entryPoint,
   6214                                    GLuint index,
   6215                                    GLuint divisor)
   6216 {
   6217    if (!context->getExtensions().instancedArraysEXT)
   6218    {
   6219        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6220        return false;
   6221    }
   6222 
   6223    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
   6224    {
   6225        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   6226        return false;
   6227    }
   6228 
   6229    return true;
   6230 }
   6231 
   6232 bool ValidateTexImage3DOES(const Context *context,
   6233                           angle::EntryPoint entryPoint,
   6234                           TextureTarget target,
   6235                           GLint level,
   6236                           GLenum internalformat,
   6237                           GLsizei width,
   6238                           GLsizei height,
   6239                           GLsizei depth,
   6240                           GLint border,
   6241                           GLenum format,
   6242                           GLenum type,
   6243                           const void *pixels)
   6244 {
   6245    return ValidateTexImage3D(context, entryPoint, target, level, internalformat, width, height,
   6246                              depth, border, format, type, pixels);
   6247 }
   6248 
   6249 bool ValidatePopGroupMarkerEXT(const Context *context, angle::EntryPoint entryPoint)
   6250 {
   6251    if (!context->getExtensions().debugMarkerEXT)
   6252    {
   6253        // The debug marker calls should not set error state
   6254        // However, it seems reasonable to set an error state if the extension is not enabled
   6255        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6256        return false;
   6257    }
   6258 
   6259    return true;
   6260 }
   6261 
   6262 bool ValidateTexStorage1DEXT(const Context *context,
   6263                             angle::EntryPoint entryPoint,
   6264                             GLenum target,
   6265                             GLsizei levels,
   6266                             GLenum internalformat,
   6267                             GLsizei width)
   6268 {
   6269    UNIMPLEMENTED();
   6270    context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6271    return false;
   6272 }
   6273 
   6274 bool ValidateTexStorage3DEXT(const Context *context,
   6275                             angle::EntryPoint entryPoint,
   6276                             TextureType target,
   6277                             GLsizei levels,
   6278                             GLenum internalformat,
   6279                             GLsizei width,
   6280                             GLsizei height,
   6281                             GLsizei depth)
   6282 {
   6283    if (!context->getExtensions().textureStorageEXT)
   6284    {
   6285        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6286        return false;
   6287    }
   6288 
   6289    if (context->getClientMajorVersion() < 3)
   6290    {
   6291        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6292        return false;
   6293    }
   6294 
   6295    return ValidateES3TexStorage3DParameters(context, entryPoint, target, levels, internalformat,
   6296                                             width, height, depth);
   6297 }
   6298 
   6299 bool ValidateMaxShaderCompilerThreadsKHR(const Context *context,
   6300                                         angle::EntryPoint entryPoint,
   6301                                         GLuint count)
   6302 {
   6303    if (!context->getExtensions().parallelShaderCompileKHR)
   6304    {
   6305        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6306        return false;
   6307    }
   6308    return true;
   6309 }
   6310 
   6311 bool ValidateMultiDrawArraysANGLE(const Context *context,
   6312                                  angle::EntryPoint entryPoint,
   6313                                  PrimitiveMode mode,
   6314                                  const GLint *firsts,
   6315                                  const GLsizei *counts,
   6316                                  GLsizei drawcount)
   6317 {
   6318    if (!context->getExtensions().multiDrawANGLE)
   6319    {
   6320        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6321        return false;
   6322    }
   6323    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
   6324    {
   6325        if (!ValidateDrawArrays(context, entryPoint, mode, firsts[drawID], counts[drawID]))
   6326        {
   6327            return false;
   6328        }
   6329    }
   6330    return true;
   6331 }
   6332 
   6333 bool ValidateMultiDrawElementsANGLE(const Context *context,
   6334                                    angle::EntryPoint entryPoint,
   6335                                    PrimitiveMode mode,
   6336                                    const GLsizei *counts,
   6337                                    DrawElementsType type,
   6338                                    const GLvoid *const *indices,
   6339                                    GLsizei drawcount)
   6340 {
   6341    if (!context->getExtensions().multiDrawANGLE)
   6342    {
   6343        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6344        return false;
   6345    }
   6346    for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
   6347    {
   6348        if (!ValidateDrawElements(context, entryPoint, mode, counts[drawID], type, indices[drawID]))
   6349        {
   6350            return false;
   6351        }
   6352    }
   6353    return true;
   6354 }
   6355 
   6356 bool ValidateProvokingVertexANGLE(const Context *context,
   6357                                  angle::EntryPoint entryPoint,
   6358                                  ProvokingVertexConvention modePacked)
   6359 {
   6360    if (!context->getExtensions().provokingVertexANGLE)
   6361    {
   6362        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6363        return false;
   6364    }
   6365 
   6366    switch (modePacked)
   6367    {
   6368        case ProvokingVertexConvention::FirstVertexConvention:
   6369        case ProvokingVertexConvention::LastVertexConvention:
   6370            break;
   6371        default:
   6372            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProvokingVertex);
   6373            return false;
   6374    }
   6375 
   6376    return true;
   6377 }
   6378 
   6379 bool ValidateFramebufferTexture2DMultisampleEXT(const Context *context,
   6380                                                angle::EntryPoint entryPoint,
   6381                                                GLenum target,
   6382                                                GLenum attachment,
   6383                                                TextureTarget textarget,
   6384                                                TextureID texture,
   6385                                                GLint level,
   6386                                                GLsizei samples)
   6387 {
   6388    if (!context->getExtensions().multisampledRenderToTextureEXT)
   6389    {
   6390        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6391        return false;
   6392    }
   6393 
   6394    if (samples < 0)
   6395    {
   6396        return false;
   6397    }
   6398 
   6399    // EXT_multisampled_render_to_texture states that the value of samples
   6400    // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
   6401    // otherwise GL_INVALID_VALUE is generated.
   6402    if (samples > context->getCaps().maxSamples)
   6403    {
   6404        context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange);
   6405        return false;
   6406    }
   6407 
   6408    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
   6409    {
   6410        return false;
   6411    }
   6412 
   6413    // EXT_multisampled_render_to_texture returns INVALID_OPERATION when a sample number higher than
   6414    // the maximum sample number supported by this format is passed.
   6415    // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
   6416    if (texture.value != 0 && context->getClientMajorVersion() >= 3)
   6417    {
   6418        Texture *tex                  = context->getTexture(texture);
   6419        GLenum sizedInternalFormat    = tex->getFormat(textarget, level).info->sizedInternalFormat;
   6420        const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
   6421        if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
   6422        {
   6423            context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
   6424            return false;
   6425        }
   6426    }
   6427 
   6428    // Unless EXT_multisampled_render_to_texture2 is enabled, only color attachment 0 can be used.
   6429    if (!context->getExtensions().multisampledRenderToTexture2EXT &&
   6430        attachment != GL_COLOR_ATTACHMENT0)
   6431    {
   6432        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   6433        return false;
   6434    }
   6435 
   6436    if (!ValidTexture2DDestinationTarget(context, textarget))
   6437    {
   6438        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   6439        return false;
   6440    }
   6441 
   6442    return true;
   6443 }
   6444 
   6445 bool ValidateRenderbufferStorageMultisampleEXT(const Context *context,
   6446                                               angle::EntryPoint entryPoint,
   6447                                               GLenum target,
   6448                                               GLsizei samples,
   6449                                               GLenum internalformat,
   6450                                               GLsizei width,
   6451                                               GLsizei height)
   6452 {
   6453    if (!context->getExtensions().multisampledRenderToTextureEXT)
   6454    {
   6455        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6456        return false;
   6457    }
   6458    if (!ValidateRenderbufferStorageParametersBase(context, entryPoint, target, samples,
   6459                                                   internalformat, width, height))
   6460    {
   6461        return false;
   6462    }
   6463 
   6464    // EXT_multisampled_render_to_texture states that the value of samples
   6465    // must be less than or equal to MAX_SAMPLES_EXT (Context::getCaps().maxSamples)
   6466    // otherwise GL_INVALID_VALUE is generated.
   6467    if (samples > context->getCaps().maxSamples)
   6468    {
   6469        context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesOutOfRange);
   6470        return false;
   6471    }
   6472 
   6473    // EXT_multisampled_render_to_texture returns GL_OUT_OF_MEMORY on failure to create
   6474    // the specified storage. This is different than ES 3.0 in which a sample number higher
   6475    // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
   6476    // The TextureCaps::getMaxSamples method is only guarenteed to be valid when the context is ES3.
   6477    if (context->getClientMajorVersion() >= 3)
   6478    {
   6479        const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
   6480        if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
   6481        {
   6482            context->validationError(entryPoint, GL_OUT_OF_MEMORY, kSamplesOutOfRange);
   6483            return false;
   6484        }
   6485    }
   6486 
   6487    return true;
   6488 }
   6489 
   6490 void RecordBindTextureTypeError(const Context *context,
   6491                                angle::EntryPoint entryPoint,
   6492                                TextureType target)
   6493 {
   6494    ASSERT(!context->getStateCache().isValidBindTextureType(target));
   6495 
   6496    switch (target)
   6497    {
   6498        case TextureType::Rectangle:
   6499            ASSERT(!context->getExtensions().textureRectangleANGLE);
   6500            context->validationError(entryPoint, GL_INVALID_ENUM, kTextureRectangleNotSupported);
   6501            break;
   6502 
   6503        case TextureType::_3D:
   6504        case TextureType::_2DArray:
   6505            ASSERT(context->getClientMajorVersion() < 3);
   6506            context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required);
   6507            break;
   6508 
   6509        case TextureType::_2DMultisample:
   6510            ASSERT(context->getClientVersion() < Version(3, 1) &&
   6511                   !context->getExtensions().textureMultisampleANGLE);
   6512            context->validationError(entryPoint, GL_INVALID_ENUM,
   6513                                     kMultisampleTextureExtensionOrES31Required);
   6514            break;
   6515 
   6516        case TextureType::_2DMultisampleArray:
   6517            ASSERT(!context->getExtensions().textureStorageMultisample2dArrayOES);
   6518            context->validationError(entryPoint, GL_INVALID_ENUM,
   6519                                     kMultisampleArrayExtensionRequired);
   6520            break;
   6521 
   6522        case TextureType::External:
   6523            ASSERT(!context->getExtensions().EGLImageExternalOES &&
   6524                   !context->getExtensions().EGLStreamConsumerExternalNV);
   6525            context->validationError(entryPoint, GL_INVALID_ENUM, kExternalTextureNotSupported);
   6526            break;
   6527 
   6528        case TextureType::VideoImage:
   6529            ASSERT(!context->getExtensions().videoTextureWEBGL);
   6530            context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   6531            break;
   6532 
   6533        case TextureType::Buffer:
   6534            ASSERT(!context->getExtensions().textureBufferOES &&
   6535                   !context->getExtensions().textureBufferEXT);
   6536            context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   6537            break;
   6538 
   6539        default:
   6540            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   6541    }
   6542 }
   6543 
   6544 }  // namespace gl