tor-browser

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

validationES.cpp (303237B)


      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 // validationES.h: Validation functions for generic OpenGL ES entry point parameters
      8 
      9 #include "libANGLE/validationES.h"
     10 
     11 #include "libANGLE/Context.h"
     12 #include "libANGLE/Display.h"
     13 #include "libANGLE/ErrorStrings.h"
     14 #include "libANGLE/Framebuffer.h"
     15 #include "libANGLE/FramebufferAttachment.h"
     16 #include "libANGLE/Image.h"
     17 #include "libANGLE/Program.h"
     18 #include "libANGLE/Query.h"
     19 #include "libANGLE/Texture.h"
     20 #include "libANGLE/TransformFeedback.h"
     21 #include "libANGLE/angletypes.h"
     22 #include "libANGLE/formatutils.h"
     23 #include "libANGLE/queryconversions.h"
     24 #include "libANGLE/queryutils.h"
     25 #include "libANGLE/validationES2.h"
     26 #include "libANGLE/validationES3.h"
     27 
     28 #include "common/mathutil.h"
     29 #include "common/utilities.h"
     30 
     31 using namespace angle;
     32 
     33 namespace gl
     34 {
     35 using namespace err;
     36 
     37 namespace
     38 {
     39 bool CompressedTextureFormatRequiresExactSize(GLenum internalFormat)
     40 {
     41    // List of compressed format that require that the texture size is smaller than or a multiple of
     42    // the compressed block size.
     43    switch (internalFormat)
     44    {
     45        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
     46        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
     47        case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE:
     48        case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE:
     49        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
     50        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
     51        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
     52        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
     53        case GL_ETC1_RGB8_LOSSY_DECODE_ANGLE:
     54        case GL_COMPRESSED_RGB8_LOSSY_DECODE_ETC2_ANGLE:
     55        case GL_COMPRESSED_SRGB8_LOSSY_DECODE_ETC2_ANGLE:
     56        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
     57        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_LOSSY_DECODE_ETC2_ANGLE:
     58        case GL_COMPRESSED_RGBA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
     59        case GL_COMPRESSED_SRGB8_ALPHA8_LOSSY_DECODE_ETC2_EAC_ANGLE:
     60        case GL_COMPRESSED_RED_RGTC1_EXT:
     61        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
     62        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
     63        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
     64        case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
     65        case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
     66        case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
     67        case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
     68            return true;
     69 
     70        default:
     71            return false;
     72    }
     73 }
     74 bool CompressedSubTextureFormatRequiresExactSize(GLenum internalFormat)
     75 {
     76    // Compressed sub textures have additional formats that requires exact size.
     77    // ES 3.1, Section 8.7, Page 171
     78    return CompressedTextureFormatRequiresExactSize(internalFormat) ||
     79           IsETC2EACFormat(internalFormat) || IsASTC2DFormat(internalFormat);
     80 }
     81 
     82 bool DifferenceCanOverflow(GLint a, GLint b)
     83 {
     84    CheckedNumeric<GLint> checkedA(a);
     85    checkedA -= b;
     86    // Use negation to make sure that the difference can't overflow regardless of the order.
     87    checkedA = -checkedA;
     88    return !checkedA.IsValid();
     89 }
     90 
     91 bool ValidReadPixelsTypeEnum(const Context *context, GLenum type)
     92 {
     93    switch (type)
     94    {
     95        // Types referenced in Table 3.4 of the ES 2.0.25 spec
     96        case GL_UNSIGNED_BYTE:
     97        case GL_UNSIGNED_SHORT_4_4_4_4:
     98        case GL_UNSIGNED_SHORT_5_5_5_1:
     99        case GL_UNSIGNED_SHORT_5_6_5:
    100            return context->getClientVersion() >= ES_2_0;
    101 
    102        // Types referenced in Table 3.2 of the ES 3.0.5 spec (Except depth stencil)
    103        case GL_BYTE:
    104        case GL_INT:
    105        case GL_SHORT:
    106        case GL_UNSIGNED_INT:
    107        case GL_UNSIGNED_INT_10F_11F_11F_REV:
    108        case GL_UNSIGNED_INT_2_10_10_10_REV:
    109        case GL_UNSIGNED_INT_5_9_9_9_REV:
    110        case GL_UNSIGNED_SHORT:
    111        case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
    112        case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
    113            return context->getClientVersion() >= ES_3_0;
    114 
    115        case GL_FLOAT:
    116            return context->getClientVersion() >= ES_3_0 ||
    117                   context->getExtensions().textureFloatOES ||
    118                   context->getExtensions().colorBufferHalfFloatEXT;
    119 
    120        case GL_HALF_FLOAT:
    121            return context->getClientVersion() >= ES_3_0 ||
    122                   context->getExtensions().textureHalfFloatOES;
    123 
    124        case GL_HALF_FLOAT_OES:
    125            return context->getExtensions().colorBufferHalfFloatEXT;
    126 
    127        default:
    128            return false;
    129    }
    130 }
    131 
    132 bool ValidReadPixelsFormatEnum(const Context *context, GLenum format)
    133 {
    134    switch (format)
    135    {
    136        // Formats referenced in Table 3.4 of the ES 2.0.25 spec (Except luminance)
    137        case GL_RGBA:
    138        case GL_RGB:
    139        case GL_ALPHA:
    140            return context->getClientVersion() >= ES_2_0;
    141 
    142        // Formats referenced in Table 3.2 of the ES 3.0.5 spec
    143        case GL_RG:
    144        case GL_RED:
    145        case GL_RGBA_INTEGER:
    146        case GL_RGB_INTEGER:
    147        case GL_RG_INTEGER:
    148        case GL_RED_INTEGER:
    149            return context->getClientVersion() >= ES_3_0;
    150 
    151        case GL_SRGB_ALPHA_EXT:
    152        case GL_SRGB_EXT:
    153            return context->getExtensions().sRGBEXT;
    154 
    155        case GL_BGRA_EXT:
    156            return context->getExtensions().readFormatBgraEXT;
    157 
    158        case GL_RGBX8_ANGLE:
    159            return context->getExtensions().rgbxInternalFormatANGLE;
    160 
    161        default:
    162            return false;
    163    }
    164 }
    165 
    166 bool ValidReadPixelsUnsignedNormalizedDepthType(const Context *context,
    167                                                const gl::InternalFormat *info,
    168                                                GLenum type)
    169 {
    170    bool supportsReadDepthNV = context->getExtensions().readDepthNV && (info->depthBits > 0);
    171    switch (type)
    172    {
    173        case GL_UNSIGNED_SHORT:
    174        case GL_UNSIGNED_INT:
    175        case GL_UNSIGNED_INT_24_8:
    176            return supportsReadDepthNV;
    177        default:
    178            return false;
    179    }
    180 }
    181 
    182 bool ValidReadPixelsFloatDepthType(const Context *context,
    183                                   const gl::InternalFormat *info,
    184                                   GLenum type)
    185 {
    186    return context->getExtensions().readDepthNV && (type == GL_FLOAT) &&
    187           context->getExtensions().depthBufferFloat2NV;
    188 }
    189 
    190 bool ValidReadPixelsFormatType(const Context *context,
    191                               const gl::InternalFormat *info,
    192                               GLenum format,
    193                               GLenum type)
    194 {
    195    switch (info->componentType)
    196    {
    197        case GL_UNSIGNED_NORMALIZED:
    198            // TODO(geofflang): Don't accept BGRA here.  Some chrome internals appear to try to use
    199            // ReadPixels with BGRA even if the extension is not present
    200            switch (format)
    201            {
    202                case GL_RGBA:
    203                    return ((type == GL_UNSIGNED_BYTE) && info->pixelBytes >= 1) ||
    204                           (context->getExtensions().textureNorm16EXT &&
    205                            (type == GL_UNSIGNED_SHORT) && info->pixelBytes >= 2);
    206                case GL_BGRA_EXT:
    207                    return context->getExtensions().readFormatBgraEXT && (type == GL_UNSIGNED_BYTE);
    208                case GL_STENCIL_INDEX_OES:
    209                    return context->getExtensions().readStencilNV && (type == GL_UNSIGNED_BYTE);
    210                case GL_DEPTH_COMPONENT:
    211                    return ValidReadPixelsUnsignedNormalizedDepthType(context, info, type);
    212                case GL_DEPTH_STENCIL_OES:
    213                    return context->getExtensions().readDepthStencilNV &&
    214                           (type == GL_UNSIGNED_INT_24_8_OES) && info->stencilBits > 0;
    215                case GL_RGBX8_ANGLE:
    216                    return context->getExtensions().rgbxInternalFormatANGLE &&
    217                           (type == GL_UNSIGNED_BYTE);
    218                default:
    219                    return false;
    220            }
    221        case GL_SIGNED_NORMALIZED:
    222            return (format == GL_RGBA && type == GL_BYTE && info->pixelBytes >= 1) ||
    223                   (context->getExtensions().textureNorm16EXT && format == GL_RGBA &&
    224                    type == GL_UNSIGNED_SHORT && info->pixelBytes >= 2);
    225 
    226        case GL_INT:
    227            return (format == GL_RGBA_INTEGER && type == GL_INT);
    228 
    229        case GL_UNSIGNED_INT:
    230            return (format == GL_RGBA_INTEGER && type == GL_UNSIGNED_INT);
    231 
    232        case GL_FLOAT:
    233            switch (format)
    234            {
    235                case GL_RGBA:
    236                    return (type == GL_FLOAT);
    237                case GL_DEPTH_COMPONENT:
    238                    return ValidReadPixelsFloatDepthType(context, info, type);
    239                case GL_DEPTH_STENCIL_OES:
    240                    return context->getExtensions().readDepthStencilNV &&
    241                           type == GL_FLOAT_32_UNSIGNED_INT_24_8_REV && info->stencilBits > 0;
    242                default:
    243                    return false;
    244            }
    245        default:
    246            UNREACHABLE();
    247            return false;
    248    }
    249 }
    250 
    251 template <typename ParamType>
    252 bool ValidateTextureWrapModeValue(const Context *context,
    253                                  angle::EntryPoint entryPoint,
    254                                  const ParamType *params,
    255                                  bool restrictedWrapModes)
    256 {
    257    switch (ConvertToGLenum(params[0]))
    258    {
    259        case GL_CLAMP_TO_EDGE:
    260            break;
    261 
    262        case GL_CLAMP_TO_BORDER:
    263            if (!context->getExtensions().textureBorderClampAny() &&
    264                context->getClientVersion() < ES_3_2)
    265            {
    266                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
    267                return false;
    268            }
    269            break;
    270 
    271        case GL_REPEAT:
    272        case GL_MIRRORED_REPEAT:
    273            if (restrictedWrapModes)
    274            {
    275                // OES_EGL_image_external and ANGLE_texture_rectangle specifies this error.
    276                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidWrapModeTexture);
    277                return false;
    278            }
    279            break;
    280 
    281        default:
    282            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureWrap);
    283            return false;
    284    }
    285 
    286    return true;
    287 }
    288 
    289 template <typename ParamType>
    290 bool ValidateTextureMinFilterValue(const Context *context,
    291                                   angle::EntryPoint entryPoint,
    292                                   const ParamType *params,
    293                                   bool restrictedMinFilter)
    294 {
    295    switch (ConvertToGLenum(params[0]))
    296    {
    297        case GL_NEAREST:
    298        case GL_LINEAR:
    299            break;
    300 
    301        case GL_NEAREST_MIPMAP_NEAREST:
    302        case GL_LINEAR_MIPMAP_NEAREST:
    303        case GL_NEAREST_MIPMAP_LINEAR:
    304        case GL_LINEAR_MIPMAP_LINEAR:
    305            if (restrictedMinFilter)
    306            {
    307                // OES_EGL_image_external specifies this error.
    308                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFilterTexture);
    309                return false;
    310            }
    311            break;
    312 
    313        default:
    314            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureFilterParam);
    315            return false;
    316    }
    317 
    318    return true;
    319 }
    320 
    321 template <typename ParamType>
    322 bool ValidateTextureMagFilterValue(const Context *context,
    323                                   angle::EntryPoint entryPoint,
    324                                   const ParamType *params)
    325 {
    326    switch (ConvertToGLenum(params[0]))
    327    {
    328        case GL_NEAREST:
    329        case GL_LINEAR:
    330            break;
    331 
    332        default:
    333            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureFilterParam);
    334            return false;
    335    }
    336 
    337    return true;
    338 }
    339 
    340 template <typename ParamType>
    341 bool ValidateTextureCompareModeValue(const Context *context,
    342                                     angle::EntryPoint entryPoint,
    343                                     const ParamType *params)
    344 {
    345    // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17
    346    switch (ConvertToGLenum(params[0]))
    347    {
    348        case GL_NONE:
    349        case GL_COMPARE_REF_TO_TEXTURE:
    350            break;
    351 
    352        default:
    353            context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
    354            return false;
    355    }
    356 
    357    return true;
    358 }
    359 
    360 template <typename ParamType>
    361 bool ValidateTextureCompareFuncValue(const Context *context,
    362                                     angle::EntryPoint entryPoint,
    363                                     const ParamType *params)
    364 {
    365    // Acceptable function parameters from GLES 3.0.2 spec, table 3.17
    366    switch (ConvertToGLenum(params[0]))
    367    {
    368        case GL_LEQUAL:
    369        case GL_GEQUAL:
    370        case GL_LESS:
    371        case GL_GREATER:
    372        case GL_EQUAL:
    373        case GL_NOTEQUAL:
    374        case GL_ALWAYS:
    375        case GL_NEVER:
    376            break;
    377 
    378        default:
    379            context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
    380            return false;
    381    }
    382 
    383    return true;
    384 }
    385 
    386 template <typename ParamType>
    387 bool ValidateTextureSRGBDecodeValue(const Context *context,
    388                                    angle::EntryPoint entryPoint,
    389                                    const ParamType *params)
    390 {
    391    if (!context->getExtensions().textureSRGBDecodeEXT)
    392    {
    393        context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
    394        return false;
    395    }
    396 
    397    switch (ConvertToGLenum(params[0]))
    398    {
    399        case GL_DECODE_EXT:
    400        case GL_SKIP_DECODE_EXT:
    401            break;
    402 
    403        default:
    404            context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
    405            return false;
    406    }
    407 
    408    return true;
    409 }
    410 
    411 template <typename ParamType>
    412 bool ValidateTextureSRGBOverrideValue(const Context *context,
    413                                      angle::EntryPoint entryPoint,
    414                                      const ParamType *params)
    415 {
    416    if (!context->getExtensions().textureFormatSRGBOverrideEXT)
    417    {
    418        context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
    419        return false;
    420    }
    421 
    422    switch (ConvertToGLenum(params[0]))
    423    {
    424        case GL_SRGB:
    425        case GL_NONE:
    426            break;
    427 
    428        default:
    429            context->validationError(entryPoint, GL_INVALID_ENUM, kUnknownParameter);
    430            return false;
    431    }
    432 
    433    return true;
    434 }
    435 
    436 bool ValidateTextureMaxAnisotropyExtensionEnabled(const Context *context,
    437                                                  angle::EntryPoint entryPoint)
    438 {
    439    if (!context->getExtensions().textureFilterAnisotropicEXT)
    440    {
    441        context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
    442        return false;
    443    }
    444 
    445    return true;
    446 }
    447 
    448 bool ValidateTextureMaxAnisotropyValue(const Context *context,
    449                                       angle::EntryPoint entryPoint,
    450                                       GLfloat paramValue)
    451 {
    452    if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
    453    {
    454        return false;
    455    }
    456 
    457    GLfloat largest = context->getCaps().maxTextureAnisotropy;
    458 
    459    if (paramValue < 1 || paramValue > largest)
    460    {
    461        context->validationError(entryPoint, GL_INVALID_VALUE, kOutsideOfBounds);
    462        return false;
    463    }
    464 
    465    return true;
    466 }
    467 
    468 bool ValidateFragmentShaderColorBufferMaskMatch(const Context *context)
    469 {
    470    const auto &glState            = context->getState();
    471    const Program *program         = context->getActiveLinkedProgram();
    472    const Framebuffer *framebuffer = glState.getDrawFramebuffer();
    473 
    474    auto drawBufferMask =
    475        framebuffer->getDrawBufferMask() & glState.getBlendStateExt().compareColorMask(0);
    476    auto fragmentOutputMask = program->getExecutable().getActiveOutputVariablesMask();
    477 
    478    return drawBufferMask == (drawBufferMask & fragmentOutputMask);
    479 }
    480 
    481 bool ValidateFragmentShaderColorBufferTypeMatch(const Context *context)
    482 {
    483    const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
    484    const Framebuffer *framebuffer      = context->getState().getDrawFramebuffer();
    485 
    486    return ValidateComponentTypeMasks(executable->getFragmentOutputsTypeMask().to_ulong(),
    487                                      framebuffer->getDrawBufferTypeMask().to_ulong(),
    488                                      executable->getActiveOutputVariablesMask().to_ulong(),
    489                                      framebuffer->getDrawBufferMask().to_ulong());
    490 }
    491 
    492 bool ValidateVertexShaderAttributeTypeMatch(const Context *context)
    493 {
    494    const auto &glState    = context->getState();
    495    const Program *program = context->getActiveLinkedProgram();
    496    const VertexArray *vao = context->getState().getVertexArray();
    497 
    498    if (!program)
    499    {
    500        return false;
    501    }
    502 
    503    unsigned long stateCurrentValuesTypeBits = glState.getCurrentValuesTypeMask().to_ulong();
    504    unsigned long vaoAttribTypeBits          = vao->getAttributesTypeMask().to_ulong();
    505    unsigned long vaoAttribEnabledMask       = vao->getAttributesMask().to_ulong();
    506 
    507    vaoAttribEnabledMask |= vaoAttribEnabledMask << kMaxComponentTypeMaskIndex;
    508    vaoAttribTypeBits = (vaoAttribEnabledMask & vaoAttribTypeBits);
    509    vaoAttribTypeBits |= (~vaoAttribEnabledMask & stateCurrentValuesTypeBits);
    510 
    511    const ProgramExecutable &executable = program->getExecutable();
    512    return ValidateComponentTypeMasks(executable.getAttributesTypeMask().to_ulong(),
    513                                      vaoAttribTypeBits, executable.getAttributesMask().to_ulong(),
    514                                      0xFFFF);
    515 }
    516 
    517 bool IsCompatibleDrawModeWithGeometryShader(PrimitiveMode drawMode,
    518                                            PrimitiveMode geometryShaderInputPrimitiveType)
    519 {
    520    // [EXT_geometry_shader] Section 11.1gs.1, Geometry Shader Input Primitives
    521    switch (drawMode)
    522    {
    523        case PrimitiveMode::Points:
    524            return geometryShaderInputPrimitiveType == PrimitiveMode::Points;
    525        case PrimitiveMode::Lines:
    526        case PrimitiveMode::LineStrip:
    527        case PrimitiveMode::LineLoop:
    528            return geometryShaderInputPrimitiveType == PrimitiveMode::Lines;
    529        case PrimitiveMode::LinesAdjacency:
    530        case PrimitiveMode::LineStripAdjacency:
    531            return geometryShaderInputPrimitiveType == PrimitiveMode::LinesAdjacency;
    532        case PrimitiveMode::Triangles:
    533        case PrimitiveMode::TriangleFan:
    534        case PrimitiveMode::TriangleStrip:
    535            return geometryShaderInputPrimitiveType == PrimitiveMode::Triangles;
    536        case PrimitiveMode::TrianglesAdjacency:
    537        case PrimitiveMode::TriangleStripAdjacency:
    538            return geometryShaderInputPrimitiveType == PrimitiveMode::TrianglesAdjacency;
    539        default:
    540            UNREACHABLE();
    541            return false;
    542    }
    543 }
    544 
    545 // GLES1 texture parameters are a small subset of the others
    546 bool IsValidGLES1TextureParameter(GLenum pname)
    547 {
    548    switch (pname)
    549    {
    550        case GL_TEXTURE_MAG_FILTER:
    551        case GL_TEXTURE_MIN_FILTER:
    552        case GL_TEXTURE_WRAP_S:
    553        case GL_TEXTURE_WRAP_T:
    554        case GL_TEXTURE_WRAP_R:
    555        case GL_GENERATE_MIPMAP:
    556        case GL_TEXTURE_CROP_RECT_OES:
    557            return true;
    558        default:
    559            return false;
    560    }
    561 }
    562 
    563 unsigned int GetSamplerParameterCount(GLenum pname)
    564 {
    565    return pname == GL_TEXTURE_BORDER_COLOR ? 4 : 1;
    566 }
    567 
    568 const char *ValidateProgramDrawAdvancedBlendState(const Context *context, Program *program)
    569 {
    570    const State &state = context->getState();
    571    const BlendEquationBitSet &supportedBlendEquations =
    572        program->getExecutable().getAdvancedBlendEquations();
    573    const DrawBufferMask &enabledDrawBufferMask = state.getBlendStateExt().getEnabledMask();
    574 
    575    for (size_t blendEnabledBufferIndex : enabledDrawBufferMask)
    576    {
    577        const gl::BlendEquationType &enabledBlendEquation = gl::FromGLenum<gl::BlendEquationType>(
    578            state.getBlendStateExt().getEquationColorIndexed(blendEnabledBufferIndex));
    579 
    580        if (enabledBlendEquation < gl::BlendEquationType::Multiply ||
    581            enabledBlendEquation > gl::BlendEquationType::HslLuminosity)
    582        {
    583            continue;
    584        }
    585 
    586        if (!supportedBlendEquations.test(enabledBlendEquation))
    587        {
    588            return gl::err::kBlendEquationNotEnabled;
    589        }
    590    }
    591 
    592    return nullptr;
    593 }
    594 
    595 ANGLE_INLINE const char *ValidateProgramDrawStates(const Context *context,
    596                                                   const Extensions &extensions,
    597                                                   Program *program)
    598 {
    599    const State &state = context->getState();
    600    if (extensions.multiviewOVR || extensions.multiview2OVR)
    601    {
    602        const int programNumViews     = program->usesMultiview() ? program->getNumViews() : 1;
    603        Framebuffer *framebuffer      = state.getDrawFramebuffer();
    604        const int framebufferNumViews = framebuffer->getNumViews();
    605 
    606        if (framebufferNumViews != programNumViews)
    607        {
    608            return gl::err::kMultiviewMismatch;
    609        }
    610 
    611        if (state.isTransformFeedbackActiveUnpaused() && framebufferNumViews > 1)
    612        {
    613            return gl::err::kMultiviewTransformFeedback;
    614        }
    615 
    616        if (extensions.disjointTimerQueryEXT && framebufferNumViews > 1 &&
    617            state.isQueryActive(QueryType::TimeElapsed))
    618        {
    619            return gl::err::kMultiviewTimerQuery;
    620        }
    621    }
    622 
    623    // Uniform buffer validation
    624    for (unsigned int uniformBlockIndex = 0;
    625         uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
    626    {
    627        const InterfaceBlock &uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
    628        GLuint blockBinding                = program->getUniformBlockBinding(uniformBlockIndex);
    629        const OffsetBindingPointer<Buffer> &uniformBuffer =
    630            state.getIndexedUniformBuffer(blockBinding);
    631 
    632        if (uniformBuffer.get() == nullptr && context->isWebGL())
    633        {
    634            // undefined behaviour
    635            return gl::err::kUniformBufferUnbound;
    636        }
    637 
    638        size_t uniformBufferSize = GetBoundBufferAvailableSize(uniformBuffer);
    639        if (uniformBufferSize < uniformBlock.dataSize &&
    640            (context->isWebGL() || context->isBufferAccessValidationEnabled()))
    641        {
    642            // undefined behaviour
    643            return gl::err::kUniformBufferTooSmall;
    644        }
    645 
    646        if (uniformBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
    647        {
    648            return gl::err::kUniformBufferBoundForTransformFeedback;
    649        }
    650    }
    651 
    652    // Enabled blend equation validation
    653    const char *errorString = nullptr;
    654 
    655    if (extensions.blendEquationAdvancedKHR)
    656    {
    657        errorString = ValidateProgramDrawAdvancedBlendState(context, program);
    658    }
    659 
    660    return errorString;
    661 }
    662 }  // anonymous namespace
    663 
    664 void SetRobustLengthParam(const GLsizei *length, GLsizei value)
    665 {
    666    if (length)
    667    {
    668        // Currently we modify robust length parameters in the validation layer. We should be only
    669        // doing this in the Context instead.
    670        // TODO(http://anglebug.com/4406): Remove when possible.
    671        *const_cast<GLsizei *>(length) = value;
    672    }
    673 }
    674 
    675 bool ValidTextureTarget(const Context *context, TextureType type)
    676 {
    677    switch (type)
    678    {
    679        case TextureType::_2D:
    680        case TextureType::CubeMap:
    681            return true;
    682 
    683        case TextureType::Rectangle:
    684            return context->getExtensions().textureRectangleANGLE;
    685 
    686        case TextureType::_3D:
    687            return ((context->getClientMajorVersion() >= 3) ||
    688                    context->getExtensions().texture3DOES);
    689 
    690        case TextureType::_2DArray:
    691            return (context->getClientMajorVersion() >= 3);
    692 
    693        case TextureType::_2DMultisample:
    694            return (context->getClientVersion() >= Version(3, 1) ||
    695                    context->getExtensions().textureMultisampleANGLE);
    696        case TextureType::_2DMultisampleArray:
    697            return context->getExtensions().textureStorageMultisample2dArrayOES;
    698 
    699        case TextureType::CubeMapArray:
    700            return (context->getClientVersion() >= Version(3, 2) ||
    701                    context->getExtensions().textureCubeMapArrayAny());
    702 
    703        case TextureType::VideoImage:
    704            return context->getExtensions().videoTextureWEBGL;
    705 
    706        case TextureType::Buffer:
    707            return (context->getClientVersion() >= Version(3, 2) ||
    708                    context->getExtensions().textureBufferAny());
    709 
    710        default:
    711            return false;
    712    }
    713 }
    714 
    715 bool ValidTexture2DTarget(const Context *context, TextureType type)
    716 {
    717    switch (type)
    718    {
    719        case TextureType::_2D:
    720        case TextureType::CubeMap:
    721            return true;
    722 
    723        case TextureType::Rectangle:
    724            return context->getExtensions().textureRectangleANGLE;
    725 
    726        default:
    727            return false;
    728    }
    729 }
    730 
    731 bool ValidTexture3DTarget(const Context *context, TextureType target)
    732 {
    733    switch (target)
    734    {
    735        case TextureType::_3D:
    736        case TextureType::_2DArray:
    737            return (context->getClientMajorVersion() >= 3);
    738 
    739        case TextureType::CubeMapArray:
    740            return (context->getClientVersion() >= Version(3, 2) ||
    741                    context->getExtensions().textureCubeMapArrayAny());
    742 
    743        default:
    744            return false;
    745    }
    746 }
    747 
    748 // Most texture GL calls are not compatible with external textures, so we have a separate validation
    749 // function for use in the GL calls that do
    750 bool ValidTextureExternalTarget(const Context *context, TextureType target)
    751 {
    752    return (target == TextureType::External) &&
    753           (context->getExtensions().EGLImageExternalOES ||
    754            context->getExtensions().EGLStreamConsumerExternalNV);
    755 }
    756 
    757 bool ValidTextureExternalTarget(const Context *context, TextureTarget target)
    758 {
    759    return (target == TextureTarget::External) &&
    760           ValidTextureExternalTarget(context, TextureType::External);
    761 }
    762 
    763 // This function differs from ValidTextureTarget in that the target must be
    764 // usable as the destination of a 2D operation-- so a cube face is valid, but
    765 // GL_TEXTURE_CUBE_MAP is not.
    766 // Note: duplicate of IsInternalTextureTarget
    767 bool ValidTexture2DDestinationTarget(const Context *context, TextureTarget target)
    768 {
    769    switch (target)
    770    {
    771        case TextureTarget::_2D:
    772        case TextureTarget::CubeMapNegativeX:
    773        case TextureTarget::CubeMapNegativeY:
    774        case TextureTarget::CubeMapNegativeZ:
    775        case TextureTarget::CubeMapPositiveX:
    776        case TextureTarget::CubeMapPositiveY:
    777        case TextureTarget::CubeMapPositiveZ:
    778            return true;
    779        case TextureTarget::Rectangle:
    780            return context->getExtensions().textureRectangleANGLE;
    781        case TextureTarget::VideoImage:
    782            return context->getExtensions().videoTextureWEBGL;
    783        default:
    784            return false;
    785    }
    786 }
    787 
    788 bool ValidateTransformFeedbackPrimitiveMode(const Context *context,
    789                                            angle::EntryPoint entryPoint,
    790                                            PrimitiveMode transformFeedbackPrimitiveMode,
    791                                            PrimitiveMode renderPrimitiveMode)
    792 {
    793    ASSERT(context);
    794 
    795    if ((!context->getExtensions().geometryShaderAny() ||
    796         !context->getExtensions().tessellationShaderEXT) &&
    797        context->getClientVersion() < ES_3_2)
    798    {
    799        // It is an invalid operation to call DrawArrays or DrawArraysInstanced with a draw mode
    800        // that does not match the current transform feedback object's draw mode (if transform
    801        // feedback is active), (3.0.2, section 2.14, pg 86)
    802        return transformFeedbackPrimitiveMode == renderPrimitiveMode;
    803    }
    804 
    805    const ProgramExecutable *executable = context->getState().getLinkedProgramExecutable(context);
    806    ASSERT(executable);
    807    if (executable->hasLinkedShaderStage(ShaderType::Geometry))
    808    {
    809        // If geometry shader is active, transform feedback mode must match what is output from this
    810        // stage.
    811        renderPrimitiveMode = executable->getGeometryShaderOutputPrimitiveType();
    812    }
    813    else if (executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
    814    {
    815        // Similarly with tessellation shaders, but only if no geometry shader is present.  With
    816        // tessellation shaders, only triangles are possibly output.
    817        return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles &&
    818               executable->getTessGenMode() == GL_TRIANGLES;
    819    }
    820 
    821    // [GL_EXT_geometry_shader] Table 12.1gs
    822    switch (renderPrimitiveMode)
    823    {
    824        case PrimitiveMode::Points:
    825            return transformFeedbackPrimitiveMode == PrimitiveMode::Points;
    826        case PrimitiveMode::Lines:
    827        case PrimitiveMode::LineStrip:
    828        case PrimitiveMode::LineLoop:
    829            return transformFeedbackPrimitiveMode == PrimitiveMode::Lines;
    830        case PrimitiveMode::Triangles:
    831        case PrimitiveMode::TriangleFan:
    832        case PrimitiveMode::TriangleStrip:
    833            return transformFeedbackPrimitiveMode == PrimitiveMode::Triangles;
    834        case PrimitiveMode::Patches:
    835            return transformFeedbackPrimitiveMode == PrimitiveMode::Patches;
    836        default:
    837            UNREACHABLE();
    838            return false;
    839    }
    840 }
    841 
    842 bool ValidateDrawElementsInstancedBase(const Context *context,
    843                                       angle::EntryPoint entryPoint,
    844                                       PrimitiveMode mode,
    845                                       GLsizei count,
    846                                       DrawElementsType type,
    847                                       const void *indices,
    848                                       GLsizei primcount)
    849 {
    850    if (primcount <= 0)
    851    {
    852        if (primcount < 0)
    853        {
    854            context->validationError(entryPoint, GL_INVALID_VALUE, kNegativePrimcount);
    855            return false;
    856        }
    857 
    858        // Early exit.
    859        return ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices,
    860                                          primcount);
    861    }
    862 
    863    if (!ValidateDrawElementsCommon(context, entryPoint, mode, count, type, indices, primcount))
    864    {
    865        return false;
    866    }
    867 
    868    if (count == 0)
    869    {
    870        // Early exit.
    871        return true;
    872    }
    873 
    874    return ValidateDrawInstancedAttribs(context, entryPoint, primcount);
    875 }
    876 
    877 bool ValidateDrawArraysInstancedBase(const Context *context,
    878                                     angle::EntryPoint entryPoint,
    879                                     PrimitiveMode mode,
    880                                     GLint first,
    881                                     GLsizei count,
    882                                     GLsizei primcount)
    883 {
    884    if (primcount <= 0)
    885    {
    886        if (primcount < 0)
    887        {
    888            context->validationError(entryPoint, GL_INVALID_VALUE, kNegativePrimcount);
    889            return false;
    890        }
    891 
    892        // Early exit.
    893        return ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount);
    894    }
    895 
    896    if (!ValidateDrawArraysCommon(context, entryPoint, mode, first, count, primcount))
    897    {
    898        return false;
    899    }
    900 
    901    if (count == 0)
    902    {
    903        // Early exit.
    904        return true;
    905    }
    906 
    907    return ValidateDrawInstancedAttribs(context, entryPoint, primcount);
    908 }
    909 
    910 bool ValidateDrawInstancedANGLE(const Context *context, angle::EntryPoint entryPoint)
    911 {
    912    // Verify there is at least one active attribute with a divisor of zero
    913    const State &state                  = context->getState();
    914    const ProgramExecutable *executable = state.getLinkedProgramExecutable(context);
    915 
    916    if (!executable)
    917    {
    918        // No executable means there is no Program/PPO bound, which is undefined behavior, but isn't
    919        // an error.
    920        context->getState().getDebug().insertMessage(
    921            GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR, 0, GL_DEBUG_SEVERITY_HIGH,
    922            std::string("Attempting to draw without a program"), gl::LOG_WARN, entryPoint);
    923        return true;
    924    }
    925 
    926    const auto &attribs  = state.getVertexArray()->getVertexAttributes();
    927    const auto &bindings = state.getVertexArray()->getVertexBindings();
    928    for (size_t attributeIndex = 0; attributeIndex < attribs.size(); attributeIndex++)
    929    {
    930        const VertexAttribute &attrib = attribs[attributeIndex];
    931        const VertexBinding &binding  = bindings[attrib.bindingIndex];
    932        if (executable->isAttribLocationActive(attributeIndex) && binding.getDivisor() == 0)
    933        {
    934            return true;
    935        }
    936    }
    937 
    938    context->validationError(entryPoint, GL_INVALID_OPERATION, kNoZeroDivisor);
    939    return false;
    940 }
    941 
    942 bool ValidTexture3DDestinationTarget(const Context *context, TextureTarget target)
    943 {
    944    switch (target)
    945    {
    946        case TextureTarget::_3D:
    947        case TextureTarget::_2DArray:
    948            return true;
    949        case TextureTarget::CubeMapArray:
    950            return (context->getClientVersion() >= Version(3, 2) ||
    951                    context->getExtensions().textureCubeMapArrayAny());
    952        default:
    953            return false;
    954    }
    955 }
    956 
    957 bool ValidTexLevelDestinationTarget(const Context *context, TextureType type)
    958 {
    959    switch (type)
    960    {
    961        case TextureType::_2D:
    962        case TextureType::_2DArray:
    963        case TextureType::_2DMultisample:
    964        case TextureType::CubeMap:
    965        case TextureType::_3D:
    966            return true;
    967        case TextureType::CubeMapArray:
    968            return (context->getClientVersion() >= Version(3, 2) ||
    969                    context->getExtensions().textureCubeMapArrayAny());
    970        case TextureType::Rectangle:
    971            return context->getExtensions().textureRectangleANGLE;
    972        case TextureType::_2DMultisampleArray:
    973            return context->getExtensions().textureStorageMultisample2dArrayOES;
    974        case TextureType::Buffer:
    975            return (context->getClientVersion() >= Version(3, 2) ||
    976                    context->getExtensions().textureBufferAny());
    977        default:
    978            return false;
    979    }
    980 }
    981 
    982 bool ValidFramebufferTarget(const Context *context, GLenum target)
    983 {
    984    static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER &&
    985                      GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
    986                  "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
    987 
    988    switch (target)
    989    {
    990        case GL_FRAMEBUFFER:
    991            return true;
    992 
    993        case GL_READ_FRAMEBUFFER:
    994        case GL_DRAW_FRAMEBUFFER:
    995            return (context->getExtensions().framebufferBlitAny() ||
    996                    context->getClientMajorVersion() >= 3);
    997 
    998        default:
    999            return false;
   1000    }
   1001 }
   1002 
   1003 bool ValidMipLevel(const Context *context, TextureType type, GLint level)
   1004 {
   1005    const auto &caps = context->getCaps();
   1006    int maxDimension = 0;
   1007    switch (type)
   1008    {
   1009        case TextureType::_2D:
   1010        case TextureType::_2DArray:
   1011        case TextureType::_2DMultisample:
   1012        case TextureType::_2DMultisampleArray:
   1013            // TODO(http://anglebug.com/2775): It's a bit unclear what the "maximum allowable
   1014            // level-of-detail" for multisample textures should be. Could maybe make it zero.
   1015            maxDimension = caps.max2DTextureSize;
   1016            break;
   1017 
   1018        case TextureType::CubeMap:
   1019        case TextureType::CubeMapArray:
   1020            maxDimension = caps.maxCubeMapTextureSize;
   1021            break;
   1022 
   1023        case TextureType::External:
   1024        case TextureType::Rectangle:
   1025        case TextureType::VideoImage:
   1026        case TextureType::Buffer:
   1027            return level == 0;
   1028 
   1029        case TextureType::_3D:
   1030            maxDimension = caps.max3DTextureSize;
   1031            break;
   1032 
   1033        default:
   1034            UNREACHABLE();
   1035    }
   1036 
   1037    return level <= log2(maxDimension) && level >= 0;
   1038 }
   1039 
   1040 bool ValidImageSizeParameters(const Context *context,
   1041                              angle::EntryPoint entryPoint,
   1042                              TextureType target,
   1043                              GLint level,
   1044                              GLsizei width,
   1045                              GLsizei height,
   1046                              GLsizei depth,
   1047                              bool isSubImage)
   1048 {
   1049    if (width < 0 || height < 0 || depth < 0)
   1050    {
   1051        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   1052        return false;
   1053    }
   1054    // TexSubImage parameters can be NPOT without textureNPOT extension,
   1055    // as long as the destination texture is POT.
   1056    bool hasNPOTSupport =
   1057        context->getExtensions().textureNpotOES || context->getClientVersion() >= Version(3, 0);
   1058    if (!isSubImage && !hasNPOTSupport &&
   1059        (level != 0 && (!isPow2(width) || !isPow2(height) || !isPow2(depth))))
   1060    {
   1061        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureNotPow2);
   1062        return false;
   1063    }
   1064 
   1065    if (!ValidMipLevel(context, target, level))
   1066    {
   1067        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   1068        return false;
   1069    }
   1070 
   1071    return true;
   1072 }
   1073 
   1074 bool ValidCompressedBaseLevel(GLsizei size, GLuint blockSize, GLint level)
   1075 {
   1076    // Already checked in ValidMipLevel.
   1077    ASSERT(level < 32);
   1078    // This function is used only for 4x4 BC formats.
   1079    ASSERT(blockSize == 4);
   1080    // Use the constant value to avoid division.
   1081    return ((size << level) % 4) == 0;
   1082 }
   1083 
   1084 bool ValidCompressedImageSize(const Context *context,
   1085                              GLenum internalFormat,
   1086                              GLint level,
   1087                              GLsizei width,
   1088                              GLsizei height,
   1089                              GLsizei depth)
   1090 {
   1091    if (width < 0 || height < 0)
   1092    {
   1093        return false;
   1094    }
   1095 
   1096    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
   1097 
   1098    if (!formatInfo.compressed && !formatInfo.paletted)
   1099    {
   1100        return false;
   1101    }
   1102 
   1103    // A texture format can not be both block-compressed and paletted
   1104    ASSERT(!(formatInfo.compressed && formatInfo.paletted));
   1105 
   1106    if (formatInfo.compressed)
   1107    {
   1108        // Only PVRTC1 requires dimensions to be powers of two
   1109        if (IsPVRTC1Format(internalFormat))
   1110        {
   1111            if (!isPow2(width) || !isPow2(height))
   1112            {
   1113                return false;
   1114            }
   1115 
   1116            if (context->getLimitations().squarePvrtc1)
   1117            {
   1118                if (width != height)
   1119                {
   1120                    return false;
   1121                }
   1122            }
   1123        }
   1124 
   1125        if (CompressedTextureFormatRequiresExactSize(internalFormat))
   1126        {
   1127            // In WebGL compatibility mode and D3D, enforce that the base level implied
   1128            // by the compressed texture's mip level would conform to the block
   1129            // size.
   1130            if (context->isWebGL() ||
   1131                context->getLimitations().compressedBaseMipLevelMultipleOfFour)
   1132            {
   1133                // This check is performed only for BC formats.
   1134                ASSERT(formatInfo.compressedBlockDepth == 1);
   1135                if (!ValidCompressedBaseLevel(width, formatInfo.compressedBlockWidth, level) ||
   1136                    !ValidCompressedBaseLevel(height, formatInfo.compressedBlockHeight, level))
   1137                {
   1138                    return false;
   1139                }
   1140            }
   1141            // non-WebGL and non-D3D check is not necessary for the following formats
   1142            // From EXT_texture_compression_s3tc specification:
   1143            // If the width or height is not a multiple of four, there will be 4x4 blocks at the
   1144            // edge of the image that contain "extra" texels that are not part of the image. From
   1145            // EXT_texture_compression_bptc & EXT_texture_compression_rgtc specification: If an
   1146            // RGTC/BPTC image has a width or height that is not a multiple of four, the data
   1147            // corresponding to texels outside the image are irrelevant and undefined.
   1148        }
   1149    }
   1150 
   1151    if (formatInfo.paletted)
   1152    {
   1153        // TODO(http://anglebug.com/7688): multi-level paletted images
   1154        if (level != 0)
   1155        {
   1156            return false;
   1157        }
   1158 
   1159        if (!isPow2(width) || !isPow2(height))
   1160        {
   1161            return false;
   1162        }
   1163    }
   1164 
   1165    return true;
   1166 }
   1167 
   1168 bool ValidCompressedSubImageSize(const Context *context,
   1169                                 GLenum internalFormat,
   1170                                 GLint xoffset,
   1171                                 GLint yoffset,
   1172                                 GLint zoffset,
   1173                                 GLsizei width,
   1174                                 GLsizei height,
   1175                                 GLsizei depth,
   1176                                 size_t textureWidth,
   1177                                 size_t textureHeight,
   1178                                 size_t textureDepth)
   1179 {
   1180    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
   1181    if (!formatInfo.compressed)
   1182    {
   1183        return false;
   1184    }
   1185 
   1186    if (xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0 || depth < 0)
   1187    {
   1188        return false;
   1189    }
   1190 
   1191    // ANGLE does not support compressed 3D blocks (provided exclusively by ASTC 3D formats), so
   1192    // there is no need to check the depth here. Only width and height determine whether a 2D array
   1193    // element or a 2D slice of a sliced 3D texture fill the entire level.
   1194    bool fillsEntireMip = xoffset == 0 && yoffset == 0 &&
   1195                          static_cast<size_t>(width) == textureWidth &&
   1196                          static_cast<size_t>(height) == textureHeight;
   1197 
   1198    if (CompressedFormatRequiresWholeImage(internalFormat))
   1199    {
   1200        return fillsEntireMip;
   1201    }
   1202 
   1203    if (CompressedSubTextureFormatRequiresExactSize(internalFormat))
   1204    {
   1205        if (xoffset % formatInfo.compressedBlockWidth != 0 ||
   1206            yoffset % formatInfo.compressedBlockHeight != 0 ||
   1207            zoffset % formatInfo.compressedBlockDepth != 0)
   1208        {
   1209            return false;
   1210        }
   1211 
   1212        // Allowed to either have data that is a multiple of block size or is smaller than the block
   1213        // size but fills the entire mip
   1214        bool sizeMultipleOfBlockSize = (width % formatInfo.compressedBlockWidth) == 0 &&
   1215                                       (height % formatInfo.compressedBlockHeight) == 0 &&
   1216                                       (depth % formatInfo.compressedBlockDepth) == 0;
   1217        if (!sizeMultipleOfBlockSize && !fillsEntireMip)
   1218        {
   1219            return false;
   1220        }
   1221    }
   1222 
   1223    return true;
   1224 }
   1225 
   1226 bool ValidImageDataSize(const Context *context,
   1227                        angle::EntryPoint entryPoint,
   1228                        TextureType texType,
   1229                        GLsizei width,
   1230                        GLsizei height,
   1231                        GLsizei depth,
   1232                        GLenum format,
   1233                        GLenum type,
   1234                        const void *pixels,
   1235                        GLsizei imageSize)
   1236 {
   1237    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
   1238    if (pixelUnpackBuffer == nullptr && imageSize < 0)
   1239    {
   1240        // Checks are not required
   1241        return true;
   1242    }
   1243 
   1244    // ...the data would be unpacked from the buffer object such that the memory reads required
   1245    // would exceed the data store size.
   1246    const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
   1247    ASSERT(formatInfo.internalFormat != GL_NONE);
   1248    const Extents size(width, height, depth);
   1249    const auto &unpack = context->getState().getUnpackState();
   1250 
   1251    bool targetIs3D = texType == TextureType::_3D || texType == TextureType::_2DArray;
   1252    GLuint endByte  = 0;
   1253    if (!formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D, &endByte))
   1254    {
   1255        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   1256        return false;
   1257    }
   1258 
   1259    if (pixelUnpackBuffer)
   1260    {
   1261        CheckedNumeric<size_t> checkedEndByte(endByte);
   1262        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
   1263        checkedEndByte += checkedOffset;
   1264 
   1265        if (!checkedEndByte.IsValid() ||
   1266            (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
   1267        {
   1268            // Overflow past the end of the buffer
   1269            context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   1270            return false;
   1271        }
   1272        if (pixelUnpackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   1273        {
   1274            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1275                                     kPixelUnpackBufferBoundForTransformFeedback);
   1276            return false;
   1277        }
   1278    }
   1279    else
   1280    {
   1281        ASSERT(imageSize >= 0);
   1282        if (pixels == nullptr && imageSize != 0)
   1283        {
   1284            context->validationError(entryPoint, GL_INVALID_OPERATION, kImageSizeMustBeZero);
   1285            return false;
   1286        }
   1287 
   1288        if (pixels != nullptr && endByte > static_cast<GLuint>(imageSize))
   1289        {
   1290            context->validationError(entryPoint, GL_INVALID_OPERATION, kImageSizeTooSmall);
   1291            return false;
   1292        }
   1293    }
   1294 
   1295    return true;
   1296 }
   1297 
   1298 bool ValidQueryType(const Context *context, QueryType queryType)
   1299 {
   1300    switch (queryType)
   1301    {
   1302        case QueryType::AnySamples:
   1303        case QueryType::AnySamplesConservative:
   1304            return context->getClientMajorVersion() >= 3 ||
   1305                   context->getExtensions().occlusionQueryBooleanEXT;
   1306        case QueryType::TransformFeedbackPrimitivesWritten:
   1307            return (context->getClientMajorVersion() >= 3);
   1308        case QueryType::TimeElapsed:
   1309            return context->getExtensions().disjointTimerQueryEXT;
   1310        case QueryType::CommandsCompleted:
   1311            return context->getExtensions().syncQueryCHROMIUM;
   1312        case QueryType::PrimitivesGenerated:
   1313            return context->getClientVersion() >= ES_3_2 ||
   1314                   context->getExtensions().geometryShaderAny();
   1315        default:
   1316            return false;
   1317    }
   1318 }
   1319 
   1320 bool ValidateWebGLVertexAttribPointer(const Context *context,
   1321                                      angle::EntryPoint entryPoint,
   1322                                      VertexAttribType type,
   1323                                      GLboolean normalized,
   1324                                      GLsizei stride,
   1325                                      const void *ptr,
   1326                                      bool pureInteger)
   1327 {
   1328    ASSERT(context->isWebGL());
   1329    // WebGL 1.0 [Section 6.11] Vertex Attribute Data Stride
   1330    // The WebGL API supports vertex attribute data strides up to 255 bytes. A call to
   1331    // vertexAttribPointer will generate an INVALID_VALUE error if the value for the stride
   1332    // parameter exceeds 255.
   1333    constexpr GLsizei kMaxWebGLStride = 255;
   1334    if (stride > kMaxWebGLStride)
   1335    {
   1336        context->validationError(entryPoint, GL_INVALID_VALUE, kStrideExceedsWebGLLimit);
   1337        return false;
   1338    }
   1339 
   1340    // WebGL 1.0 [Section 6.4] Buffer Offset and Stride Requirements
   1341    // The offset arguments to drawElements and vertexAttribPointer, and the stride argument to
   1342    // vertexAttribPointer, must be a multiple of the size of the data type passed to the call,
   1343    // or an INVALID_OPERATION error is generated.
   1344    angle::FormatID internalType = GetVertexFormatID(type, normalized, 1, pureInteger);
   1345    size_t typeSize              = GetVertexFormatSize(internalType);
   1346 
   1347    ASSERT(isPow2(typeSize) && typeSize > 0);
   1348    size_t sizeMask = (typeSize - 1);
   1349    if ((reinterpret_cast<intptr_t>(ptr) & sizeMask) != 0)
   1350    {
   1351        context->validationError(entryPoint, GL_INVALID_OPERATION, kOffsetMustBeMultipleOfType);
   1352        return false;
   1353    }
   1354 
   1355    if ((stride & sizeMask) != 0)
   1356    {
   1357        context->validationError(entryPoint, GL_INVALID_OPERATION, kStrideMustBeMultipleOfType);
   1358        return false;
   1359    }
   1360 
   1361    return true;
   1362 }
   1363 
   1364 Program *GetValidProgramNoResolve(const Context *context,
   1365                                  angle::EntryPoint entryPoint,
   1366                                  ShaderProgramID id)
   1367 {
   1368    // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will
   1369    // generate the error INVALID_VALUE if the provided name is not the name of either a shader
   1370    // or program object and INVALID_OPERATION if the provided name identifies an object
   1371    // that is not the expected type."
   1372 
   1373    Program *validProgram = context->getProgramNoResolveLink(id);
   1374 
   1375    if (!validProgram)
   1376    {
   1377        if (context->getShader(id))
   1378        {
   1379            context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
   1380        }
   1381        else
   1382        {
   1383            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramName);
   1384        }
   1385    }
   1386 
   1387    return validProgram;
   1388 }
   1389 
   1390 Program *GetValidProgram(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
   1391 {
   1392    Program *program = GetValidProgramNoResolve(context, entryPoint, id);
   1393    if (program)
   1394    {
   1395        program->resolveLink(context);
   1396    }
   1397    return program;
   1398 }
   1399 
   1400 Shader *GetValidShader(const Context *context, angle::EntryPoint entryPoint, ShaderProgramID id)
   1401 {
   1402    // See ValidProgram for spec details.
   1403 
   1404    Shader *validShader = context->getShader(id);
   1405 
   1406    if (!validShader)
   1407    {
   1408        if (context->getProgramNoResolveLink(id))
   1409        {
   1410            context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedShaderName);
   1411        }
   1412        else
   1413        {
   1414            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidShaderName);
   1415        }
   1416    }
   1417 
   1418    return validShader;
   1419 }
   1420 
   1421 bool ValidateAttachmentTarget(const Context *context,
   1422                              angle::EntryPoint entryPoint,
   1423                              GLenum attachment)
   1424 {
   1425    if (attachment >= GL_COLOR_ATTACHMENT1_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
   1426    {
   1427        if (context->getClientMajorVersion() < 3 && !context->getExtensions().drawBuffersEXT)
   1428        {
   1429            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   1430            return false;
   1431        }
   1432 
   1433        // Color attachment 0 is validated below because it is always valid
   1434        const int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT);
   1435        if (colorAttachment >= context->getCaps().maxColorAttachments)
   1436        {
   1437            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
   1438            return false;
   1439        }
   1440    }
   1441    else
   1442    {
   1443        switch (attachment)
   1444        {
   1445            case GL_COLOR_ATTACHMENT0:
   1446            case GL_DEPTH_ATTACHMENT:
   1447            case GL_STENCIL_ATTACHMENT:
   1448                break;
   1449 
   1450            case GL_DEPTH_STENCIL_ATTACHMENT:
   1451                if (!context->isWebGL() && context->getClientMajorVersion() < 3)
   1452                {
   1453                    context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   1454                    return false;
   1455                }
   1456                break;
   1457 
   1458            default:
   1459                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   1460                return false;
   1461        }
   1462    }
   1463 
   1464    return true;
   1465 }
   1466 
   1467 bool ValidateRenderbufferStorageParametersBase(const Context *context,
   1468                                               angle::EntryPoint entryPoint,
   1469                                               GLenum target,
   1470                                               GLsizei samples,
   1471                                               GLenum internalformat,
   1472                                               GLsizei width,
   1473                                               GLsizei height)
   1474 {
   1475    switch (target)
   1476    {
   1477        case GL_RENDERBUFFER:
   1478            break;
   1479        default:
   1480            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
   1481            return false;
   1482    }
   1483 
   1484    if (width < 0 || height < 0 || samples < 0)
   1485    {
   1486        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferWidthHeight);
   1487        return false;
   1488    }
   1489 
   1490    // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format.
   1491    GLenum convertedInternalFormat = context->getConvertedRenderbufferFormat(internalformat);
   1492 
   1493    const TextureCaps &formatCaps = context->getTextureCaps().get(convertedInternalFormat);
   1494    if (!formatCaps.renderbuffer)
   1495    {
   1496        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
   1497        return false;
   1498    }
   1499 
   1500    // ANGLE_framebuffer_multisample does not explicitly state that the internal format must be
   1501    // sized but it does state that the format must be in the ES2.0 spec table 4.5 which contains
   1502    // only sized internal formats.
   1503    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(convertedInternalFormat);
   1504    if (formatInfo.internalFormat == GL_NONE)
   1505    {
   1506        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferInternalFormat);
   1507        return false;
   1508    }
   1509 
   1510    if (std::max(width, height) > context->getCaps().maxRenderbufferSize)
   1511    {
   1512        context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxRenderbufferSize);
   1513        return false;
   1514    }
   1515 
   1516    RenderbufferID id = context->getState().getRenderbufferId();
   1517    if (id.value == 0)
   1518    {
   1519        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
   1520        return false;
   1521    }
   1522 
   1523    return true;
   1524 }
   1525 
   1526 bool ValidateBlitFramebufferParameters(const Context *context,
   1527                                       angle::EntryPoint entryPoint,
   1528                                       GLint srcX0,
   1529                                       GLint srcY0,
   1530                                       GLint srcX1,
   1531                                       GLint srcY1,
   1532                                       GLint dstX0,
   1533                                       GLint dstY0,
   1534                                       GLint dstX1,
   1535                                       GLint dstY1,
   1536                                       GLbitfield mask,
   1537                                       GLenum filter)
   1538 {
   1539    switch (filter)
   1540    {
   1541        case GL_NEAREST:
   1542            break;
   1543        case GL_LINEAR:
   1544            break;
   1545        default:
   1546            context->validationError(entryPoint, GL_INVALID_ENUM, kBlitInvalidFilter);
   1547            return false;
   1548    }
   1549 
   1550    if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
   1551    {
   1552        context->validationError(entryPoint, GL_INVALID_VALUE, kBlitInvalidMask);
   1553        return false;
   1554    }
   1555 
   1556    // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
   1557    // color buffer, leaving only nearest being unfiltered from above
   1558    if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
   1559    {
   1560        context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitOnlyNearestForNonColor);
   1561        return false;
   1562    }
   1563 
   1564    const auto &glState          = context->getState();
   1565    Framebuffer *readFramebuffer = glState.getReadFramebuffer();
   1566    Framebuffer *drawFramebuffer = glState.getDrawFramebuffer();
   1567 
   1568    if (!readFramebuffer || !drawFramebuffer)
   1569    {
   1570        context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
   1571                                 kBlitFramebufferMissing);
   1572        return false;
   1573    }
   1574 
   1575    if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
   1576    {
   1577        return false;
   1578    }
   1579 
   1580    if (!ValidateFramebufferComplete(context, entryPoint, drawFramebuffer))
   1581    {
   1582        return false;
   1583    }
   1584 
   1585    // EXT_YUV_target disallows blitting to or from a YUV framebuffer
   1586    if ((mask & GL_COLOR_BUFFER_BIT) != 0 &&
   1587        (readFramebuffer->hasYUVAttachment() || drawFramebuffer->hasYUVAttachment()))
   1588    {
   1589        context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitYUVFramebuffer);
   1590        return false;
   1591    }
   1592 
   1593    // The draw and read framebuffers can only match if:
   1594    // - They are the default framebuffer AND
   1595    // - The read/draw surfaces are different
   1596    if ((readFramebuffer->id() == drawFramebuffer->id()) &&
   1597        ((drawFramebuffer->id() != Framebuffer::kDefaultDrawFramebufferHandle) ||
   1598         (context->getCurrentDrawSurface() == context->getCurrentReadSurface())))
   1599    {
   1600        context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitFeedbackLoop);
   1601        return false;
   1602    }
   1603 
   1604    // Not allow blitting to MS buffers, therefore if renderToTextureSamples exist,
   1605    // consider it MS. checkReadBufferResourceSamples = false
   1606    if (!ValidateFramebufferNotMultisampled(context, entryPoint, drawFramebuffer, false))
   1607    {
   1608        return false;
   1609    }
   1610 
   1611    // This validation is specified in the WebGL 2.0 spec and not in the GLES 3.0.5 spec, but we
   1612    // always run it in order to avoid triggering driver bugs.
   1613    if (DifferenceCanOverflow(srcX0, srcX1) || DifferenceCanOverflow(srcY0, srcY1) ||
   1614        DifferenceCanOverflow(dstX0, dstX1) || DifferenceCanOverflow(dstY0, dstY1))
   1615    {
   1616        context->validationError(entryPoint, GL_INVALID_VALUE, kBlitDimensionsOutOfRange);
   1617        return false;
   1618    }
   1619 
   1620    bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
   1621 
   1622    if (mask & GL_COLOR_BUFFER_BIT)
   1623    {
   1624        const FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorAttachment();
   1625        const Extensions &extensions                 = context->getExtensions();
   1626 
   1627        if (readColorBuffer)
   1628        {
   1629            const Format &readFormat = readColorBuffer->getFormat();
   1630 
   1631            for (size_t drawbufferIdx = 0;
   1632                 drawbufferIdx < drawFramebuffer->getDrawbufferStateCount(); ++drawbufferIdx)
   1633            {
   1634                const FramebufferAttachment *attachment =
   1635                    drawFramebuffer->getDrawBuffer(drawbufferIdx);
   1636                if (attachment)
   1637                {
   1638                    const Format &drawFormat = attachment->getFormat();
   1639 
   1640                    // The GL ES 3.0.2 spec (pg 193) states that:
   1641                    // 1) If the read buffer is fixed point format, the draw buffer must be as well
   1642                    // 2) If the read buffer is an unsigned integer format, the draw buffer must be
   1643                    // as well
   1644                    // 3) If the read buffer is a signed integer format, the draw buffer must be as
   1645                    // well
   1646                    // Changes with EXT_color_buffer_float:
   1647                    // Case 1) is changed to fixed point OR floating point
   1648                    GLenum readComponentType = readFormat.info->componentType;
   1649                    GLenum drawComponentType = drawFormat.info->componentType;
   1650                    bool readFixedPoint      = (readComponentType == GL_UNSIGNED_NORMALIZED ||
   1651                                           readComponentType == GL_SIGNED_NORMALIZED);
   1652                    bool drawFixedPoint      = (drawComponentType == GL_UNSIGNED_NORMALIZED ||
   1653                                           drawComponentType == GL_SIGNED_NORMALIZED);
   1654 
   1655                    if (extensions.colorBufferFloatEXT)
   1656                    {
   1657                        bool readFixedOrFloat = (readFixedPoint || readComponentType == GL_FLOAT);
   1658                        bool drawFixedOrFloat = (drawFixedPoint || drawComponentType == GL_FLOAT);
   1659 
   1660                        if (readFixedOrFloat != drawFixedOrFloat)
   1661                        {
   1662                            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1663                                                     kBlitTypeMismatchFixedOrFloat);
   1664                            return false;
   1665                        }
   1666                    }
   1667                    else if (readFixedPoint != drawFixedPoint)
   1668                    {
   1669                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1670                                                 kBlitTypeMismatchFixedPoint);
   1671                        return false;
   1672                    }
   1673 
   1674                    if (readComponentType == GL_UNSIGNED_INT &&
   1675                        drawComponentType != GL_UNSIGNED_INT)
   1676                    {
   1677                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1678                                                 kBlitTypeMismatchUnsignedInteger);
   1679                        return false;
   1680                    }
   1681 
   1682                    if (readComponentType == GL_INT && drawComponentType != GL_INT)
   1683                    {
   1684                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1685                                                 kBlitTypeMismatchSignedInteger);
   1686                        return false;
   1687                    }
   1688 
   1689                    if (readColorBuffer->getResourceSamples() > 0 &&
   1690                        (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
   1691                    {
   1692                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1693                                                 kBlitMultisampledFormatOrBoundsMismatch);
   1694                        return false;
   1695                    }
   1696 
   1697                    if (context->isWebGL() && *readColorBuffer == *attachment)
   1698                    {
   1699                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1700                                                 kBlitSameImageColor);
   1701                        return false;
   1702                    }
   1703                }
   1704            }
   1705 
   1706            if (readFormat.info->isInt() && filter == GL_LINEAR)
   1707            {
   1708                context->validationError(entryPoint, GL_INVALID_OPERATION,
   1709                                         kBlitIntegerWithLinearFilter);
   1710                return false;
   1711            }
   1712        }
   1713        // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
   1714        // In OpenGL ES it is undefined what happens when an operation tries to blit from a missing
   1715        // attachment and WebGL defines it to be an error. We do the check unconditionally as the
   1716        // situation is an application error that would lead to a crash in ANGLE.
   1717        else if (drawFramebuffer->hasEnabledDrawBuffer())
   1718        {
   1719            context->validationError(entryPoint, GL_INVALID_OPERATION, kBlitMissingColor);
   1720            return false;
   1721        }
   1722    }
   1723 
   1724    GLenum masks[]       = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
   1725    GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
   1726    for (size_t i = 0; i < 2; i++)
   1727    {
   1728        if (mask & masks[i])
   1729        {
   1730            const FramebufferAttachment *readBuffer =
   1731                readFramebuffer->getAttachment(context, attachments[i]);
   1732            const FramebufferAttachment *drawBuffer =
   1733                drawFramebuffer->getAttachment(context, attachments[i]);
   1734 
   1735            if (readBuffer && drawBuffer)
   1736            {
   1737                if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
   1738                {
   1739                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   1740                                             kBlitDepthOrStencilFormatMismatch);
   1741                    return false;
   1742                }
   1743 
   1744                if (readBuffer->getResourceSamples() > 0 && !sameBounds)
   1745                {
   1746                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   1747                                             kBlitMultisampledBoundsMismatch);
   1748                    return false;
   1749                }
   1750 
   1751                if (context->isWebGL() && *readBuffer == *drawBuffer)
   1752                {
   1753                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   1754                                             kBlitSameImageDepthOrStencil);
   1755                    return false;
   1756                }
   1757            }
   1758            // WebGL 2.0 BlitFramebuffer when blitting from a missing attachment
   1759            else if (drawBuffer)
   1760            {
   1761                context->validationError(entryPoint, GL_INVALID_OPERATION,
   1762                                         kBlitMissingDepthOrStencil);
   1763                return false;
   1764            }
   1765        }
   1766    }
   1767 
   1768    // OVR_multiview2:
   1769    // Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
   1770    // current draw framebuffer isMultiview() or the number of
   1771    // views in the current read framebuffer is more than one.
   1772    if (readFramebuffer->readDisallowedByMultiview())
   1773    {
   1774        context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, kBlitFromMultiview);
   1775        return false;
   1776    }
   1777    if (drawFramebuffer->isMultiview())
   1778    {
   1779        context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION, kBlitToMultiview);
   1780        return false;
   1781    }
   1782 
   1783    return true;
   1784 }
   1785 
   1786 bool ValidateBindFramebufferBase(const Context *context,
   1787                                 angle::EntryPoint entryPoint,
   1788                                 GLenum target,
   1789                                 FramebufferID framebuffer)
   1790 {
   1791    if (!ValidFramebufferTarget(context, target))
   1792    {
   1793        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   1794        return false;
   1795    }
   1796 
   1797    if (!context->getState().isBindGeneratesResourceEnabled() &&
   1798        !context->isFramebufferGenerated(framebuffer))
   1799    {
   1800        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   1801        return false;
   1802    }
   1803 
   1804    return true;
   1805 }
   1806 
   1807 bool ValidateBindRenderbufferBase(const Context *context,
   1808                                  angle::EntryPoint entryPoint,
   1809                                  GLenum target,
   1810                                  RenderbufferID renderbuffer)
   1811 {
   1812    if (target != GL_RENDERBUFFER)
   1813    {
   1814        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
   1815        return false;
   1816    }
   1817 
   1818    if (!context->getState().isBindGeneratesResourceEnabled() &&
   1819        !context->isRenderbufferGenerated(renderbuffer))
   1820    {
   1821        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   1822        return false;
   1823    }
   1824 
   1825    return true;
   1826 }
   1827 
   1828 bool ValidateFramebufferParameteriBase(const Context *context,
   1829                                       angle::EntryPoint entryPoint,
   1830                                       GLenum target,
   1831                                       GLenum pname,
   1832                                       GLint param)
   1833 {
   1834    if (!ValidFramebufferTarget(context, target))
   1835    {
   1836        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   1837        return false;
   1838    }
   1839 
   1840    switch (pname)
   1841    {
   1842        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
   1843        {
   1844            GLint maxWidth = context->getCaps().maxFramebufferWidth;
   1845            if (param < 0 || param > maxWidth)
   1846            {
   1847                context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferWidth);
   1848                return false;
   1849            }
   1850            break;
   1851        }
   1852        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
   1853        {
   1854            GLint maxHeight = context->getCaps().maxFramebufferHeight;
   1855            if (param < 0 || param > maxHeight)
   1856            {
   1857                context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferHeight);
   1858                return false;
   1859            }
   1860            break;
   1861        }
   1862        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
   1863        {
   1864            GLint maxSamples = context->getCaps().maxFramebufferSamples;
   1865            if (param < 0 || param > maxSamples)
   1866            {
   1867                context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsFramebufferSamples);
   1868                return false;
   1869            }
   1870            break;
   1871        }
   1872        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
   1873        {
   1874            break;
   1875        }
   1876        case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
   1877        {
   1878            if (!context->getExtensions().geometryShaderAny() &&
   1879                context->getClientVersion() < ES_3_2)
   1880            {
   1881                context->validationError(entryPoint, GL_INVALID_ENUM,
   1882                                         kGeometryShaderExtensionNotEnabled);
   1883                return false;
   1884            }
   1885            GLint maxLayers = context->getCaps().maxFramebufferLayers;
   1886            if (param < 0 || param > maxLayers)
   1887            {
   1888                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFramebufferLayer);
   1889                return false;
   1890            }
   1891            break;
   1892        }
   1893        case GL_FRAMEBUFFER_FLIP_Y_MESA:
   1894        {
   1895            if (!context->getExtensions().framebufferFlipYMESA)
   1896            {
   1897                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   1898                return false;
   1899            }
   1900            break;
   1901        }
   1902        default:
   1903        {
   1904            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   1905            return false;
   1906        }
   1907    }
   1908 
   1909    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
   1910    ASSERT(framebuffer);
   1911    if (framebuffer->isDefault())
   1912    {
   1913        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebuffer);
   1914        return false;
   1915    }
   1916    return true;
   1917 }
   1918 
   1919 bool ValidateFramebufferRenderbufferBase(const Context *context,
   1920                                         angle::EntryPoint entryPoint,
   1921                                         GLenum target,
   1922                                         GLenum attachment,
   1923                                         GLenum renderbuffertarget,
   1924                                         RenderbufferID renderbuffer)
   1925 {
   1926    if (!ValidFramebufferTarget(context, target))
   1927    {
   1928        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   1929        return false;
   1930    }
   1931 
   1932    if (renderbuffertarget != GL_RENDERBUFFER)
   1933    {
   1934        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
   1935        return false;
   1936    }
   1937 
   1938    Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
   1939 
   1940    ASSERT(framebuffer);
   1941    if (framebuffer->isDefault())
   1942    {
   1943        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget);
   1944        return false;
   1945    }
   1946 
   1947    if (!ValidateAttachmentTarget(context, entryPoint, attachment))
   1948    {
   1949        return false;
   1950    }
   1951 
   1952    // [OpenGL ES 2.0.25] Section 4.4.3 page 112
   1953    // [OpenGL ES 3.0.2] Section 4.4.2 page 201
   1954    // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of
   1955    // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated.
   1956    if (renderbuffer.value != 0)
   1957    {
   1958        if (!context->getRenderbuffer(renderbuffer))
   1959        {
   1960            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidRenderbufferTarget);
   1961            return false;
   1962        }
   1963    }
   1964 
   1965    return true;
   1966 }
   1967 
   1968 bool ValidateFramebufferTextureBase(const Context *context,
   1969                                    angle::EntryPoint entryPoint,
   1970                                    GLenum target,
   1971                                    GLenum attachment,
   1972                                    TextureID texture,
   1973                                    GLint level)
   1974 {
   1975    if (!ValidFramebufferTarget(context, target))
   1976    {
   1977        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   1978        return false;
   1979    }
   1980 
   1981    if (!ValidateAttachmentTarget(context, entryPoint, attachment))
   1982    {
   1983        return false;
   1984    }
   1985 
   1986    if (texture.value != 0)
   1987    {
   1988        Texture *tex = context->getTexture(texture);
   1989 
   1990        if (tex == nullptr)
   1991        {
   1992            context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingTexture);
   1993            return false;
   1994        }
   1995 
   1996        if (level < 0)
   1997        {
   1998            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   1999            return false;
   2000        }
   2001 
   2002        // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
   2003        // An INVALID_VALUE error is generated if texture is not zero and level is
   2004        // not a supported texture level for textarget
   2005 
   2006        // Common criteria for not supported texture levels(other criteria are handled case by case
   2007        // in non base functions): If texture refers to an immutable-format texture, level must be
   2008        // greater than or equal to zero and smaller than the value of TEXTURE_IMMUTABLE_LEVELS for
   2009        // texture.
   2010        if (tex->getImmutableFormat() && context->getClientVersion() >= ES_3_1)
   2011        {
   2012            if (level >= static_cast<GLint>(tex->getImmutableLevels()))
   2013            {
   2014                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   2015                return false;
   2016            }
   2017        }
   2018 
   2019        // GLES spec 3.2, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
   2020        // An INVALID_OPERATION error is generated if <texture> is the name of a buffer texture.
   2021        if ((context->getClientVersion() >= ES_3_2 ||
   2022             context->getExtensions().textureBufferAny()) &&
   2023            tex->getType() == TextureType::Buffer)
   2024        {
   2025            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidTextureTarget);
   2026            return false;
   2027        }
   2028 
   2029        if (tex->getState().hasProtectedContent() != context->getState().hasProtectedContent())
   2030        {
   2031            context->validationError(
   2032                entryPoint, GL_INVALID_OPERATION,
   2033                "Mismatch between Texture and Context Protected Content state");
   2034            return false;
   2035        }
   2036    }
   2037 
   2038    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
   2039    ASSERT(framebuffer);
   2040 
   2041    if (framebuffer->isDefault())
   2042    {
   2043        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget);
   2044        return false;
   2045    }
   2046 
   2047    return true;
   2048 }
   2049 
   2050 bool ValidateGenerateMipmapBase(const Context *context,
   2051                                angle::EntryPoint entryPoint,
   2052                                TextureType target)
   2053 {
   2054    if (!ValidTextureTarget(context, target))
   2055    {
   2056        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   2057        return false;
   2058    }
   2059 
   2060    Texture *texture = context->getTextureByType(target);
   2061 
   2062    if (texture == nullptr)
   2063    {
   2064        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotBound);
   2065        return false;
   2066    }
   2067 
   2068    const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
   2069 
   2070    // This error isn't spelled out in the spec in a very explicit way, but we interpret the spec so
   2071    // that out-of-range base level has a non-color-renderable / non-texture-filterable format.
   2072    if (effectiveBaseLevel >= IMPLEMENTATION_MAX_TEXTURE_LEVELS)
   2073    {
   2074        context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelOutOfRange);
   2075        return false;
   2076    }
   2077 
   2078    TextureTarget baseTarget = (target == TextureType::CubeMap)
   2079                                   ? TextureTarget::CubeMapPositiveX
   2080                                   : NonCubeTextureTypeToTarget(target);
   2081    const auto &format       = *(texture->getFormat(baseTarget, effectiveBaseLevel).info);
   2082    if (format.sizedInternalFormat == GL_NONE || format.compressed || format.depthBits > 0 ||
   2083        format.stencilBits > 0)
   2084    {
   2085        context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
   2086        return false;
   2087    }
   2088 
   2089    // GenerateMipmap accepts formats that are unsized or both color renderable and filterable.
   2090    bool formatUnsized = !format.sized;
   2091    bool formatColorRenderableAndFilterable =
   2092        format.filterSupport(context->getClientVersion(), context->getExtensions()) &&
   2093        format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions());
   2094    if (!formatUnsized && !formatColorRenderableAndFilterable)
   2095    {
   2096        context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
   2097        return false;
   2098    }
   2099 
   2100    // GL_EXT_sRGB adds an unsized SRGB (no alpha) format which has explicitly disabled mipmap
   2101    // generation
   2102    if (format.colorEncoding == GL_SRGB && format.format == GL_RGB)
   2103    {
   2104        context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
   2105        return false;
   2106    }
   2107 
   2108    // According to the OpenGL extension spec EXT_sRGB.txt, EXT_SRGB is based on ES 2.0 and
   2109    // generateMipmap is not allowed if texture format is SRGB_EXT or SRGB_ALPHA_EXT.
   2110    if (context->getClientVersion() < Version(3, 0) && format.colorEncoding == GL_SRGB)
   2111    {
   2112        context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapNotAllowed);
   2113        return false;
   2114    }
   2115 
   2116    // Non-power of 2 ES2 check
   2117    if (context->getClientVersion() < Version(3, 0) && !context->getExtensions().textureNpotOES &&
   2118        (!isPow2(static_cast<int>(texture->getWidth(baseTarget, 0))) ||
   2119         !isPow2(static_cast<int>(texture->getHeight(baseTarget, 0)))))
   2120    {
   2121        ASSERT(target == TextureType::_2D || target == TextureType::Rectangle ||
   2122               target == TextureType::CubeMap);
   2123        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotPow2);
   2124        return false;
   2125    }
   2126 
   2127    // Cube completeness check
   2128    if (target == TextureType::CubeMap && !texture->getTextureState().isCubeComplete())
   2129    {
   2130        context->validationError(entryPoint, GL_INVALID_OPERATION, kCubemapIncomplete);
   2131        return false;
   2132    }
   2133 
   2134    if (context->isWebGL() && (texture->getWidth(baseTarget, effectiveBaseLevel) == 0 ||
   2135                               texture->getHeight(baseTarget, effectiveBaseLevel) == 0))
   2136    {
   2137        context->validationError(entryPoint, GL_INVALID_OPERATION, kGenerateMipmapZeroSize);
   2138        return false;
   2139    }
   2140 
   2141    return true;
   2142 }
   2143 
   2144 bool ValidateReadPixelsRobustANGLE(const Context *context,
   2145                                   angle::EntryPoint entryPoint,
   2146                                   GLint x,
   2147                                   GLint y,
   2148                                   GLsizei width,
   2149                                   GLsizei height,
   2150                                   GLenum format,
   2151                                   GLenum type,
   2152                                   GLsizei bufSize,
   2153                                   const GLsizei *length,
   2154                                   const GLsizei *columns,
   2155                                   const GLsizei *rows,
   2156                                   const void *pixels)
   2157 {
   2158    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2159    {
   2160        return false;
   2161    }
   2162 
   2163    GLsizei writeLength  = 0;
   2164    GLsizei writeColumns = 0;
   2165    GLsizei writeRows    = 0;
   2166 
   2167    if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
   2168                                &writeLength, &writeColumns, &writeRows, pixels))
   2169    {
   2170        return false;
   2171    }
   2172 
   2173    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   2174    {
   2175        return false;
   2176    }
   2177 
   2178    SetRobustLengthParam(length, writeLength);
   2179    SetRobustLengthParam(columns, writeColumns);
   2180    SetRobustLengthParam(rows, writeRows);
   2181 
   2182    return true;
   2183 }
   2184 
   2185 bool ValidateReadnPixelsEXT(const Context *context,
   2186                            angle::EntryPoint entryPoint,
   2187                            GLint x,
   2188                            GLint y,
   2189                            GLsizei width,
   2190                            GLsizei height,
   2191                            GLenum format,
   2192                            GLenum type,
   2193                            GLsizei bufSize,
   2194                            const void *pixels)
   2195 {
   2196    if (bufSize < 0)
   2197    {
   2198        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   2199        return false;
   2200    }
   2201 
   2202    return ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
   2203                                  nullptr, nullptr, nullptr, pixels);
   2204 }
   2205 
   2206 bool ValidateReadnPixelsRobustANGLE(const Context *context,
   2207                                    angle::EntryPoint entryPoint,
   2208                                    GLint x,
   2209                                    GLint y,
   2210                                    GLsizei width,
   2211                                    GLsizei height,
   2212                                    GLenum format,
   2213                                    GLenum type,
   2214                                    GLsizei bufSize,
   2215                                    const GLsizei *length,
   2216                                    const GLsizei *columns,
   2217                                    const GLsizei *rows,
   2218                                    const void *data)
   2219 {
   2220    GLsizei writeLength  = 0;
   2221    GLsizei writeColumns = 0;
   2222    GLsizei writeRows    = 0;
   2223 
   2224    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2225    {
   2226        return false;
   2227    }
   2228 
   2229    if (!ValidateReadPixelsBase(context, entryPoint, x, y, width, height, format, type, bufSize,
   2230                                &writeLength, &writeColumns, &writeRows, data))
   2231    {
   2232        return false;
   2233    }
   2234 
   2235    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   2236    {
   2237        return false;
   2238    }
   2239 
   2240    SetRobustLengthParam(length, writeLength);
   2241    SetRobustLengthParam(columns, writeColumns);
   2242    SetRobustLengthParam(rows, writeRows);
   2243 
   2244    return true;
   2245 }
   2246 
   2247 bool ValidateGenQueriesEXT(const Context *context,
   2248                           angle::EntryPoint entryPoint,
   2249                           GLsizei n,
   2250                           const QueryID *ids)
   2251 {
   2252    if (!context->getExtensions().occlusionQueryBooleanEXT &&
   2253        !context->getExtensions().disjointTimerQueryEXT)
   2254    {
   2255        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
   2256        return false;
   2257    }
   2258 
   2259    return ValidateGenOrDelete(context, entryPoint, n);
   2260 }
   2261 
   2262 bool ValidateDeleteQueriesEXT(const Context *context,
   2263                              angle::EntryPoint entryPoint,
   2264                              GLsizei n,
   2265                              const QueryID *ids)
   2266 {
   2267    if (!context->getExtensions().occlusionQueryBooleanEXT &&
   2268        !context->getExtensions().disjointTimerQueryEXT)
   2269    {
   2270        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
   2271        return false;
   2272    }
   2273 
   2274    return ValidateGenOrDelete(context, entryPoint, n);
   2275 }
   2276 
   2277 bool ValidateIsQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryID id)
   2278 {
   2279    if (!context->getExtensions().occlusionQueryBooleanEXT &&
   2280        !context->getExtensions().disjointTimerQueryEXT)
   2281    {
   2282        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
   2283        return false;
   2284    }
   2285 
   2286    return true;
   2287 }
   2288 
   2289 bool ValidateBeginQueryBase(const Context *context,
   2290                            angle::EntryPoint entryPoint,
   2291                            QueryType target,
   2292                            QueryID id)
   2293 {
   2294    if (!ValidQueryType(context, target))
   2295    {
   2296        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType);
   2297        return false;
   2298    }
   2299 
   2300    if (id.value == 0)
   2301    {
   2302        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
   2303        return false;
   2304    }
   2305 
   2306    // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
   2307    // of zero, if the active query object name for <target> is non-zero (for the
   2308    // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
   2309    // the active query for either target is non-zero), if <id> is the name of an
   2310    // existing query object whose type does not match <target>, or if <id> is the
   2311    // active query object name for any query type, the error INVALID_OPERATION is
   2312    // generated.
   2313 
   2314    // Ensure no other queries are active
   2315    // NOTE: If other queries than occlusion are supported, we will need to check
   2316    // separately that:
   2317    //    a) The query ID passed is not the current active query for any target/type
   2318    //    b) There are no active queries for the requested target (and in the case
   2319    //       of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
   2320    //       no query may be active for either if glBeginQuery targets either.
   2321 
   2322    if (context->getState().isQueryActive(target))
   2323    {
   2324        context->validationError(entryPoint, GL_INVALID_OPERATION, kOtherQueryActive);
   2325        return false;
   2326    }
   2327 
   2328    // check that name was obtained with glGenQueries
   2329    if (!context->isQueryGenerated(id))
   2330    {
   2331        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
   2332        return false;
   2333    }
   2334 
   2335    // Check for type mismatch. If query is not yet started we're good to go.
   2336    Query *queryObject = context->getQuery(id);
   2337    if (queryObject && queryObject->getType() != target)
   2338    {
   2339        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryTargetMismatch);
   2340        return false;
   2341    }
   2342 
   2343    return true;
   2344 }
   2345 
   2346 bool ValidateBeginQueryEXT(const Context *context,
   2347                           angle::EntryPoint entryPoint,
   2348                           QueryType target,
   2349                           QueryID id)
   2350 {
   2351    if (!context->getExtensions().occlusionQueryBooleanEXT &&
   2352        !context->getExtensions().disjointTimerQueryEXT &&
   2353        !context->getExtensions().syncQueryCHROMIUM)
   2354    {
   2355        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
   2356        return false;
   2357    }
   2358 
   2359    return ValidateBeginQueryBase(context, entryPoint, target, id);
   2360 }
   2361 
   2362 bool ValidateEndQueryBase(const Context *context, angle::EntryPoint entryPoint, QueryType target)
   2363 {
   2364    if (!ValidQueryType(context, target))
   2365    {
   2366        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType);
   2367        return false;
   2368    }
   2369 
   2370    const Query *queryObject = context->getState().getActiveQuery(target);
   2371 
   2372    if (queryObject == nullptr)
   2373    {
   2374        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryInactive);
   2375        return false;
   2376    }
   2377 
   2378    return true;
   2379 }
   2380 
   2381 bool ValidateEndQueryEXT(const Context *context, angle::EntryPoint entryPoint, QueryType target)
   2382 {
   2383    if (!context->getExtensions().occlusionQueryBooleanEXT &&
   2384        !context->getExtensions().disjointTimerQueryEXT &&
   2385        !context->getExtensions().syncQueryCHROMIUM)
   2386    {
   2387        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryExtensionNotEnabled);
   2388        return false;
   2389    }
   2390 
   2391    return ValidateEndQueryBase(context, entryPoint, target);
   2392 }
   2393 
   2394 bool ValidateQueryCounterEXT(const Context *context,
   2395                             angle::EntryPoint entryPoint,
   2396                             QueryID id,
   2397                             QueryType target)
   2398 {
   2399    if (!context->getExtensions().disjointTimerQueryEXT)
   2400    {
   2401        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2402        return false;
   2403    }
   2404 
   2405    if (target != QueryType::Timestamp)
   2406    {
   2407        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryTarget);
   2408        return false;
   2409    }
   2410 
   2411    if (!context->isQueryGenerated(id))
   2412    {
   2413        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
   2414        return false;
   2415    }
   2416 
   2417    // If query object is not started, that's fine.
   2418    Query *queryObject = context->getQuery(id);
   2419    if (queryObject && context->getState().isQueryActive(queryObject))
   2420    {
   2421        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryActive);
   2422        return false;
   2423    }
   2424 
   2425    return true;
   2426 }
   2427 
   2428 bool ValidateGetQueryivBase(const Context *context,
   2429                            angle::EntryPoint entryPoint,
   2430                            QueryType target,
   2431                            GLenum pname,
   2432                            GLsizei *numParams)
   2433 {
   2434    if (numParams)
   2435    {
   2436        *numParams = 0;
   2437    }
   2438 
   2439    if (!ValidQueryType(context, target) && target != QueryType::Timestamp)
   2440    {
   2441        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryType);
   2442        return false;
   2443    }
   2444 
   2445    switch (pname)
   2446    {
   2447        case GL_CURRENT_QUERY_EXT:
   2448            if (target == QueryType::Timestamp)
   2449            {
   2450                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidQueryTarget);
   2451                return false;
   2452            }
   2453            break;
   2454        case GL_QUERY_COUNTER_BITS_EXT:
   2455            if (!context->getExtensions().disjointTimerQueryEXT ||
   2456                (target != QueryType::Timestamp && target != QueryType::TimeElapsed))
   2457            {
   2458                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   2459                return false;
   2460            }
   2461            break;
   2462        default:
   2463            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   2464            return false;
   2465    }
   2466 
   2467    if (numParams)
   2468    {
   2469        // All queries return only one value
   2470        *numParams = 1;
   2471    }
   2472 
   2473    return true;
   2474 }
   2475 
   2476 bool ValidateGetQueryivEXT(const Context *context,
   2477                           angle::EntryPoint entryPoint,
   2478                           QueryType target,
   2479                           GLenum pname,
   2480                           const GLint *params)
   2481 {
   2482    if (!context->getExtensions().occlusionQueryBooleanEXT &&
   2483        !context->getExtensions().disjointTimerQueryEXT &&
   2484        !context->getExtensions().syncQueryCHROMIUM)
   2485    {
   2486        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2487        return false;
   2488    }
   2489 
   2490    return ValidateGetQueryivBase(context, entryPoint, target, pname, nullptr);
   2491 }
   2492 
   2493 bool ValidateGetQueryivRobustANGLE(const Context *context,
   2494                                   angle::EntryPoint entryPoint,
   2495                                   QueryType target,
   2496                                   GLenum pname,
   2497                                   GLsizei bufSize,
   2498                                   const GLsizei *length,
   2499                                   const GLint *params)
   2500 {
   2501    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2502    {
   2503        return false;
   2504    }
   2505 
   2506    GLsizei numParams = 0;
   2507 
   2508    if (!ValidateGetQueryivBase(context, entryPoint, target, pname, &numParams))
   2509    {
   2510        return false;
   2511    }
   2512 
   2513    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   2514    {
   2515        return false;
   2516    }
   2517 
   2518    SetRobustLengthParam(length, numParams);
   2519 
   2520    return true;
   2521 }
   2522 
   2523 bool ValidateGetQueryObjectValueBase(const Context *context,
   2524                                     angle::EntryPoint entryPoint,
   2525                                     QueryID id,
   2526                                     GLenum pname,
   2527                                     GLsizei *numParams)
   2528 {
   2529    if (numParams)
   2530    {
   2531        *numParams = 1;
   2532    }
   2533 
   2534    if (context->isContextLost())
   2535    {
   2536        context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
   2537 
   2538        if (pname == GL_QUERY_RESULT_AVAILABLE_EXT)
   2539        {
   2540            // Generate an error but still return true, the context still needs to return a
   2541            // value in this case.
   2542            return true;
   2543        }
   2544        else
   2545        {
   2546            return false;
   2547        }
   2548    }
   2549 
   2550    Query *queryObject = context->getQuery(id);
   2551 
   2552    if (!queryObject)
   2553    {
   2554        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidQueryId);
   2555        return false;
   2556    }
   2557 
   2558    if (context->getState().isQueryActive(queryObject))
   2559    {
   2560        context->validationError(entryPoint, GL_INVALID_OPERATION, kQueryActive);
   2561        return false;
   2562    }
   2563 
   2564    switch (pname)
   2565    {
   2566        case GL_QUERY_RESULT_EXT:
   2567        case GL_QUERY_RESULT_AVAILABLE_EXT:
   2568            break;
   2569 
   2570        default:
   2571            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   2572            return false;
   2573    }
   2574 
   2575    return true;
   2576 }
   2577 
   2578 bool ValidateGetQueryObjectivEXT(const Context *context,
   2579                                 angle::EntryPoint entryPoint,
   2580                                 QueryID id,
   2581                                 GLenum pname,
   2582                                 const GLint *params)
   2583 {
   2584    if (!context->getExtensions().disjointTimerQueryEXT)
   2585    {
   2586        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2587        return false;
   2588    }
   2589    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
   2590 }
   2591 
   2592 bool ValidateGetQueryObjectivRobustANGLE(const Context *context,
   2593                                         angle::EntryPoint entryPoint,
   2594                                         QueryID id,
   2595                                         GLenum pname,
   2596                                         GLsizei bufSize,
   2597                                         const GLsizei *length,
   2598                                         const GLint *params)
   2599 {
   2600    if (!context->getExtensions().disjointTimerQueryEXT)
   2601    {
   2602        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2603        return false;
   2604    }
   2605 
   2606    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2607    {
   2608        return false;
   2609    }
   2610 
   2611    GLsizei numParams = 0;
   2612 
   2613    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
   2614    {
   2615        return false;
   2616    }
   2617 
   2618    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   2619    {
   2620        return false;
   2621    }
   2622 
   2623    SetRobustLengthParam(length, numParams);
   2624 
   2625    return true;
   2626 }
   2627 
   2628 bool ValidateGetQueryObjectuivEXT(const Context *context,
   2629                                  angle::EntryPoint entryPoint,
   2630                                  QueryID id,
   2631                                  GLenum pname,
   2632                                  const GLuint *params)
   2633 {
   2634    if (!context->getExtensions().disjointTimerQueryEXT &&
   2635        !context->getExtensions().occlusionQueryBooleanEXT &&
   2636        !context->getExtensions().syncQueryCHROMIUM)
   2637    {
   2638        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2639        return false;
   2640    }
   2641    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
   2642 }
   2643 
   2644 bool ValidateGetQueryObjectuivRobustANGLE(const Context *context,
   2645                                          angle::EntryPoint entryPoint,
   2646                                          QueryID id,
   2647                                          GLenum pname,
   2648                                          GLsizei bufSize,
   2649                                          const GLsizei *length,
   2650                                          const GLuint *params)
   2651 {
   2652    if (!context->getExtensions().disjointTimerQueryEXT &&
   2653        !context->getExtensions().occlusionQueryBooleanEXT &&
   2654        !context->getExtensions().syncQueryCHROMIUM)
   2655    {
   2656        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2657        return false;
   2658    }
   2659 
   2660    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2661    {
   2662        return false;
   2663    }
   2664 
   2665    GLsizei numParams = 0;
   2666 
   2667    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
   2668    {
   2669        return false;
   2670    }
   2671 
   2672    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   2673    {
   2674        return false;
   2675    }
   2676 
   2677    SetRobustLengthParam(length, numParams);
   2678 
   2679    return true;
   2680 }
   2681 
   2682 bool ValidateGetQueryObjecti64vEXT(const Context *context,
   2683                                   angle::EntryPoint entryPoint,
   2684                                   QueryID id,
   2685                                   GLenum pname,
   2686                                   GLint64 *params)
   2687 {
   2688    if (!context->getExtensions().disjointTimerQueryEXT)
   2689    {
   2690        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2691        return false;
   2692    }
   2693    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
   2694 }
   2695 
   2696 bool ValidateGetQueryObjecti64vRobustANGLE(const Context *context,
   2697                                           angle::EntryPoint entryPoint,
   2698                                           QueryID id,
   2699                                           GLenum pname,
   2700                                           GLsizei bufSize,
   2701                                           const GLsizei *length,
   2702                                           GLint64 *params)
   2703 {
   2704    if (!context->getExtensions().disjointTimerQueryEXT)
   2705    {
   2706        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2707        return false;
   2708    }
   2709 
   2710    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2711    {
   2712        return false;
   2713    }
   2714 
   2715    GLsizei numParams = 0;
   2716 
   2717    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
   2718    {
   2719        return false;
   2720    }
   2721 
   2722    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   2723    {
   2724        return false;
   2725    }
   2726 
   2727    SetRobustLengthParam(length, numParams);
   2728 
   2729    return true;
   2730 }
   2731 
   2732 bool ValidateGetQueryObjectui64vEXT(const Context *context,
   2733                                    angle::EntryPoint entryPoint,
   2734                                    QueryID id,
   2735                                    GLenum pname,
   2736                                    GLuint64 *params)
   2737 {
   2738    if (!context->getExtensions().disjointTimerQueryEXT)
   2739    {
   2740        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2741        return false;
   2742    }
   2743    return ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, nullptr);
   2744 }
   2745 
   2746 bool ValidateGetQueryObjectui64vRobustANGLE(const Context *context,
   2747                                            angle::EntryPoint entryPoint,
   2748                                            QueryID id,
   2749                                            GLenum pname,
   2750                                            GLsizei bufSize,
   2751                                            const GLsizei *length,
   2752                                            GLuint64 *params)
   2753 {
   2754    if (!context->getExtensions().disjointTimerQueryEXT)
   2755    {
   2756        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2757        return false;
   2758    }
   2759 
   2760    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   2761    {
   2762        return false;
   2763    }
   2764 
   2765    GLsizei numParams = 0;
   2766 
   2767    if (!ValidateGetQueryObjectValueBase(context, entryPoint, id, pname, &numParams))
   2768    {
   2769        return false;
   2770    }
   2771 
   2772    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   2773    {
   2774        return false;
   2775    }
   2776 
   2777    SetRobustLengthParam(length, numParams);
   2778 
   2779    return true;
   2780 }
   2781 
   2782 bool ValidateUniformCommonBase(const Context *context,
   2783                               angle::EntryPoint entryPoint,
   2784                               const Program *program,
   2785                               UniformLocation location,
   2786                               GLsizei count,
   2787                               const LinkedUniform **uniformOut)
   2788 {
   2789    // TODO(Jiajia): Add image uniform check in future.
   2790    if (count < 0)
   2791    {
   2792        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   2793        return false;
   2794    }
   2795 
   2796    if (!program)
   2797    {
   2798        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidProgramName);
   2799        return false;
   2800    }
   2801 
   2802    if (!program->isLinked())
   2803    {
   2804        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   2805        return false;
   2806    }
   2807 
   2808    if (location.value == -1)
   2809    {
   2810        // Silently ignore the uniform command
   2811        return false;
   2812    }
   2813 
   2814    const auto &uniformLocations = program->getUniformLocations();
   2815    size_t castedLocation        = static_cast<size_t>(location.value);
   2816    if (castedLocation >= uniformLocations.size())
   2817    {
   2818        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation);
   2819        return false;
   2820    }
   2821 
   2822    const auto &uniformLocation = uniformLocations[castedLocation];
   2823    if (uniformLocation.ignored)
   2824    {
   2825        // Silently ignore the uniform command
   2826        return false;
   2827    }
   2828 
   2829    if (!uniformLocation.used())
   2830    {
   2831        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation);
   2832        return false;
   2833    }
   2834 
   2835    const auto &uniform = program->getUniformByIndex(uniformLocation.index);
   2836 
   2837    // attempting to write an array to a non-array uniform is an INVALID_OPERATION
   2838    if (count > 1 && !uniform.isArray())
   2839    {
   2840        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformCount);
   2841        return false;
   2842    }
   2843 
   2844    *uniformOut = &uniform;
   2845    return true;
   2846 }
   2847 
   2848 bool ValidateUniform1ivValue(const Context *context,
   2849                             angle::EntryPoint entryPoint,
   2850                             GLenum uniformType,
   2851                             GLsizei count,
   2852                             const GLint *value)
   2853 {
   2854    // Value type is GL_INT, because we only get here from glUniform1i{v}.
   2855    // It is compatible with INT or BOOL.
   2856    // Do these cheap tests first, for a little extra speed.
   2857    if (GL_INT == uniformType || GL_BOOL == uniformType)
   2858    {
   2859        return true;
   2860    }
   2861 
   2862    if (IsSamplerType(uniformType))
   2863    {
   2864        // Check that the values are in range.
   2865        const GLint max = context->getCaps().maxCombinedTextureImageUnits;
   2866        for (GLsizei i = 0; i < count; ++i)
   2867        {
   2868            if (value[i] < 0 || value[i] >= max)
   2869            {
   2870                context->validationError(entryPoint, GL_INVALID_VALUE,
   2871                                         kSamplerUniformValueOutOfRange);
   2872                return false;
   2873            }
   2874        }
   2875        return true;
   2876    }
   2877 
   2878    context->validationError(entryPoint, GL_INVALID_OPERATION, kUniformTypeMismatch);
   2879    return false;
   2880 }
   2881 
   2882 bool ValidateUniformMatrixValue(const Context *context,
   2883                                angle::EntryPoint entryPoint,
   2884                                GLenum valueType,
   2885                                GLenum uniformType)
   2886 {
   2887    // Check that the value type is compatible with uniform type.
   2888    if (valueType == uniformType)
   2889    {
   2890        return true;
   2891    }
   2892 
   2893    context->validationError(entryPoint, GL_INVALID_OPERATION, kUniformTypeMismatch);
   2894    return false;
   2895 }
   2896 
   2897 bool ValidateUniform(const Context *context,
   2898                     angle::EntryPoint entryPoint,
   2899                     GLenum valueType,
   2900                     UniformLocation location,
   2901                     GLsizei count)
   2902 {
   2903    const LinkedUniform *uniform = nullptr;
   2904    Program *programObject       = context->getActiveLinkedProgram();
   2905    return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
   2906                                     &uniform) &&
   2907           ValidateUniformValue(context, entryPoint, valueType, uniform->type);
   2908 }
   2909 
   2910 bool ValidateUniform1iv(const Context *context,
   2911                        angle::EntryPoint entryPoint,
   2912                        UniformLocation location,
   2913                        GLsizei count,
   2914                        const GLint *value)
   2915 {
   2916    const LinkedUniform *uniform = nullptr;
   2917    Program *programObject       = context->getActiveLinkedProgram();
   2918    return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
   2919                                     &uniform) &&
   2920           ValidateUniform1ivValue(context, entryPoint, uniform->type, count, value);
   2921 }
   2922 
   2923 bool ValidateUniformMatrix(const Context *context,
   2924                           angle::EntryPoint entryPoint,
   2925                           GLenum valueType,
   2926                           UniformLocation location,
   2927                           GLsizei count,
   2928                           GLboolean transpose)
   2929 {
   2930    if (ConvertToBool(transpose) && context->getClientMajorVersion() < 3)
   2931    {
   2932        context->validationError(entryPoint, GL_INVALID_VALUE, kES3Required);
   2933        return false;
   2934    }
   2935 
   2936    const LinkedUniform *uniform = nullptr;
   2937    Program *programObject       = context->getActiveLinkedProgram();
   2938    return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
   2939                                     &uniform) &&
   2940           ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->type);
   2941 }
   2942 
   2943 bool ValidateStateQuery(const Context *context,
   2944                        angle::EntryPoint entryPoint,
   2945                        GLenum pname,
   2946                        GLenum *nativeType,
   2947                        unsigned int *numParams)
   2948 {
   2949    if (!context->getQueryParameterInfo(pname, nativeType, numParams))
   2950    {
   2951        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   2952        return false;
   2953    }
   2954 
   2955    const Caps &caps = context->getCaps();
   2956 
   2957    if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
   2958    {
   2959        int colorAttachment = (pname - GL_DRAW_BUFFER0);
   2960 
   2961        if (colorAttachment >= caps.maxDrawBuffers)
   2962        {
   2963            context->validationError(entryPoint, GL_INVALID_OPERATION, kIndexExceedsMaxDrawBuffer);
   2964            return false;
   2965        }
   2966    }
   2967 
   2968    switch (pname)
   2969    {
   2970        case GL_TEXTURE_BINDING_2D:
   2971        case GL_TEXTURE_BINDING_CUBE_MAP:
   2972        case GL_TEXTURE_BINDING_3D:
   2973        case GL_TEXTURE_BINDING_2D_ARRAY:
   2974        case GL_TEXTURE_BINDING_2D_MULTISAMPLE:
   2975            break;
   2976        case GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY:
   2977            if (!context->getExtensions().textureStorageMultisample2dArrayOES)
   2978            {
   2979                context->validationError(entryPoint, GL_INVALID_ENUM,
   2980                                         kMultisampleArrayExtensionRequired);
   2981                return false;
   2982            }
   2983            break;
   2984        case GL_TEXTURE_BINDING_RECTANGLE_ANGLE:
   2985            if (!context->getExtensions().textureRectangleANGLE)
   2986            {
   2987                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   2988                return false;
   2989            }
   2990            break;
   2991        case GL_TEXTURE_BINDING_EXTERNAL_OES:
   2992            if (!context->getExtensions().EGLStreamConsumerExternalNV &&
   2993                !context->getExtensions().EGLImageExternalOES)
   2994            {
   2995                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   2996                return false;
   2997            }
   2998            break;
   2999        case GL_TEXTURE_BUFFER_BINDING:
   3000        case GL_TEXTURE_BINDING_BUFFER:
   3001        case GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
   3002        case GL_MAX_TEXTURE_BUFFER_SIZE:
   3003            if (context->getClientVersion() < Version(3, 2) &&
   3004                !context->getExtensions().textureBufferAny())
   3005            {
   3006                context->validationError(entryPoint, GL_INVALID_ENUM,
   3007                                         kTextureBufferExtensionNotAvailable);
   3008                return false;
   3009            }
   3010            break;
   3011 
   3012        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
   3013        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
   3014        {
   3015            Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
   3016            ASSERT(readFramebuffer);
   3017 
   3018            if (!ValidateFramebufferComplete<GL_INVALID_OPERATION>(context, entryPoint,
   3019                                                                   readFramebuffer))
   3020            {
   3021                return false;
   3022            }
   3023 
   3024            if (readFramebuffer->getReadBufferState() == GL_NONE)
   3025            {
   3026                context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone);
   3027                return false;
   3028            }
   3029 
   3030            const FramebufferAttachment *attachment = readFramebuffer->getReadColorAttachment();
   3031            if (!attachment)
   3032            {
   3033                context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNotAttached);
   3034                return false;
   3035            }
   3036        }
   3037        break;
   3038 
   3039        case GL_PRIMITIVE_BOUNDING_BOX:
   3040            if (!context->getExtensions().primitiveBoundingBoxAny())
   3041            {
   3042                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   3043                return false;
   3044            }
   3045            break;
   3046 
   3047        case GL_SHADING_RATE_QCOM:
   3048            if (!context->getExtensions().shadingRateQCOM)
   3049            {
   3050                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   3051                return false;
   3052            }
   3053            break;
   3054 
   3055        default:
   3056            break;
   3057    }
   3058 
   3059    // pname is valid, but there are no parameters to return
   3060    if (*numParams == 0)
   3061    {
   3062        return false;
   3063    }
   3064 
   3065    return true;
   3066 }
   3067 
   3068 bool ValidateGetBooleanvRobustANGLE(const Context *context,
   3069                                    angle::EntryPoint entryPoint,
   3070                                    GLenum pname,
   3071                                    GLsizei bufSize,
   3072                                    const GLsizei *length,
   3073                                    const GLboolean *params)
   3074 {
   3075    GLenum nativeType;
   3076    unsigned int numParams = 0;
   3077 
   3078    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
   3079    {
   3080        return false;
   3081    }
   3082 
   3083    SetRobustLengthParam(length, numParams);
   3084 
   3085    return true;
   3086 }
   3087 
   3088 bool ValidateGetFloatvRobustANGLE(const Context *context,
   3089                                  angle::EntryPoint entryPoint,
   3090                                  GLenum pname,
   3091                                  GLsizei bufSize,
   3092                                  const GLsizei *length,
   3093                                  const GLfloat *params)
   3094 {
   3095    GLenum nativeType;
   3096    unsigned int numParams = 0;
   3097 
   3098    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
   3099    {
   3100        return false;
   3101    }
   3102 
   3103    SetRobustLengthParam(length, numParams);
   3104 
   3105    return true;
   3106 }
   3107 
   3108 bool ValidateGetIntegervRobustANGLE(const Context *context,
   3109                                    angle::EntryPoint entryPoint,
   3110                                    GLenum pname,
   3111                                    GLsizei bufSize,
   3112                                    const GLsizei *length,
   3113                                    const GLint *data)
   3114 {
   3115    GLenum nativeType;
   3116    unsigned int numParams = 0;
   3117 
   3118    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
   3119    {
   3120        return false;
   3121    }
   3122 
   3123    SetRobustLengthParam(length, numParams);
   3124 
   3125    return true;
   3126 }
   3127 
   3128 bool ValidateGetInteger64vRobustANGLE(const Context *context,
   3129                                      angle::EntryPoint entryPoint,
   3130                                      GLenum pname,
   3131                                      GLsizei bufSize,
   3132                                      const GLsizei *length,
   3133                                      GLint64 *data)
   3134 {
   3135    GLenum nativeType;
   3136    unsigned int numParams = 0;
   3137 
   3138    if (!ValidateRobustStateQuery(context, entryPoint, pname, bufSize, &nativeType, &numParams))
   3139    {
   3140        return false;
   3141    }
   3142 
   3143    if (nativeType == GL_INT_64_ANGLEX)
   3144    {
   3145        CastStateValues(context, nativeType, pname, numParams, data);
   3146        return false;
   3147    }
   3148 
   3149    SetRobustLengthParam(length, numParams);
   3150    return true;
   3151 }
   3152 
   3153 bool ValidateRobustStateQuery(const Context *context,
   3154                              angle::EntryPoint entryPoint,
   3155                              GLenum pname,
   3156                              GLsizei bufSize,
   3157                              GLenum *nativeType,
   3158                              unsigned int *numParams)
   3159 {
   3160    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   3161    {
   3162        return false;
   3163    }
   3164 
   3165    if (!ValidateStateQuery(context, entryPoint, pname, nativeType, numParams))
   3166    {
   3167        return false;
   3168    }
   3169 
   3170    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, *numParams))
   3171    {
   3172        return false;
   3173    }
   3174 
   3175    return true;
   3176 }
   3177 
   3178 bool ValidateCopyImageSubDataTarget(const Context *context,
   3179                                    angle::EntryPoint entryPoint,
   3180                                    GLuint name,
   3181                                    GLenum target)
   3182 {
   3183    // From EXT_copy_image: INVALID_ENUM is generated if either <srcTarget> or <dstTarget> is not
   3184    // RENDERBUFFER or a valid non - proxy texture target, is TEXTURE_BUFFER, or is one of the
   3185    // cubemap face selectors described in table 3.17, or if the target does not match the type of
   3186    // the object. INVALID_VALUE is generated if either <srcName> or <dstName> does not correspond
   3187    // to a valid renderbuffer or texture object according to the corresponding target parameter.
   3188    switch (target)
   3189    {
   3190        case GL_RENDERBUFFER:
   3191        {
   3192            RenderbufferID renderbuffer = PackParam<RenderbufferID>(name);
   3193            if (!context->isRenderbuffer(renderbuffer))
   3194            {
   3195                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidRenderbufferName);
   3196                return false;
   3197            }
   3198            break;
   3199        }
   3200        case GL_TEXTURE_2D:
   3201        case GL_TEXTURE_3D:
   3202        case GL_TEXTURE_2D_ARRAY:
   3203        case GL_TEXTURE_CUBE_MAP:
   3204        case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
   3205        {
   3206            TextureID texture = PackParam<TextureID>(name);
   3207            if (!context->isTexture(texture))
   3208            {
   3209                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName);
   3210                return false;
   3211            }
   3212 
   3213            Texture *textureObject = context->getTexture(texture);
   3214            if (textureObject && textureObject->getType() != PackParam<TextureType>(target))
   3215            {
   3216                context->validationError(entryPoint, GL_INVALID_ENUM, err::kTextureTypeMismatch);
   3217                return false;
   3218            }
   3219            break;
   3220        }
   3221        default:
   3222            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
   3223            return false;
   3224    }
   3225 
   3226    return true;
   3227 }
   3228 
   3229 bool ValidateCopyImageSubDataLevel(const Context *context,
   3230                                   angle::EntryPoint entryPoint,
   3231                                   GLenum target,
   3232                                   GLint level)
   3233 {
   3234    switch (target)
   3235    {
   3236        case GL_RENDERBUFFER:
   3237        {
   3238            if (level != 0)
   3239            {
   3240                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   3241                return false;
   3242            }
   3243            break;
   3244        }
   3245        case GL_TEXTURE_2D:
   3246        case GL_TEXTURE_3D:
   3247        case GL_TEXTURE_2D_ARRAY:
   3248        case GL_TEXTURE_CUBE_MAP:
   3249        case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
   3250        {
   3251            if (!ValidMipLevel(context, PackParam<TextureType>(target), level))
   3252            {
   3253                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   3254                return false;
   3255            }
   3256            break;
   3257        }
   3258        default:
   3259            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
   3260            return false;
   3261    }
   3262 
   3263    return true;
   3264 }
   3265 
   3266 bool ValidateCopyImageSubDataTargetRegion(const Context *context,
   3267                                          angle::EntryPoint entryPoint,
   3268                                          GLuint name,
   3269                                          GLenum target,
   3270                                          GLint level,
   3271                                          GLint offsetX,
   3272                                          GLint offsetY,
   3273                                          GLint offsetZ,
   3274                                          GLsizei width,
   3275                                          GLsizei height,
   3276                                          GLsizei *samples)
   3277 {
   3278    // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
   3279    // of the corresponding image object.
   3280    if (offsetX < 0 || offsetY < 0 || offsetZ < 0)
   3281    {
   3282        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   3283        return false;
   3284    }
   3285 
   3286    if (target == GL_RENDERBUFFER)
   3287    {
   3288        // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
   3289        // boundaries of the corresponding image object
   3290        Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
   3291        if ((buffer->getWidth() - offsetX < width) || (buffer->getHeight() - offsetY < height))
   3292        {
   3293            context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
   3294            return false;
   3295        }
   3296    }
   3297    else
   3298    {
   3299        Texture *texture = context->getTexture(PackParam<TextureID>(name));
   3300 
   3301        // INVALID_OPERATION is generated if either object is a texture and the texture is not
   3302        // complete
   3303        // This will handle the texture completeness check. Note that this ignores format-based
   3304        // compleness rules.
   3305        if (!texture->isSamplerCompleteForCopyImage(context, nullptr))
   3306        {
   3307            context->validationError(entryPoint, GL_INVALID_OPERATION, kNotTextureComplete);
   3308            return false;
   3309        }
   3310 
   3311        GLenum textureTargetToUse = target;
   3312        if (target == GL_TEXTURE_CUBE_MAP)
   3313        {
   3314            // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the textureWidth/textureHeight
   3315            textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
   3316        }
   3317 
   3318        const GLsizei textureWidth = static_cast<GLsizei>(
   3319            texture->getWidth(PackParam<TextureTarget>(textureTargetToUse), level));
   3320        const GLsizei textureHeight = static_cast<GLsizei>(
   3321            texture->getHeight(PackParam<TextureTarget>(textureTargetToUse), level));
   3322 
   3323        // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the
   3324        // boundaries of the corresponding image object
   3325        if ((textureWidth - offsetX < width) || (textureHeight - offsetY < height))
   3326        {
   3327            context->validationError(entryPoint, GL_INVALID_VALUE, kSourceTextureTooSmall);
   3328            return false;
   3329        }
   3330 
   3331        *samples = texture->getSamples(PackParam<TextureTarget>(textureTargetToUse), level);
   3332        *samples = (*samples == 0) ? 1 : *samples;
   3333    }
   3334 
   3335    return true;
   3336 }
   3337 
   3338 bool ValidateCompressedRegion(const Context *context,
   3339                              angle::EntryPoint entryPoint,
   3340                              const InternalFormat &formatInfo,
   3341                              GLsizei width,
   3342                              GLsizei height)
   3343 {
   3344    ASSERT(formatInfo.compressed);
   3345 
   3346    // INVALID_VALUE is generated if the image format is compressed and the dimensions of the
   3347    // subregion fail to meet the alignment constraints of the format.
   3348    if ((width % formatInfo.compressedBlockWidth != 0) ||
   3349        (height % formatInfo.compressedBlockHeight != 0))
   3350    {
   3351        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidCompressedRegionSize);
   3352        return false;
   3353    }
   3354 
   3355    return true;
   3356 }
   3357 
   3358 const InternalFormat &GetTargetFormatInfo(const Context *context,
   3359                                          angle::EntryPoint entryPoint,
   3360                                          GLuint name,
   3361                                          GLenum target,
   3362                                          GLint level)
   3363 {
   3364    static const InternalFormat defaultInternalFormat;
   3365 
   3366    switch (target)
   3367    {
   3368        case GL_RENDERBUFFER:
   3369        {
   3370            Renderbuffer *buffer = context->getRenderbuffer(PackParam<RenderbufferID>(name));
   3371            return *buffer->getFormat().info;
   3372        }
   3373        case GL_TEXTURE_2D:
   3374        case GL_TEXTURE_3D:
   3375        case GL_TEXTURE_2D_ARRAY:
   3376        case GL_TEXTURE_CUBE_MAP:
   3377        case GL_TEXTURE_CUBE_MAP_ARRAY_EXT:
   3378        {
   3379            Texture *texture          = context->getTexture(PackParam<TextureID>(name));
   3380            GLenum textureTargetToUse = target;
   3381 
   3382            if (target == GL_TEXTURE_CUBE_MAP)
   3383            {
   3384                // Use GL_TEXTURE_CUBE_MAP_POSITIVE_X to properly gather the
   3385                // textureWidth/textureHeight
   3386                textureTargetToUse = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
   3387            }
   3388            return *texture->getFormat(PackParam<TextureTarget>(textureTargetToUse), level).info;
   3389        }
   3390        default:
   3391            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
   3392            return defaultInternalFormat;
   3393    }
   3394 }
   3395 
   3396 bool ValidateCopyMixedFormatCompatible(GLenum uncompressedFormat, GLenum compressedFormat)
   3397 {
   3398    // Validates mixed format compatibility (uncompressed and compressed) from Table 4.X.1 of the
   3399    // EXT_copy_image spec.
   3400    switch (compressedFormat)
   3401    {
   3402        case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
   3403        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
   3404        case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
   3405        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
   3406        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
   3407        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
   3408        case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
   3409        case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
   3410        case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
   3411        case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
   3412        case GL_COMPRESSED_RGBA8_ETC2_EAC:
   3413        case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
   3414        case GL_COMPRESSED_RG11_EAC:
   3415        case GL_COMPRESSED_SIGNED_RG11_EAC:
   3416        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
   3417        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
   3418        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
   3419        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
   3420        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
   3421        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
   3422        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
   3423        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
   3424        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
   3425        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
   3426        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
   3427        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
   3428        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
   3429        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
   3430        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR:
   3431        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR:
   3432        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR:
   3433        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR:
   3434        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR:
   3435        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR:
   3436        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR:
   3437        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR:
   3438        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR:
   3439        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR:
   3440        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR:
   3441        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR:
   3442        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR:
   3443        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR:
   3444        case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
   3445        case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
   3446        case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
   3447        case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
   3448        case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
   3449        case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
   3450        case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
   3451        case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
   3452        case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
   3453        case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
   3454        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES:
   3455        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES:
   3456        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES:
   3457        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES:
   3458        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES:
   3459        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES:
   3460        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES:
   3461        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES:
   3462        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES:
   3463        case GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES:
   3464        {
   3465            switch (uncompressedFormat)
   3466            {
   3467                case GL_RGBA32UI:
   3468                case GL_RGBA32I:
   3469                case GL_RGBA32F:
   3470                    return true;
   3471                default:
   3472                    return false;
   3473            }
   3474        }
   3475        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
   3476        case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
   3477        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
   3478        case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
   3479        case GL_COMPRESSED_RED_RGTC1_EXT:
   3480        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
   3481        case GL_COMPRESSED_RGB8_ETC2:
   3482        case GL_COMPRESSED_SRGB8_ETC2:
   3483        case GL_COMPRESSED_R11_EAC:
   3484        case GL_COMPRESSED_SIGNED_R11_EAC:
   3485        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
   3486        case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
   3487        {
   3488            switch (uncompressedFormat)
   3489            {
   3490                case GL_RGBA16UI:
   3491                case GL_RGBA16I:
   3492                case GL_RGBA16F:
   3493                case GL_RG32UI:
   3494                case GL_RG32I:
   3495                case GL_RG32F:
   3496                    return true;
   3497                default:
   3498                    return false;
   3499            }
   3500        }
   3501        default:
   3502            break;
   3503    }
   3504 
   3505    return false;
   3506 }
   3507 
   3508 bool ValidateCopyCompressedFormatCompatible(const InternalFormat &srcFormatInfo,
   3509                                            const InternalFormat &dstFormatInfo)
   3510 {
   3511    // Validates compressed format compatibility from Table 4.X.2 of the EXT_copy_image spec.
   3512 
   3513    ASSERT(srcFormatInfo.internalFormat != dstFormatInfo.internalFormat);
   3514 
   3515    const GLenum srcFormat = srcFormatInfo.internalFormat;
   3516    const GLenum dstFormat = dstFormatInfo.internalFormat;
   3517 
   3518    switch (srcFormat)
   3519    {
   3520        case GL_COMPRESSED_RED_RGTC1_EXT:
   3521            return (dstFormat == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT);
   3522        case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
   3523            return (dstFormat == GL_COMPRESSED_RED_RGTC1_EXT);
   3524        case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
   3525            return (dstFormat == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT);
   3526        case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
   3527            return (dstFormat == GL_COMPRESSED_RED_GREEN_RGTC2_EXT);
   3528        case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
   3529            return (dstFormat == GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT);
   3530        case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
   3531            return (dstFormat == GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT);
   3532        case GL_COMPRESSED_R11_EAC:
   3533            return (dstFormat == GL_COMPRESSED_SIGNED_R11_EAC);
   3534        case GL_COMPRESSED_SIGNED_R11_EAC:
   3535            return (dstFormat == GL_COMPRESSED_R11_EAC);
   3536        case GL_COMPRESSED_RG11_EAC:
   3537            return (dstFormat == GL_COMPRESSED_SIGNED_RG11_EAC);
   3538        case GL_COMPRESSED_SIGNED_RG11_EAC:
   3539            return (dstFormat == GL_COMPRESSED_RG11_EAC);
   3540        default:
   3541            break;
   3542    }
   3543 
   3544    // Since they can't be the same format and are both compressed formats, one must be linear and
   3545    // the other nonlinear.
   3546    if (srcFormatInfo.colorEncoding == dstFormatInfo.colorEncoding)
   3547    {
   3548        return false;
   3549    }
   3550 
   3551    const GLenum linearFormat = (srcFormatInfo.colorEncoding == GL_LINEAR) ? srcFormat : dstFormat;
   3552    const GLenum nonLinearFormat =
   3553        (srcFormatInfo.colorEncoding != GL_LINEAR) ? srcFormat : dstFormat;
   3554 
   3555    switch (linearFormat)
   3556    {
   3557        case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
   3558            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT);
   3559        case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
   3560            return (nonLinearFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT);
   3561        case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
   3562            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT);
   3563        case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
   3564            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT);
   3565        case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
   3566            return (nonLinearFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT);
   3567        case GL_COMPRESSED_RGB8_ETC2:
   3568            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ETC2);
   3569        case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
   3570            return (nonLinearFormat == GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2);
   3571        case GL_COMPRESSED_RGBA8_ETC2_EAC:
   3572            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC);
   3573        case GL_COMPRESSED_RGBA_ASTC_4x4_KHR:
   3574            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR);
   3575        case GL_COMPRESSED_RGBA_ASTC_5x4_KHR:
   3576            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR);
   3577        case GL_COMPRESSED_RGBA_ASTC_5x5_KHR:
   3578            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR);
   3579        case GL_COMPRESSED_RGBA_ASTC_6x5_KHR:
   3580            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR);
   3581        case GL_COMPRESSED_RGBA_ASTC_6x6_KHR:
   3582            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR);
   3583        case GL_COMPRESSED_RGBA_ASTC_8x5_KHR:
   3584            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR);
   3585        case GL_COMPRESSED_RGBA_ASTC_8x6_KHR:
   3586            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR);
   3587        case GL_COMPRESSED_RGBA_ASTC_8x8_KHR:
   3588            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR);
   3589        case GL_COMPRESSED_RGBA_ASTC_10x5_KHR:
   3590            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR);
   3591        case GL_COMPRESSED_RGBA_ASTC_10x6_KHR:
   3592            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR);
   3593        case GL_COMPRESSED_RGBA_ASTC_10x8_KHR:
   3594            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR);
   3595        case GL_COMPRESSED_RGBA_ASTC_10x10_KHR:
   3596            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR);
   3597        case GL_COMPRESSED_RGBA_ASTC_12x10_KHR:
   3598            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR);
   3599        case GL_COMPRESSED_RGBA_ASTC_12x12_KHR:
   3600            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR);
   3601        case GL_COMPRESSED_RGBA_ASTC_3x3x3_OES:
   3602            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES);
   3603        case GL_COMPRESSED_RGBA_ASTC_4x3x3_OES:
   3604            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES);
   3605        case GL_COMPRESSED_RGBA_ASTC_4x4x3_OES:
   3606            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES);
   3607        case GL_COMPRESSED_RGBA_ASTC_4x4x4_OES:
   3608            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES);
   3609        case GL_COMPRESSED_RGBA_ASTC_5x4x4_OES:
   3610            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES);
   3611        case GL_COMPRESSED_RGBA_ASTC_5x5x4_OES:
   3612            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES);
   3613        case GL_COMPRESSED_RGBA_ASTC_5x5x5_OES:
   3614            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES);
   3615        case GL_COMPRESSED_RGBA_ASTC_6x5x5_OES:
   3616            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES);
   3617        case GL_COMPRESSED_RGBA_ASTC_6x6x5_OES:
   3618            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES);
   3619        case GL_COMPRESSED_RGBA_ASTC_6x6x6_OES:
   3620            return (nonLinearFormat == GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES);
   3621        default:
   3622            break;
   3623    }
   3624 
   3625    return false;
   3626 }
   3627 
   3628 bool ValidateCopyFormatCompatible(const InternalFormat &srcFormatInfo,
   3629                                  const InternalFormat &dstFormatInfo)
   3630 {
   3631    // Matching source and destination formats are compatible.
   3632    if (srcFormatInfo.internalFormat == dstFormatInfo.internalFormat)
   3633    {
   3634        return true;
   3635    }
   3636 
   3637    if (srcFormatInfo.compressed != dstFormatInfo.compressed)
   3638    {
   3639        GLenum uncompressedFormat = (!srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
   3640                                                                : dstFormatInfo.internalFormat;
   3641        GLenum compressedFormat   = (srcFormatInfo.compressed) ? srcFormatInfo.internalFormat
   3642                                                               : dstFormatInfo.internalFormat;
   3643 
   3644        return ValidateCopyMixedFormatCompatible(uncompressedFormat, compressedFormat);
   3645    }
   3646 
   3647    if (!srcFormatInfo.compressed)
   3648    {
   3649        // Source and destination are uncompressed formats.
   3650        return (srcFormatInfo.pixelBytes == dstFormatInfo.pixelBytes);
   3651    }
   3652 
   3653    return ValidateCopyCompressedFormatCompatible(srcFormatInfo, dstFormatInfo);
   3654 }
   3655 
   3656 bool ValidateCopyImageSubDataBase(const Context *context,
   3657                                  angle::EntryPoint entryPoint,
   3658                                  GLuint srcName,
   3659                                  GLenum srcTarget,
   3660                                  GLint srcLevel,
   3661                                  GLint srcX,
   3662                                  GLint srcY,
   3663                                  GLint srcZ,
   3664                                  GLuint dstName,
   3665                                  GLenum dstTarget,
   3666                                  GLint dstLevel,
   3667                                  GLint dstX,
   3668                                  GLint dstY,
   3669                                  GLint dstZ,
   3670                                  GLsizei srcWidth,
   3671                                  GLsizei srcHeight,
   3672                                  GLsizei srcDepth)
   3673 {
   3674    // INVALID_VALUE is generated if the dimensions of the either subregion exceeds the boundaries
   3675    // of the corresponding image object
   3676    if ((srcWidth < 0) || (srcHeight < 0) || (srcDepth < 0))
   3677    {
   3678        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   3679        return false;
   3680    }
   3681 
   3682    if (!ValidateCopyImageSubDataTarget(context, entryPoint, srcName, srcTarget))
   3683    {
   3684        return false;
   3685    }
   3686    if (!ValidateCopyImageSubDataTarget(context, entryPoint, dstName, dstTarget))
   3687    {
   3688        return false;
   3689    }
   3690 
   3691    if (!ValidateCopyImageSubDataLevel(context, entryPoint, srcTarget, srcLevel))
   3692    {
   3693        return false;
   3694    }
   3695    if (!ValidateCopyImageSubDataLevel(context, entryPoint, dstTarget, dstLevel))
   3696    {
   3697        return false;
   3698    }
   3699 
   3700    const InternalFormat &srcFormatInfo =
   3701        GetTargetFormatInfo(context, entryPoint, srcName, srcTarget, srcLevel);
   3702    const InternalFormat &dstFormatInfo =
   3703        GetTargetFormatInfo(context, entryPoint, dstName, dstTarget, dstLevel);
   3704    GLsizei dstWidth   = srcWidth;
   3705    GLsizei dstHeight  = srcHeight;
   3706    GLsizei srcSamples = 1;
   3707    GLsizei dstSamples = 1;
   3708 
   3709    if (srcFormatInfo.internalFormat == GL_NONE || dstFormatInfo.internalFormat == GL_NONE)
   3710    {
   3711        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureLevel);
   3712        return false;
   3713    }
   3714 
   3715    if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, srcName, srcTarget, srcLevel,
   3716                                              srcX, srcY, srcZ, srcWidth, srcHeight, &srcSamples))
   3717    {
   3718        return false;
   3719    }
   3720 
   3721    // When copying from a compressed image to an uncompressed image the image texel dimensions
   3722    // written to the uncompressed image will be source extent divided by the compressed texel block
   3723    // dimensions.
   3724    if ((srcFormatInfo.compressed) && (!dstFormatInfo.compressed))
   3725    {
   3726        ASSERT(srcFormatInfo.compressedBlockWidth != 0);
   3727        ASSERT(srcFormatInfo.compressedBlockHeight != 0);
   3728 
   3729        dstWidth /= srcFormatInfo.compressedBlockWidth;
   3730        dstHeight /= srcFormatInfo.compressedBlockHeight;
   3731    }
   3732    // When copying from an uncompressed image to a compressed image the image texel dimensions
   3733    // written to the compressed image will be the source extent multiplied by the compressed texel
   3734    // block dimensions.
   3735    else if ((!srcFormatInfo.compressed) && (dstFormatInfo.compressed))
   3736    {
   3737        dstWidth *= dstFormatInfo.compressedBlockWidth;
   3738        dstHeight *= dstFormatInfo.compressedBlockHeight;
   3739    }
   3740 
   3741    if (!ValidateCopyImageSubDataTargetRegion(context, entryPoint, dstName, dstTarget, dstLevel,
   3742                                              dstX, dstY, dstZ, dstWidth, dstHeight, &dstSamples))
   3743    {
   3744        return false;
   3745    }
   3746 
   3747    bool fillsEntireMip               = false;
   3748    gl::Texture *dstTexture           = context->getTexture({dstName});
   3749    gl::TextureTarget dstTargetPacked = gl::PackParam<gl::TextureTarget>(dstTarget);
   3750    // TODO(http://anglebug.com/5643): Some targets (e.g., GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER) are
   3751    // unsupported when used with compressed formats due to gl::PackParam() returning
   3752    // TextureTarget::InvalidEnum.
   3753    if (dstTargetPacked != gl::TextureTarget::InvalidEnum)
   3754    {
   3755        const gl::Extents &dstExtents = dstTexture->getExtents(dstTargetPacked, dstLevel);
   3756        fillsEntireMip = dstX == 0 && dstY == 0 && dstZ == 0 && srcWidth == dstExtents.width &&
   3757                         srcHeight == dstExtents.height && srcDepth == dstExtents.depth;
   3758    }
   3759 
   3760    if (srcFormatInfo.compressed && !fillsEntireMip &&
   3761        !ValidateCompressedRegion(context, entryPoint, srcFormatInfo, srcWidth, srcHeight))
   3762    {
   3763        return false;
   3764    }
   3765 
   3766    if (dstFormatInfo.compressed && !fillsEntireMip &&
   3767        !ValidateCompressedRegion(context, entryPoint, dstFormatInfo, dstWidth, dstHeight))
   3768    {
   3769        return false;
   3770    }
   3771 
   3772    // From EXT_copy_image: INVALID_OPERATION is generated if the source and destination formats
   3773    // are not compatible, if one image is compressed and the other is uncompressed and the block
   3774    // size of compressed image is not equal to the texel size of the compressed image.
   3775    if (!ValidateCopyFormatCompatible(srcFormatInfo, dstFormatInfo))
   3776    {
   3777        context->validationError(entryPoint, GL_INVALID_OPERATION, kIncompatibleTextures);
   3778        return false;
   3779    }
   3780 
   3781    // INVALID_OPERATION is generated if the source and destination number of samples do not match
   3782    if (srcSamples != dstSamples)
   3783    {
   3784        context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
   3785        return false;
   3786    }
   3787 
   3788    return true;
   3789 }
   3790 
   3791 bool ValidateCopyTexImageParametersBase(const Context *context,
   3792                                        angle::EntryPoint entryPoint,
   3793                                        TextureTarget target,
   3794                                        GLint level,
   3795                                        GLenum internalformat,
   3796                                        bool isSubImage,
   3797                                        GLint xoffset,
   3798                                        GLint yoffset,
   3799                                        GLint zoffset,
   3800                                        GLint x,
   3801                                        GLint y,
   3802                                        GLsizei width,
   3803                                        GLsizei height,
   3804                                        GLint border,
   3805                                        Format *textureFormatOut)
   3806 {
   3807    TextureType texType = TextureTargetToType(target);
   3808 
   3809    if (xoffset < 0 || yoffset < 0 || zoffset < 0)
   3810    {
   3811        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   3812        return false;
   3813    }
   3814 
   3815    if (width < 0 || height < 0)
   3816    {
   3817        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   3818        return false;
   3819    }
   3820 
   3821    if (std::numeric_limits<GLsizei>::max() - xoffset < width ||
   3822        std::numeric_limits<GLsizei>::max() - yoffset < height)
   3823    {
   3824        context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
   3825        return false;
   3826    }
   3827 
   3828    if (std::numeric_limits<GLint>::max() - width < x ||
   3829        std::numeric_limits<GLint>::max() - height < y)
   3830    {
   3831        context->validationError(entryPoint, GL_INVALID_VALUE, kIntegerOverflow);
   3832        return false;
   3833    }
   3834 
   3835    if (border != 0)
   3836    {
   3837        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidBorder);
   3838        return false;
   3839    }
   3840 
   3841    if (!ValidMipLevel(context, texType, level))
   3842    {
   3843        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   3844        return false;
   3845    }
   3846 
   3847    const State &state           = context->getState();
   3848    Framebuffer *readFramebuffer = state.getReadFramebuffer();
   3849    if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
   3850    {
   3851        return false;
   3852    }
   3853 
   3854    // checkReadBufferResourceSamples = true. Treat renderToTexture textures as single sample since
   3855    // they will be resolved before copying.
   3856    if (!readFramebuffer->isDefault() &&
   3857        !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
   3858    {
   3859        return false;
   3860    }
   3861 
   3862    if (readFramebuffer->getReadBufferState() == GL_NONE)
   3863    {
   3864        context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone);
   3865        return false;
   3866    }
   3867 
   3868    // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
   3869    // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
   3870    // attachment and WebGL defines it to be an error. We do the check unconditionally as the
   3871    // situation is an application error that would lead to a crash in ANGLE.
   3872    const FramebufferAttachment *source = readFramebuffer->getReadColorAttachment();
   3873    if (source == nullptr)
   3874    {
   3875        context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingReadAttachment);
   3876        return false;
   3877    }
   3878 
   3879    if (source->isYUV())
   3880    {
   3881        context->validationError(entryPoint, GL_INVALID_OPERATION, kCopyFromYUVFramebuffer);
   3882        return false;
   3883    }
   3884 
   3885    // ANGLE_multiview spec, Revision 1:
   3886    // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
   3887    // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
   3888    // is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
   3889    // framebuffer is more than one.
   3890    if (readFramebuffer->readDisallowedByMultiview())
   3891    {
   3892        context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
   3893                                 kMultiviewReadFramebuffer);
   3894        return false;
   3895    }
   3896 
   3897    const Caps &caps = context->getCaps();
   3898 
   3899    GLint maxDimension = 0;
   3900    switch (texType)
   3901    {
   3902        case TextureType::_2D:
   3903            maxDimension = caps.max2DTextureSize;
   3904            break;
   3905 
   3906        case TextureType::CubeMap:
   3907        case TextureType::CubeMapArray:
   3908            maxDimension = caps.maxCubeMapTextureSize;
   3909            break;
   3910 
   3911        case TextureType::Rectangle:
   3912            maxDimension = caps.maxRectangleTextureSize;
   3913            break;
   3914 
   3915        case TextureType::_2DArray:
   3916            maxDimension = caps.max2DTextureSize;
   3917            break;
   3918 
   3919        case TextureType::_3D:
   3920            maxDimension = caps.max3DTextureSize;
   3921            break;
   3922 
   3923        default:
   3924            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   3925            return false;
   3926    }
   3927 
   3928    Texture *texture = state.getTargetTexture(texType);
   3929    if (!texture)
   3930    {
   3931        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureNotBound);
   3932        return false;
   3933    }
   3934 
   3935    if (texture->getImmutableFormat() && !isSubImage)
   3936    {
   3937        context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureIsImmutable);
   3938        return false;
   3939    }
   3940 
   3941    const InternalFormat &formatInfo =
   3942        isSubImage ? *texture->getFormat(target, level).info
   3943                   : GetInternalFormatInfo(internalformat, GL_UNSIGNED_BYTE);
   3944 
   3945    if (formatInfo.depthBits > 0 || formatInfo.compressed)
   3946    {
   3947        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFormat);
   3948        return false;
   3949    }
   3950 
   3951    if (isSubImage)
   3952    {
   3953        if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
   3954            static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
   3955            static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
   3956        {
   3957            context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetOverflow);
   3958            return false;
   3959        }
   3960    }
   3961    else
   3962    {
   3963        if ((texType == TextureType::CubeMap || texType == TextureType::CubeMapArray) &&
   3964            width != height)
   3965        {
   3966            context->validationError(entryPoint, GL_INVALID_VALUE, kCubemapIncomplete);
   3967            return false;
   3968        }
   3969 
   3970        if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions()))
   3971        {
   3972            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   3973                                      internalformat);
   3974            return false;
   3975        }
   3976 
   3977        int maxLevelDimension = (maxDimension >> level);
   3978        if (static_cast<int>(width) > maxLevelDimension ||
   3979            static_cast<int>(height) > maxLevelDimension)
   3980        {
   3981            context->validationError(entryPoint, GL_INVALID_VALUE, kResourceMaxTextureSize);
   3982            return false;
   3983        }
   3984    }
   3985 
   3986    // Do not leak the previous texture format for non-subImage case.
   3987    if (textureFormatOut && isSubImage)
   3988    {
   3989        *textureFormatOut = texture->getFormat(target, level);
   3990    }
   3991 
   3992    // Detect texture copying feedback loops for WebGL.
   3993    if (context->isWebGL())
   3994    {
   3995        if (readFramebuffer->formsCopyingFeedbackLoopWith(texture->id(), level, zoffset))
   3996        {
   3997            context->validationError(entryPoint, GL_INVALID_OPERATION, kFeedbackLoop);
   3998            return false;
   3999        }
   4000    }
   4001 
   4002    return true;
   4003 }
   4004 
   4005 const char *ValidateProgramPipelineDrawStates(const Context *context,
   4006                                              const Extensions &extensions,
   4007                                              ProgramPipeline *programPipeline)
   4008 {
   4009    for (const ShaderType shaderType : gl::AllShaderTypes())
   4010    {
   4011        Program *program = programPipeline->getShaderProgram(shaderType);
   4012        if (program)
   4013        {
   4014            const char *errorMsg = ValidateProgramDrawStates(context, extensions, program);
   4015            if (errorMsg)
   4016            {
   4017                return errorMsg;
   4018            }
   4019        }
   4020    }
   4021 
   4022    return nullptr;
   4023 }
   4024 
   4025 const char *ValidateProgramPipelineAttachedPrograms(ProgramPipeline *programPipeline)
   4026 {
   4027    // An INVALID_OPERATION error is generated by any command that transfers vertices to the
   4028    // GL or launches compute work if the current set of active
   4029    // program objects cannot be executed, for reasons including:
   4030    // - There is no current program object specified by UseProgram, there is a current program
   4031    //    pipeline object, and that object is empty (no executable code is installed for any stage).
   4032    // - A program object is active for at least one, but not all of the shader
   4033    // stages that were present when the program was linked.
   4034    if (!programPipeline->getExecutable().getLinkedShaderStages().any())
   4035    {
   4036        return gl::err::kNoExecutableCodeInstalled;
   4037    }
   4038    for (const ShaderType shaderType : gl::AllShaderTypes())
   4039    {
   4040        Program *shaderProgram = programPipeline->getShaderProgram(shaderType);
   4041        if (shaderProgram)
   4042        {
   4043            ProgramExecutable &executable = shaderProgram->getExecutable();
   4044            for (const ShaderType programShaderType : executable.getLinkedShaderStages())
   4045            {
   4046                if (shaderProgram != programPipeline->getShaderProgram(programShaderType))
   4047                {
   4048                    return gl::err::kNotAllStagesOfSeparableProgramUsed;
   4049                }
   4050            }
   4051        }
   4052    }
   4053 
   4054    // [EXT_geometry_shader] Section 11.1.gs Geometry Shaders
   4055    // A non-separable program object or program pipeline object that includes
   4056    // a geometry shader must also include a vertex shader.
   4057    // An INVALID_OPERATION error is generated by any command that transfers
   4058    // vertices to the GL if the current program state has a geometry shader
   4059    // but no vertex shader.
   4060    if (!programPipeline->getShaderProgram(ShaderType::Vertex) &&
   4061        programPipeline->getShaderProgram(ShaderType::Geometry))
   4062    {
   4063        return gl::err::kNoActiveGraphicsShaderStage;
   4064    }
   4065 
   4066    return nullptr;
   4067 }
   4068 
   4069 // Note all errors returned from this function are INVALID_OPERATION except for the draw framebuffer
   4070 // completeness check.
   4071 const char *ValidateDrawStates(const Context *context)
   4072 {
   4073    const Extensions &extensions = context->getExtensions();
   4074    const State &state           = context->getState();
   4075 
   4076    // WebGL buffers cannot be mapped/unmapped because the MapBufferRange, FlushMappedBufferRange,
   4077    // and UnmapBuffer entry points are removed from the WebGL 2.0 API.
   4078    // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.14
   4079    VertexArray *vertexArray = state.getVertexArray();
   4080    ASSERT(vertexArray);
   4081 
   4082    if (!extensions.webglCompatibilityANGLE && vertexArray->hasInvalidMappedArrayBuffer())
   4083    {
   4084        return kBufferMapped;
   4085    }
   4086 
   4087    // Note: these separate values are not supported in WebGL, due to D3D's limitations. See
   4088    // Section 6.10 of the WebGL 1.0 spec.
   4089    Framebuffer *framebuffer = state.getDrawFramebuffer();
   4090    ASSERT(framebuffer);
   4091 
   4092    if (context->getLimitations().noSeparateStencilRefsAndMasks ||
   4093        extensions.webglCompatibilityANGLE)
   4094    {
   4095        ASSERT(framebuffer);
   4096        const FramebufferAttachment *dsAttachment =
   4097            framebuffer->getStencilOrDepthStencilAttachment();
   4098        const GLuint stencilBits = dsAttachment ? dsAttachment->getStencilSize() : 0;
   4099        ASSERT(stencilBits <= 8);
   4100 
   4101        const DepthStencilState &depthStencilState = state.getDepthStencilState();
   4102        if (depthStencilState.stencilTest && stencilBits > 0)
   4103        {
   4104            GLuint maxStencilValue = (1 << stencilBits) - 1;
   4105 
   4106            bool differentRefs =
   4107                clamp(state.getStencilRef(), 0, static_cast<GLint>(maxStencilValue)) !=
   4108                clamp(state.getStencilBackRef(), 0, static_cast<GLint>(maxStencilValue));
   4109            bool differentWritemasks = (depthStencilState.stencilWritemask & maxStencilValue) !=
   4110                                       (depthStencilState.stencilBackWritemask & maxStencilValue);
   4111            bool differentMasks = (depthStencilState.stencilMask & maxStencilValue) !=
   4112                                  (depthStencilState.stencilBackMask & maxStencilValue);
   4113 
   4114            if (differentRefs || differentWritemasks || differentMasks)
   4115            {
   4116                if (!extensions.webglCompatibilityANGLE)
   4117                {
   4118                    WARN() << "This ANGLE implementation does not support separate front/back "
   4119                              "stencil writemasks, reference values, or stencil mask values.";
   4120                }
   4121                return kStencilReferenceMaskOrMismatch;
   4122            }
   4123        }
   4124    }
   4125 
   4126    if (!extensions.floatBlendEXT)
   4127    {
   4128        const DrawBufferMask blendEnabledActiveFloat32ColorAttachmentDrawBufferMask =
   4129            state.getBlendEnabledDrawBufferMask() &
   4130            framebuffer->getActiveFloat32ColorAttachmentDrawBufferMask();
   4131        if (blendEnabledActiveFloat32ColorAttachmentDrawBufferMask.any())
   4132        {
   4133            return kUnsupportedFloatBlending;
   4134        }
   4135    }
   4136 
   4137    if (context->getLimitations().noSimultaneousConstantColorAndAlphaBlendFunc ||
   4138        extensions.webglCompatibilityANGLE)
   4139    {
   4140        if (state.hasSimultaneousConstantColorAndAlphaBlendFunc())
   4141        {
   4142            if (extensions.webglCompatibilityANGLE)
   4143            {
   4144                return kInvalidConstantColor;
   4145            }
   4146 
   4147            WARN() << kConstantColorAlphaLimitation;
   4148            return kConstantColorAlphaLimitation;
   4149        }
   4150    }
   4151 
   4152    if (!framebuffer->isComplete(context))
   4153    {
   4154        // Note: this error should be generated as INVALID_FRAMEBUFFER_OPERATION.
   4155        return kDrawFramebufferIncomplete;
   4156    }
   4157 
   4158    bool framebufferIsYUV = framebuffer->hasYUVAttachment();
   4159    if (framebufferIsYUV)
   4160    {
   4161        const BlendState &blendState = state.getBlendState();
   4162        if (!blendState.colorMaskRed || !blendState.colorMaskGreen || !blendState.colorMaskBlue)
   4163        {
   4164            // When rendering into a YUV framebuffer, the color mask must have r g and b set to
   4165            // true.
   4166            return kInvalidColorMaskForYUV;
   4167        }
   4168 
   4169        if (blendState.blend)
   4170        {
   4171            // When rendering into a YUV framebuffer, blending must be disabled.
   4172            return kInvalidBlendStateForYUV;
   4173        }
   4174    }
   4175    else
   4176    {
   4177        if (framebuffer->hasExternalTextureAttachment())
   4178        {
   4179            // It is an error to render into an external texture that is not YUV.
   4180            return kExternalTextureAttachmentNotYUV;
   4181        }
   4182    }
   4183 
   4184    // Advanced blend equation can only be enabled for a single render target.
   4185    const BlendStateExt &blendStateExt = state.getBlendStateExt();
   4186    if (blendStateExt.getUsesAdvancedBlendEquationMask().any())
   4187    {
   4188        const size_t drawBufferCount            = framebuffer->getDrawbufferStateCount();
   4189        uint32_t advancedBlendRenderTargetCount = 0;
   4190 
   4191        for (size_t drawBufferIndex : blendStateExt.getUsesAdvancedBlendEquationMask())
   4192        {
   4193            if (drawBufferIndex < drawBufferCount &&
   4194                framebuffer->getDrawBufferState(drawBufferIndex) != GL_NONE &&
   4195                blendStateExt.getEnabledMask().test(drawBufferIndex) &&
   4196                blendStateExt.getUsesAdvancedBlendEquationMask().test(drawBufferIndex))
   4197            {
   4198                ++advancedBlendRenderTargetCount;
   4199            }
   4200        }
   4201 
   4202        if (advancedBlendRenderTargetCount > 1)
   4203        {
   4204            return kAdvancedBlendEquationWithMRT;
   4205        }
   4206    }
   4207 
   4208    if (context->getStateCache().hasAnyEnabledClientAttrib())
   4209    {
   4210        if (extensions.webglCompatibilityANGLE || !state.areClientArraysEnabled())
   4211        {
   4212            // [WebGL 1.0] Section 6.5 Enabled Vertex Attributes and Range Checking
   4213            // If a vertex attribute is enabled as an array via enableVertexAttribArray but no
   4214            // buffer is bound to that attribute via bindBuffer and vertexAttribPointer, then calls
   4215            // to drawArrays or drawElements will generate an INVALID_OPERATION error.
   4216            return kVertexArrayNoBuffer;
   4217        }
   4218 
   4219        if (state.getVertexArray()->hasEnabledNullPointerClientArray())
   4220        {
   4221            // This is an application error that would normally result in a crash, but we catch it
   4222            // and return an error
   4223            return kVertexArrayNoBufferPointer;
   4224        }
   4225    }
   4226 
   4227    // If we are running GLES1, there is no current program.
   4228    if (context->getClientVersion() >= Version(2, 0))
   4229    {
   4230        Program *program                    = state.getLinkedProgram(context);
   4231        ProgramPipeline *programPipeline    = state.getLinkedProgramPipeline(context);
   4232        const ProgramExecutable *executable = state.getProgramExecutable();
   4233 
   4234        bool programIsYUVOutput = false;
   4235 
   4236        if (program)
   4237        {
   4238            const char *errorMsg = ValidateProgramDrawStates(context, extensions, program);
   4239            if (errorMsg)
   4240            {
   4241                return errorMsg;
   4242            }
   4243 
   4244            programIsYUVOutput = executable->isYUVOutput();
   4245        }
   4246        else if (programPipeline)
   4247        {
   4248            const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
   4249            if (errorMsg)
   4250            {
   4251                return errorMsg;
   4252            }
   4253 
   4254            errorMsg = ValidateProgramPipelineDrawStates(context, extensions, programPipeline);
   4255            if (errorMsg)
   4256            {
   4257                return errorMsg;
   4258            }
   4259 
   4260            if (!programPipeline->isLinked())
   4261            {
   4262                return kProgramPipelineLinkFailed;
   4263            }
   4264 
   4265            programIsYUVOutput = executable->isYUVOutput();
   4266        }
   4267 
   4268        if (executable)
   4269        {
   4270            if (!executable->validateSamplers(nullptr, context->getCaps()))
   4271            {
   4272                return kTextureTypeConflict;
   4273            }
   4274 
   4275            if (executable->hasLinkedTessellationShader())
   4276            {
   4277                if (!executable->hasLinkedShaderStage(ShaderType::Vertex))
   4278                {
   4279                    return kTessellationShaderRequiresVertexShader;
   4280                }
   4281 
   4282                if (!executable->hasLinkedShaderStage(ShaderType::TessControl) ||
   4283                    !executable->hasLinkedShaderStage(ShaderType::TessEvaluation))
   4284                {
   4285                    return kTessellationShaderRequiresBothControlAndEvaluation;
   4286                }
   4287            }
   4288 
   4289            if (state.isTransformFeedbackActive())
   4290            {
   4291                if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
   4292                {
   4293                    return kTransformFeedbackBufferMissing;
   4294                }
   4295            }
   4296        }
   4297 
   4298        if (programIsYUVOutput != framebufferIsYUV)
   4299        {
   4300            // Both the program and framebuffer must match in YUV output state.
   4301            return kYUVOutputMissmatch;
   4302        }
   4303 
   4304        if (!state.validateSamplerFormats())
   4305        {
   4306            return kSamplerFormatMismatch;
   4307        }
   4308 
   4309        // Do some additional WebGL-specific validation
   4310        if (extensions.webglCompatibilityANGLE)
   4311        {
   4312            const TransformFeedback *transformFeedbackObject = state.getCurrentTransformFeedback();
   4313            if (state.isTransformFeedbackActive() &&
   4314                transformFeedbackObject->buffersBoundForOtherUseInWebGL())
   4315            {
   4316                return kTransformFeedbackBufferDoubleBound;
   4317            }
   4318 
   4319            // Detect rendering feedback loops for WebGL.
   4320            if (framebuffer->formsRenderingFeedbackLoopWith(context))
   4321            {
   4322                return kFeedbackLoop;
   4323            }
   4324 
   4325            // Detect that the vertex shader input types match the attribute types
   4326            if (!ValidateVertexShaderAttributeTypeMatch(context))
   4327            {
   4328                return kVertexShaderTypeMismatch;
   4329            }
   4330 
   4331            if (!context->getState().getRasterizerState().rasterizerDiscard &&
   4332                !context->getState().allActiveDrawBufferChannelsMasked())
   4333            {
   4334                // Detect that if there's active color buffer without fragment shader output
   4335                if (!ValidateFragmentShaderColorBufferMaskMatch(context))
   4336                {
   4337                    return kDrawBufferMaskMismatch;
   4338                }
   4339 
   4340                // Detect that the color buffer types match the fragment shader output types
   4341                if (!ValidateFragmentShaderColorBufferTypeMatch(context))
   4342                {
   4343                    return kDrawBufferTypeMismatch;
   4344                }
   4345            }
   4346 
   4347            const VertexArray *vao = context->getState().getVertexArray();
   4348            if (vao->hasTransformFeedbackBindingConflict(context))
   4349            {
   4350                return kVertexBufferBoundForTransformFeedback;
   4351            }
   4352 
   4353            // Validate that we are rendering with a linked program.
   4354            if (!program->isLinked())
   4355            {
   4356                return kProgramNotLinked;
   4357            }
   4358        }
   4359    }
   4360 
   4361    return nullptr;
   4362 }
   4363 
   4364 const char *ValidateProgramPipeline(const Context *context)
   4365 {
   4366    const State &state = context->getState();
   4367    // If we are running GLES1, there is no current program.
   4368    if (context->getClientVersion() >= Version(2, 0))
   4369    {
   4370        ProgramPipeline *programPipeline = state.getProgramPipeline();
   4371        if (programPipeline)
   4372        {
   4373            const char *errorMsg = ValidateProgramPipelineAttachedPrograms(programPipeline);
   4374            if (errorMsg)
   4375            {
   4376                return errorMsg;
   4377            }
   4378        }
   4379    }
   4380    return nullptr;
   4381 }
   4382 
   4383 void RecordDrawModeError(const Context *context, angle::EntryPoint entryPoint, PrimitiveMode mode)
   4384 {
   4385    const State &state                      = context->getState();
   4386    TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
   4387    if (state.isTransformFeedbackActiveUnpaused())
   4388    {
   4389        if (!ValidateTransformFeedbackPrimitiveMode(context, entryPoint,
   4390                                                    curTransformFeedback->getPrimitiveMode(), mode))
   4391        {
   4392            context->validationError(entryPoint, GL_INVALID_OPERATION,
   4393                                     kInvalidDrawModeTransformFeedback);
   4394            return;
   4395        }
   4396    }
   4397 
   4398    const Extensions &extensions = context->getExtensions();
   4399 
   4400    switch (mode)
   4401    {
   4402        case PrimitiveMode::Points:
   4403        case PrimitiveMode::Lines:
   4404        case PrimitiveMode::LineLoop:
   4405        case PrimitiveMode::LineStrip:
   4406        case PrimitiveMode::Triangles:
   4407        case PrimitiveMode::TriangleStrip:
   4408        case PrimitiveMode::TriangleFan:
   4409            break;
   4410 
   4411        case PrimitiveMode::LinesAdjacency:
   4412        case PrimitiveMode::LineStripAdjacency:
   4413        case PrimitiveMode::TrianglesAdjacency:
   4414        case PrimitiveMode::TriangleStripAdjacency:
   4415            if (!extensions.geometryShaderAny() && context->getClientVersion() < ES_3_2)
   4416            {
   4417                context->validationError(entryPoint, GL_INVALID_ENUM,
   4418                                         kGeometryShaderExtensionNotEnabled);
   4419                return;
   4420            }
   4421            break;
   4422 
   4423        case PrimitiveMode::Patches:
   4424            if (!extensions.tessellationShaderEXT && context->getClientVersion() < ES_3_2)
   4425            {
   4426                context->validationError(entryPoint, GL_INVALID_ENUM,
   4427                                         kTessellationShaderExtensionNotEnabled);
   4428                return;
   4429            }
   4430            break;
   4431 
   4432        default:
   4433            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDrawMode);
   4434            return;
   4435    }
   4436 
   4437    // If we are running GLES1, there is no current program.
   4438    if (context->getClientVersion() >= Version(2, 0))
   4439    {
   4440        const ProgramExecutable *executable = state.getProgramExecutable();
   4441        ASSERT(executable);
   4442 
   4443        // Do geometry shader specific validations
   4444        if (executable->hasLinkedShaderStage(ShaderType::Geometry))
   4445        {
   4446            if (!IsCompatibleDrawModeWithGeometryShader(
   4447                    mode, executable->getGeometryShaderInputPrimitiveType()))
   4448            {
   4449                context->validationError(entryPoint, GL_INVALID_OPERATION,
   4450                                         kIncompatibleDrawModeAgainstGeometryShader);
   4451                return;
   4452            }
   4453        }
   4454 
   4455        if (executable->hasLinkedTessellationShader() && mode != PrimitiveMode::Patches)
   4456        {
   4457            context->validationError(entryPoint, GL_INVALID_OPERATION,
   4458                                     kIncompatibleDrawModeWithTessellationShader);
   4459            return;
   4460        }
   4461 
   4462        if (!executable->hasLinkedTessellationShader() && mode == PrimitiveMode::Patches)
   4463        {
   4464            context->validationError(entryPoint, GL_INVALID_OPERATION,
   4465                                     kIncompatibleDrawModeWithoutTessellationShader);
   4466            return;
   4467        }
   4468    }
   4469 
   4470    // An error should be recorded.
   4471    UNREACHABLE();
   4472 }
   4473 
   4474 bool ValidateDrawArraysInstancedANGLE(const Context *context,
   4475                                      angle::EntryPoint entryPoint,
   4476                                      PrimitiveMode mode,
   4477                                      GLint first,
   4478                                      GLsizei count,
   4479                                      GLsizei primcount)
   4480 {
   4481    if (!context->getExtensions().instancedArraysANGLE)
   4482    {
   4483        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4484        return false;
   4485    }
   4486 
   4487    if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount))
   4488    {
   4489        return false;
   4490    }
   4491 
   4492    return ValidateDrawInstancedANGLE(context, entryPoint);
   4493 }
   4494 
   4495 bool ValidateDrawArraysInstancedEXT(const Context *context,
   4496                                    angle::EntryPoint entryPoint,
   4497                                    PrimitiveMode mode,
   4498                                    GLint first,
   4499                                    GLsizei count,
   4500                                    GLsizei primcount)
   4501 {
   4502    if (!context->getExtensions().instancedArraysEXT)
   4503    {
   4504        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4505        return false;
   4506    }
   4507 
   4508    if (!ValidateDrawArraysInstancedBase(context, entryPoint, mode, first, count, primcount))
   4509    {
   4510        return false;
   4511    }
   4512 
   4513    return true;
   4514 }
   4515 
   4516 const char *ValidateDrawElementsStates(const Context *context)
   4517 {
   4518    const State &state = context->getState();
   4519 
   4520    if (context->getStateCache().isTransformFeedbackActiveUnpaused())
   4521    {
   4522        // EXT_geometry_shader allows transform feedback to work with all draw commands.
   4523        // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
   4524        if (!context->getExtensions().geometryShaderAny() && context->getClientVersion() < ES_3_2)
   4525        {
   4526            // It is an invalid operation to call DrawElements, DrawRangeElements or
   4527            // DrawElementsInstanced while transform feedback is active, (3.0.2, section 2.14, pg
   4528            // 86)
   4529            return kUnsupportedDrawModeForTransformFeedback;
   4530        }
   4531    }
   4532 
   4533    const VertexArray *vao     = state.getVertexArray();
   4534    Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
   4535 
   4536    if (elementArrayBuffer)
   4537    {
   4538        if (elementArrayBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   4539        {
   4540            return kElementArrayBufferBoundForTransformFeedback;
   4541        }
   4542        if (elementArrayBuffer->isMapped() &&
   4543            (!elementArrayBuffer->isImmutable() ||
   4544             (elementArrayBuffer->getAccessFlags() & GL_MAP_PERSISTENT_BIT_EXT) == 0))
   4545        {
   4546            return kBufferMapped;
   4547        }
   4548    }
   4549    else
   4550    {
   4551        // [WebGL 1.0] Section 6.2 No Client Side Arrays
   4552        // If an indexed draw command (drawElements) is called and no WebGLBuffer is bound to
   4553        // the ELEMENT_ARRAY_BUFFER binding point, an INVALID_OPERATION error is generated.
   4554        if (!context->getState().areClientArraysEnabled() || context->isWebGL())
   4555        {
   4556            return kMustHaveElementArrayBinding;
   4557        }
   4558    }
   4559 
   4560    return nullptr;
   4561 }
   4562 
   4563 bool ValidateDrawElementsInstancedANGLE(const Context *context,
   4564                                        angle::EntryPoint entryPoint,
   4565                                        PrimitiveMode mode,
   4566                                        GLsizei count,
   4567                                        DrawElementsType type,
   4568                                        const void *indices,
   4569                                        GLsizei primcount)
   4570 {
   4571    if (!context->getExtensions().instancedArraysANGLE)
   4572    {
   4573        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4574        return false;
   4575    }
   4576 
   4577    if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
   4578                                           primcount))
   4579    {
   4580        return false;
   4581    }
   4582 
   4583    return ValidateDrawInstancedANGLE(context, entryPoint);
   4584 }
   4585 
   4586 bool ValidateDrawElementsInstancedEXT(const Context *context,
   4587                                      angle::EntryPoint entryPoint,
   4588                                      PrimitiveMode mode,
   4589                                      GLsizei count,
   4590                                      DrawElementsType type,
   4591                                      const void *indices,
   4592                                      GLsizei primcount)
   4593 {
   4594    if (!context->getExtensions().instancedArraysEXT)
   4595    {
   4596        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4597        return false;
   4598    }
   4599 
   4600    if (!ValidateDrawElementsInstancedBase(context, entryPoint, mode, count, type, indices,
   4601                                           primcount))
   4602    {
   4603        return false;
   4604    }
   4605 
   4606    return true;
   4607 }
   4608 
   4609 bool ValidateGetUniformBase(const Context *context,
   4610                            angle::EntryPoint entryPoint,
   4611                            ShaderProgramID program,
   4612                            UniformLocation location)
   4613 {
   4614    if (program.value == 0)
   4615    {
   4616        context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist);
   4617        return false;
   4618    }
   4619 
   4620    Program *programObject = GetValidProgram(context, entryPoint, program);
   4621    if (!programObject)
   4622    {
   4623        return false;
   4624    }
   4625 
   4626    if (!programObject || !programObject->isLinked())
   4627    {
   4628        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   4629        return false;
   4630    }
   4631 
   4632    if (!programObject->isValidUniformLocation(location))
   4633    {
   4634        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidUniformLocation);
   4635        return false;
   4636    }
   4637 
   4638    return true;
   4639 }
   4640 
   4641 bool ValidateSizedGetUniform(const Context *context,
   4642                             angle::EntryPoint entryPoint,
   4643                             ShaderProgramID program,
   4644                             UniformLocation location,
   4645                             GLsizei bufSize,
   4646                             GLsizei *length)
   4647 {
   4648    if (length)
   4649    {
   4650        *length = 0;
   4651    }
   4652 
   4653    if (!ValidateGetUniformBase(context, entryPoint, program, location))
   4654    {
   4655        return false;
   4656    }
   4657 
   4658    if (bufSize < 0)
   4659    {
   4660        context->validationError(entryPoint, GL_INVALID_OPERATION, kNegativeBufferSize);
   4661        return false;
   4662    }
   4663 
   4664    Program *programObject = context->getProgramResolveLink(program);
   4665    ASSERT(programObject);
   4666 
   4667    // sized queries -- ensure the provided buffer is large enough
   4668    const LinkedUniform &uniform = programObject->getUniformByLocation(location);
   4669    size_t requiredBytes         = VariableExternalSize(uniform.type);
   4670    if (static_cast<size_t>(bufSize) < requiredBytes)
   4671    {
   4672        context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
   4673        return false;
   4674    }
   4675 
   4676    if (length)
   4677    {
   4678        *length = VariableComponentCount(uniform.type);
   4679    }
   4680    return true;
   4681 }
   4682 
   4683 bool ValidateGetnUniformfvEXT(const Context *context,
   4684                              angle::EntryPoint entryPoint,
   4685                              ShaderProgramID program,
   4686                              UniformLocation location,
   4687                              GLsizei bufSize,
   4688                              const GLfloat *params)
   4689 {
   4690    return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
   4691 }
   4692 
   4693 bool ValidateGetnUniformfvRobustANGLE(const Context *context,
   4694                                      angle::EntryPoint entryPoint,
   4695                                      ShaderProgramID program,
   4696                                      UniformLocation location,
   4697                                      GLsizei bufSize,
   4698                                      const GLsizei *length,
   4699                                      const GLfloat *params)
   4700 {
   4701    UNIMPLEMENTED();
   4702    return false;
   4703 }
   4704 
   4705 bool ValidateGetnUniformivEXT(const Context *context,
   4706                              angle::EntryPoint entryPoint,
   4707                              ShaderProgramID program,
   4708                              UniformLocation location,
   4709                              GLsizei bufSize,
   4710                              const GLint *params)
   4711 {
   4712    return ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, nullptr);
   4713 }
   4714 
   4715 bool ValidateGetnUniformivRobustANGLE(const Context *context,
   4716                                      angle::EntryPoint entryPoint,
   4717                                      ShaderProgramID program,
   4718                                      UniformLocation location,
   4719                                      GLsizei bufSize,
   4720                                      const GLsizei *length,
   4721                                      const GLint *params)
   4722 {
   4723    UNIMPLEMENTED();
   4724    return false;
   4725 }
   4726 
   4727 bool ValidateGetnUniformuivRobustANGLE(const Context *context,
   4728                                       angle::EntryPoint entryPoint,
   4729                                       ShaderProgramID program,
   4730                                       UniformLocation location,
   4731                                       GLsizei bufSize,
   4732                                       const GLsizei *length,
   4733                                       const GLuint *params)
   4734 {
   4735    UNIMPLEMENTED();
   4736    return false;
   4737 }
   4738 
   4739 bool ValidateGetUniformfvRobustANGLE(const Context *context,
   4740                                     angle::EntryPoint entryPoint,
   4741                                     ShaderProgramID program,
   4742                                     UniformLocation location,
   4743                                     GLsizei bufSize,
   4744                                     const GLsizei *length,
   4745                                     const GLfloat *params)
   4746 {
   4747    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   4748    {
   4749        return false;
   4750    }
   4751 
   4752    GLsizei writeLength = 0;
   4753 
   4754    // bufSize is validated in ValidateSizedGetUniform
   4755    if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
   4756    {
   4757        return false;
   4758    }
   4759 
   4760    SetRobustLengthParam(length, writeLength);
   4761 
   4762    return true;
   4763 }
   4764 
   4765 bool ValidateGetUniformivRobustANGLE(const Context *context,
   4766                                     angle::EntryPoint entryPoint,
   4767                                     ShaderProgramID program,
   4768                                     UniformLocation location,
   4769                                     GLsizei bufSize,
   4770                                     const GLsizei *length,
   4771                                     const GLint *params)
   4772 {
   4773    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   4774    {
   4775        return false;
   4776    }
   4777 
   4778    GLsizei writeLength = 0;
   4779 
   4780    // bufSize is validated in ValidateSizedGetUniform
   4781    if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
   4782    {
   4783        return false;
   4784    }
   4785 
   4786    SetRobustLengthParam(length, writeLength);
   4787 
   4788    return true;
   4789 }
   4790 
   4791 bool ValidateGetUniformuivRobustANGLE(const Context *context,
   4792                                      angle::EntryPoint entryPoint,
   4793                                      ShaderProgramID program,
   4794                                      UniformLocation location,
   4795                                      GLsizei bufSize,
   4796                                      const GLsizei *length,
   4797                                      const GLuint *params)
   4798 {
   4799    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   4800    {
   4801        return false;
   4802    }
   4803 
   4804    if (context->getClientMajorVersion() < 3)
   4805    {
   4806        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   4807        return false;
   4808    }
   4809 
   4810    GLsizei writeLength = 0;
   4811 
   4812    // bufSize is validated in ValidateSizedGetUniform
   4813    if (!ValidateSizedGetUniform(context, entryPoint, program, location, bufSize, &writeLength))
   4814    {
   4815        return false;
   4816    }
   4817 
   4818    SetRobustLengthParam(length, writeLength);
   4819 
   4820    return true;
   4821 }
   4822 
   4823 bool ValidateDiscardFramebufferBase(const Context *context,
   4824                                    angle::EntryPoint entryPoint,
   4825                                    GLenum target,
   4826                                    GLsizei numAttachments,
   4827                                    const GLenum *attachments,
   4828                                    bool defaultFramebuffer)
   4829 {
   4830    if (numAttachments < 0)
   4831    {
   4832        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeAttachments);
   4833        return false;
   4834    }
   4835 
   4836    for (GLsizei i = 0; i < numAttachments; ++i)
   4837    {
   4838        if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT31)
   4839        {
   4840            if (defaultFramebuffer)
   4841            {
   4842                context->validationError(entryPoint, GL_INVALID_ENUM,
   4843                                         kDefaultFramebufferInvalidAttachment);
   4844                return false;
   4845            }
   4846 
   4847            if (attachments[i] >=
   4848                GL_COLOR_ATTACHMENT0 + static_cast<GLuint>(context->getCaps().maxColorAttachments))
   4849            {
   4850                context->validationError(entryPoint, GL_INVALID_OPERATION,
   4851                                         kExceedsMaxColorAttachments);
   4852                return false;
   4853            }
   4854        }
   4855        else
   4856        {
   4857            switch (attachments[i])
   4858            {
   4859                case GL_DEPTH_ATTACHMENT:
   4860                case GL_STENCIL_ATTACHMENT:
   4861                case GL_DEPTH_STENCIL_ATTACHMENT:
   4862                    if (defaultFramebuffer)
   4863                    {
   4864                        context->validationError(entryPoint, GL_INVALID_ENUM,
   4865                                                 kDefaultFramebufferInvalidAttachment);
   4866                        return false;
   4867                    }
   4868                    break;
   4869                case GL_COLOR:
   4870                case GL_DEPTH:
   4871                case GL_STENCIL:
   4872                    if (!defaultFramebuffer)
   4873                    {
   4874                        context->validationError(entryPoint, GL_INVALID_ENUM,
   4875                                                 kDefaultFramebufferAttachmentOnUserFBO);
   4876                        return false;
   4877                    }
   4878                    break;
   4879                default:
   4880                    context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   4881                    return false;
   4882            }
   4883        }
   4884    }
   4885 
   4886    return true;
   4887 }
   4888 
   4889 bool ValidateInsertEventMarkerEXT(const Context *context,
   4890                                  angle::EntryPoint entryPoint,
   4891                                  GLsizei length,
   4892                                  const char *marker)
   4893 {
   4894    if (!context->getExtensions().debugMarkerEXT)
   4895    {
   4896        // The debug marker calls should not set error state
   4897        // However, it seems reasonable to set an error state if the extension is not enabled
   4898        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4899        return false;
   4900    }
   4901 
   4902    // Note that debug marker calls must not set error state
   4903    if (length < 0)
   4904    {
   4905        return false;
   4906    }
   4907 
   4908    if (marker == nullptr)
   4909    {
   4910        return false;
   4911    }
   4912 
   4913    return true;
   4914 }
   4915 
   4916 bool ValidatePushGroupMarkerEXT(const Context *context,
   4917                                angle::EntryPoint entryPoint,
   4918                                GLsizei length,
   4919                                const char *marker)
   4920 {
   4921    if (!context->getExtensions().debugMarkerEXT)
   4922    {
   4923        // The debug marker calls should not set error state
   4924        // However, it seems reasonable to set an error state if the extension is not enabled
   4925        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   4926        return false;
   4927    }
   4928 
   4929    // Note that debug marker calls must not set error state
   4930    if (length < 0)
   4931    {
   4932        return false;
   4933    }
   4934 
   4935    if (length > 0 && marker == nullptr)
   4936    {
   4937        return false;
   4938    }
   4939 
   4940    return true;
   4941 }
   4942 
   4943 bool ValidateEGLImageObject(const Context *context,
   4944                            angle::EntryPoint entryPoint,
   4945                            TextureType type,
   4946                            GLeglImageOES image)
   4947 {
   4948    egl::Image *imageObject = static_cast<egl::Image *>(image);
   4949 
   4950    ASSERT(context->getDisplay());
   4951    if (!context->getDisplay()->isValidImage(imageObject))
   4952    {
   4953        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEGLImage);
   4954        return false;
   4955    }
   4956 
   4957    if (imageObject->getSamples() > 0)
   4958    {
   4959        context->validationError(entryPoint, GL_INVALID_OPERATION,
   4960                                 kEGLImageCannotCreate2DMultisampled);
   4961        return false;
   4962    }
   4963 
   4964    if (!imageObject->isTexturable(context))
   4965    {
   4966        context->validationError(entryPoint, GL_INVALID_OPERATION,
   4967                                 kEGLImageTextureFormatNotSupported);
   4968        return false;
   4969    }
   4970 
   4971    // Validate source egl image and target texture are compatible
   4972    size_t depth = static_cast<size_t>(imageObject->getExtents().depth);
   4973    if (imageObject->isYUV() && type != TextureType::External)
   4974    {
   4975        context->validationError(entryPoint, GL_INVALID_OPERATION,
   4976                                 "Image is YUV, target must be TEXTURE_EXTERNAL_OES");
   4977        return false;
   4978    }
   4979 
   4980    if (depth > 1 && type != TextureType::_2DArray && type != TextureType::CubeMap &&
   4981        type != TextureType::CubeMapArray && type != TextureType::_3D)
   4982    {
   4983        context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
   4984        return false;
   4985    }
   4986 
   4987    if (imageObject->isCubeMap() && type != TextureType::CubeMapArray &&
   4988        (type != TextureType::CubeMap || depth > gl::kCubeFaceCount))
   4989    {
   4990        context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
   4991        return false;
   4992    }
   4993 
   4994    if (imageObject->getLevelCount() > 1 && type == TextureType::External)
   4995    {
   4996        context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
   4997        return false;
   4998    }
   4999 
   5000    // 3d EGLImages are currently not supported
   5001    if (type == TextureType::_3D)
   5002    {
   5003        context->validationError(entryPoint, GL_INVALID_OPERATION, kEGLImageTextureTargetMismatch);
   5004        return false;
   5005    }
   5006 
   5007    if (imageObject->hasProtectedContent() && !context->getState().hasProtectedContent())
   5008    {
   5009        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5010                                 "Mismatch between Image and Context Protected Content state");
   5011        return false;
   5012    }
   5013 
   5014    return true;
   5015 }
   5016 
   5017 bool ValidateEGLImageTargetTexture2DOES(const Context *context,
   5018                                        angle::EntryPoint entryPoint,
   5019                                        TextureType type,
   5020                                        GLeglImageOES image)
   5021 {
   5022    if (!context->getExtensions().EGLImageOES && !context->getExtensions().EGLImageExternalOES)
   5023    {
   5024        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   5025        return false;
   5026    }
   5027 
   5028    switch (type)
   5029    {
   5030        case TextureType::_2D:
   5031            if (!context->getExtensions().EGLImageOES)
   5032            {
   5033                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   5034                                          ToGLenum(type));
   5035            }
   5036            break;
   5037 
   5038        case TextureType::_2DArray:
   5039            if (!context->getExtensions().EGLImageArrayEXT)
   5040            {
   5041                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   5042                                          ToGLenum(type));
   5043            }
   5044            break;
   5045 
   5046        case TextureType::External:
   5047            if (!context->getExtensions().EGLImageExternalOES)
   5048            {
   5049                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   5050                                          ToGLenum(type));
   5051            }
   5052            break;
   5053 
   5054        default:
   5055            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   5056            return false;
   5057    }
   5058 
   5059    return ValidateEGLImageObject(context, entryPoint, type, image);
   5060 }
   5061 
   5062 bool ValidateEGLImageTargetRenderbufferStorageOES(const Context *context,
   5063                                                  angle::EntryPoint entryPoint,
   5064                                                  GLenum target,
   5065                                                  GLeglImageOES image)
   5066 {
   5067    if (!context->getExtensions().EGLImageOES)
   5068    {
   5069        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   5070        return false;
   5071    }
   5072 
   5073    switch (target)
   5074    {
   5075        case GL_RENDERBUFFER:
   5076            break;
   5077 
   5078        default:
   5079            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
   5080            return false;
   5081    }
   5082 
   5083    egl::Image *imageObject = static_cast<egl::Image *>(image);
   5084 
   5085    ASSERT(context->getDisplay());
   5086    if (!context->getDisplay()->isValidImage(imageObject))
   5087    {
   5088        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidEGLImage);
   5089        return false;
   5090    }
   5091 
   5092    if (!imageObject->isRenderable(context))
   5093    {
   5094        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5095                                 kEGLImageRenderbufferFormatNotSupported);
   5096        return false;
   5097    }
   5098 
   5099    if (imageObject->hasProtectedContent() != context->getState().hasProtectedContent())
   5100    {
   5101        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5102                                 "Mismatch between Image and Context Protected Content state");
   5103        return false;
   5104    }
   5105 
   5106    return true;
   5107 }
   5108 
   5109 bool ValidateProgramBinaryBase(const Context *context,
   5110                               angle::EntryPoint entryPoint,
   5111                               ShaderProgramID program,
   5112                               GLenum binaryFormat,
   5113                               const void *binary,
   5114                               GLint length)
   5115 {
   5116    Program *programObject = GetValidProgram(context, entryPoint, program);
   5117    if (programObject == nullptr)
   5118    {
   5119        return false;
   5120    }
   5121 
   5122    const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
   5123    if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) ==
   5124        programBinaryFormats.end())
   5125    {
   5126        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramBinaryFormat);
   5127        return false;
   5128    }
   5129 
   5130    if (context->hasActiveTransformFeedback(program))
   5131    {
   5132        // ES 3.0.4 section 2.15 page 91
   5133        context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackProgramBinary);
   5134        return false;
   5135    }
   5136 
   5137    return true;
   5138 }
   5139 
   5140 bool ValidateGetProgramBinaryBase(const Context *context,
   5141                                  angle::EntryPoint entryPoint,
   5142                                  ShaderProgramID program,
   5143                                  GLsizei bufSize,
   5144                                  const GLsizei *length,
   5145                                  const GLenum *binaryFormat,
   5146                                  const void *binary)
   5147 {
   5148    Program *programObject = GetValidProgram(context, entryPoint, program);
   5149    if (programObject == nullptr)
   5150    {
   5151        return false;
   5152    }
   5153 
   5154    if (!programObject->isLinked())
   5155    {
   5156        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   5157        return false;
   5158    }
   5159 
   5160    if (context->getCaps().programBinaryFormats.empty())
   5161    {
   5162        context->validationError(entryPoint, GL_INVALID_OPERATION, kNoProgramBinaryFormats);
   5163        return false;
   5164    }
   5165 
   5166    return true;
   5167 }
   5168 
   5169 bool ValidateDrawBuffersBase(const Context *context,
   5170                             angle::EntryPoint entryPoint,
   5171                             GLsizei n,
   5172                             const GLenum *bufs)
   5173 {
   5174    // INVALID_VALUE is generated if n is negative or greater than value of MAX_DRAW_BUFFERS
   5175    if (n < 0)
   5176    {
   5177        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   5178        return false;
   5179    }
   5180    if (n > context->getCaps().maxDrawBuffers)
   5181    {
   5182        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxDrawBuffer);
   5183        return false;
   5184    }
   5185 
   5186    ASSERT(context->getState().getDrawFramebuffer());
   5187    FramebufferID frameBufferId = context->getState().getDrawFramebuffer()->id();
   5188    GLuint maxColorAttachment   = GL_COLOR_ATTACHMENT0_EXT + context->getCaps().maxColorAttachments;
   5189 
   5190    // This should come first before the check for the default frame buffer
   5191    // because when we switch to ES3.1+, invalid enums will return INVALID_ENUM
   5192    // rather than INVALID_OPERATION
   5193    for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
   5194    {
   5195        const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
   5196 
   5197        if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != GL_BACK &&
   5198            (bufs[colorAttachment] < GL_COLOR_ATTACHMENT0 ||
   5199             bufs[colorAttachment] > GL_COLOR_ATTACHMENT31))
   5200        {
   5201            // Value in bufs is not NONE, BACK, or GL_COLOR_ATTACHMENTi
   5202            // The 3.0.4 spec says to generate GL_INVALID_OPERATION here, but this
   5203            // was changed to GL_INVALID_ENUM in 3.1, which dEQP also expects.
   5204            // 3.1 is still a bit ambiguous about the error, but future specs are
   5205            // expected to clarify that GL_INVALID_ENUM is the correct error.
   5206            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidDrawBuffer);
   5207            return false;
   5208        }
   5209        else if (bufs[colorAttachment] >= maxColorAttachment)
   5210        {
   5211            context->validationError(entryPoint, GL_INVALID_OPERATION, kExceedsMaxColorAttachments);
   5212            return false;
   5213        }
   5214        else if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment &&
   5215                 frameBufferId.value != 0)
   5216        {
   5217            // INVALID_OPERATION-GL is bound to buffer and ith argument
   5218            // is not COLOR_ATTACHMENTi or NONE
   5219            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidDrawBufferValue);
   5220            return false;
   5221        }
   5222    }
   5223 
   5224    // INVALID_OPERATION is generated if GL is bound to the default framebuffer
   5225    // and n is not 1 or bufs is bound to value other than BACK and NONE
   5226    if (frameBufferId.value == 0)
   5227    {
   5228        if (n != 1)
   5229        {
   5230            context->validationError(entryPoint, GL_INVALID_OPERATION,
   5231                                     kInvalidDrawBufferCountForDefault);
   5232            return false;
   5233        }
   5234 
   5235        if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
   5236        {
   5237            context->validationError(entryPoint, GL_INVALID_OPERATION,
   5238                                     kDefaultFramebufferInvalidDrawBuffer);
   5239            return false;
   5240        }
   5241    }
   5242 
   5243    return true;
   5244 }
   5245 
   5246 bool ValidateGetBufferPointervBase(const Context *context,
   5247                                   angle::EntryPoint entryPoint,
   5248                                   BufferBinding target,
   5249                                   GLenum pname,
   5250                                   GLsizei *length,
   5251                                   void *const *params)
   5252 {
   5253    if (length)
   5254    {
   5255        *length = 0;
   5256    }
   5257 
   5258    if (!context->isValidBufferBinding(target))
   5259    {
   5260        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   5261        return false;
   5262    }
   5263 
   5264    switch (pname)
   5265    {
   5266        case GL_BUFFER_MAP_POINTER:
   5267            break;
   5268 
   5269        default:
   5270            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   5271            return false;
   5272    }
   5273 
   5274    // GLES 3.0 section 2.10.1: "Attempts to attempts to modify or query buffer object state for a
   5275    // target bound to zero generate an INVALID_OPERATION error."
   5276    // GLES 3.1 section 6.6 explicitly specifies this error.
   5277    if (context->getState().getTargetBuffer(target) == nullptr)
   5278    {
   5279        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferPointerNotAvailable);
   5280        return false;
   5281    }
   5282 
   5283    if (length)
   5284    {
   5285        *length = 1;
   5286    }
   5287 
   5288    return true;
   5289 }
   5290 
   5291 bool ValidateUnmapBufferBase(const Context *context,
   5292                             angle::EntryPoint entryPoint,
   5293                             BufferBinding target)
   5294 {
   5295    if (!context->isValidBufferBinding(target))
   5296    {
   5297        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   5298        return false;
   5299    }
   5300 
   5301    Buffer *buffer = context->getState().getTargetBuffer(target);
   5302 
   5303    if (buffer == nullptr || !buffer->isMapped())
   5304    {
   5305        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMapped);
   5306        return false;
   5307    }
   5308 
   5309    return true;
   5310 }
   5311 
   5312 bool ValidateMapBufferRangeBase(const Context *context,
   5313                                angle::EntryPoint entryPoint,
   5314                                BufferBinding target,
   5315                                GLintptr offset,
   5316                                GLsizeiptr length,
   5317                                GLbitfield access)
   5318 {
   5319    if (!context->isValidBufferBinding(target))
   5320    {
   5321        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   5322        return false;
   5323    }
   5324 
   5325    if (offset < 0)
   5326    {
   5327        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   5328        return false;
   5329    }
   5330 
   5331    if (length < 0)
   5332    {
   5333        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength);
   5334        return false;
   5335    }
   5336 
   5337    Buffer *buffer = context->getState().getTargetBuffer(target);
   5338 
   5339    if (!buffer)
   5340    {
   5341        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotMappable);
   5342        return false;
   5343    }
   5344 
   5345    // Check for buffer overflow
   5346    CheckedNumeric<size_t> checkedOffset(offset);
   5347    auto checkedSize = checkedOffset + length;
   5348 
   5349    if (!checkedSize.IsValid() || checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getSize()))
   5350    {
   5351        context->validationError(entryPoint, GL_INVALID_VALUE, kMapOutOfRange);
   5352        return false;
   5353    }
   5354 
   5355    // Check for invalid bits in the mask
   5356    constexpr GLbitfield kAllAccessBits =
   5357        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT |
   5358        GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
   5359 
   5360    if (buffer->isImmutable())
   5361    {
   5362        // GL_EXT_buffer_storage's additions to glMapBufferRange
   5363        constexpr GLbitfield kBufferStorageAccessBits =
   5364            kAllAccessBits | GL_MAP_PERSISTENT_BIT_EXT | GL_MAP_COHERENT_BIT_EXT;
   5365 
   5366        if ((access & ~kBufferStorageAccessBits) != 0)
   5367        {
   5368            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidAccessBits);
   5369            return false;
   5370        }
   5371 
   5372        // It is invalid if any of bufferStorageMatchedAccessBits bits are included in access,
   5373        // but the same bits are not included in the buffer's storage flags
   5374        constexpr GLbitfield kBufferStorageMatchedAccessBits = GL_MAP_READ_BIT | GL_MAP_WRITE_BIT |
   5375                                                               GL_MAP_PERSISTENT_BIT_EXT |
   5376                                                               GL_MAP_COHERENT_BIT_EXT;
   5377        GLbitfield accessFlags = access & kBufferStorageMatchedAccessBits;
   5378        if ((accessFlags & buffer->getStorageExtUsageFlags()) != accessFlags)
   5379        {
   5380            context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBits);
   5381            return false;
   5382        }
   5383    }
   5384    else if ((access & ~kAllAccessBits) != 0)
   5385    {
   5386        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidAccessBits);
   5387        return false;
   5388    }
   5389 
   5390    if (length == 0)
   5391    {
   5392        context->validationError(entryPoint, GL_INVALID_OPERATION, kLengthZero);
   5393        return false;
   5394    }
   5395 
   5396    if (buffer->isMapped())
   5397    {
   5398        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferAlreadyMapped);
   5399        return false;
   5400    }
   5401 
   5402    // Check for invalid bit combinations
   5403    if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
   5404    {
   5405        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsReadWrite);
   5406        return false;
   5407    }
   5408 
   5409    GLbitfield writeOnlyBits =
   5410        GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
   5411 
   5412    if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
   5413    {
   5414        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsRead);
   5415        return false;
   5416    }
   5417 
   5418    if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
   5419    {
   5420        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAccessBitsFlush);
   5421        return false;
   5422    }
   5423 
   5424    return ValidateMapBufferBase(context, entryPoint, target);
   5425 }
   5426 
   5427 bool ValidateFlushMappedBufferRangeBase(const Context *context,
   5428                                        angle::EntryPoint entryPoint,
   5429                                        BufferBinding target,
   5430                                        GLintptr offset,
   5431                                        GLsizeiptr length)
   5432 {
   5433    if (offset < 0)
   5434    {
   5435        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   5436        return false;
   5437    }
   5438 
   5439    if (length < 0)
   5440    {
   5441        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLength);
   5442        return false;
   5443    }
   5444 
   5445    if (!context->isValidBufferBinding(target))
   5446    {
   5447        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   5448        return false;
   5449    }
   5450 
   5451    Buffer *buffer = context->getState().getTargetBuffer(target);
   5452 
   5453    if (buffer == nullptr)
   5454    {
   5455        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFlushZero);
   5456        return false;
   5457    }
   5458 
   5459    if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
   5460    {
   5461        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidFlushTarget);
   5462        return false;
   5463    }
   5464 
   5465    // Check for buffer overflow
   5466    CheckedNumeric<size_t> checkedOffset(offset);
   5467    auto checkedSize = checkedOffset + length;
   5468 
   5469    if (!checkedSize.IsValid() ||
   5470        checkedSize.ValueOrDie() > static_cast<size_t>(buffer->getMapLength()))
   5471    {
   5472        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidFlushOutOfRange);
   5473        return false;
   5474    }
   5475 
   5476    return true;
   5477 }
   5478 
   5479 bool ValidateGenOrDelete(const Context *context, angle::EntryPoint entryPoint, GLint n)
   5480 {
   5481    if (n < 0)
   5482    {
   5483        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   5484        return false;
   5485    }
   5486    return true;
   5487 }
   5488 
   5489 bool ValidateRobustEntryPoint(const Context *context, angle::EntryPoint entryPoint, GLsizei bufSize)
   5490 {
   5491    if (!context->getExtensions().robustClientMemoryANGLE)
   5492    {
   5493        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   5494        return false;
   5495    }
   5496 
   5497    if (bufSize < 0)
   5498    {
   5499        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   5500        return false;
   5501    }
   5502 
   5503    return true;
   5504 }
   5505 
   5506 bool ValidateRobustBufferSize(const Context *context,
   5507                              angle::EntryPoint entryPoint,
   5508                              GLsizei bufSize,
   5509                              GLsizei numParams)
   5510 {
   5511    if (bufSize < numParams)
   5512    {
   5513        context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientParams);
   5514        return false;
   5515    }
   5516 
   5517    return true;
   5518 }
   5519 
   5520 bool ValidateGetFramebufferAttachmentParameterivBase(const Context *context,
   5521                                                     angle::EntryPoint entryPoint,
   5522                                                     GLenum target,
   5523                                                     GLenum attachment,
   5524                                                     GLenum pname,
   5525                                                     GLsizei *numParams)
   5526 {
   5527    if (!ValidFramebufferTarget(context, target))
   5528    {
   5529        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   5530        return false;
   5531    }
   5532 
   5533    int clientVersion = context->getClientMajorVersion();
   5534 
   5535    switch (pname)
   5536    {
   5537        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
   5538        case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
   5539        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
   5540        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
   5541            break;
   5542 
   5543        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR:
   5544        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR:
   5545            if (clientVersion < 3 ||
   5546                !(context->getExtensions().multiviewOVR || context->getExtensions().multiview2OVR))
   5547            {
   5548                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   5549                return false;
   5550            }
   5551            break;
   5552 
   5553        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT:
   5554            if (!context->getExtensions().multisampledRenderToTextureEXT)
   5555            {
   5556                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   5557                return false;
   5558            }
   5559            break;
   5560 
   5561        case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
   5562            if (clientVersion < 3 && !context->getExtensions().sRGBEXT)
   5563            {
   5564                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   5565                return false;
   5566            }
   5567            break;
   5568 
   5569        case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
   5570        case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
   5571        case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
   5572        case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
   5573        case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
   5574        case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
   5575        case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
   5576        case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
   5577            if (clientVersion < 3)
   5578            {
   5579                context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required);
   5580                return false;
   5581            }
   5582            break;
   5583 
   5584        case GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT:
   5585            if (!context->getExtensions().geometryShaderAny() &&
   5586                context->getClientVersion() < ES_3_2)
   5587            {
   5588                context->validationError(entryPoint, GL_INVALID_ENUM,
   5589                                         kGeometryShaderExtensionNotEnabled);
   5590                return false;
   5591            }
   5592            break;
   5593 
   5594        default:
   5595            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   5596            return false;
   5597    }
   5598 
   5599    // Determine if the attachment is a valid enum
   5600    switch (attachment)
   5601    {
   5602        case GL_BACK:
   5603        case GL_DEPTH:
   5604        case GL_STENCIL:
   5605            if (clientVersion < 3)
   5606            {
   5607                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   5608                return false;
   5609            }
   5610            break;
   5611 
   5612        case GL_DEPTH_STENCIL_ATTACHMENT:
   5613            if (clientVersion < 3 && !context->isWebGL1())
   5614            {
   5615                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   5616                return false;
   5617            }
   5618            break;
   5619 
   5620        case GL_COLOR_ATTACHMENT0:
   5621        case GL_DEPTH_ATTACHMENT:
   5622        case GL_STENCIL_ATTACHMENT:
   5623            break;
   5624 
   5625        default:
   5626            if ((clientVersion < 3 && !context->getExtensions().drawBuffersEXT) ||
   5627                attachment < GL_COLOR_ATTACHMENT0_EXT ||
   5628                (attachment - GL_COLOR_ATTACHMENT0_EXT) >=
   5629                    static_cast<GLuint>(context->getCaps().maxColorAttachments))
   5630            {
   5631                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidAttachment);
   5632                return false;
   5633            }
   5634            break;
   5635    }
   5636 
   5637    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
   5638    ASSERT(framebuffer);
   5639 
   5640    if (framebuffer->isDefault())
   5641    {
   5642        if (clientVersion < 3)
   5643        {
   5644            context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebufferTarget);
   5645            return false;
   5646        }
   5647 
   5648        switch (attachment)
   5649        {
   5650            case GL_BACK:
   5651            case GL_DEPTH:
   5652            case GL_STENCIL:
   5653                break;
   5654 
   5655            default:
   5656                context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
   5657                return false;
   5658        }
   5659    }
   5660    else
   5661    {
   5662        if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
   5663        {
   5664            // Valid attachment query
   5665        }
   5666        else
   5667        {
   5668            switch (attachment)
   5669            {
   5670                case GL_DEPTH_ATTACHMENT:
   5671                case GL_STENCIL_ATTACHMENT:
   5672                    break;
   5673 
   5674                case GL_DEPTH_STENCIL_ATTACHMENT:
   5675                    if (!framebuffer->hasValidDepthStencil() && !context->isWebGL1())
   5676                    {
   5677                        context->validationError(entryPoint, GL_INVALID_OPERATION,
   5678                                                 kInvalidAttachment);
   5679                        return false;
   5680                    }
   5681                    break;
   5682 
   5683                default:
   5684                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
   5685                    return false;
   5686            }
   5687        }
   5688    }
   5689 
   5690    const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(context, attachment);
   5691    if (attachmentObject)
   5692    {
   5693        ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
   5694               attachmentObject->type() == GL_TEXTURE ||
   5695               attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
   5696 
   5697        switch (pname)
   5698        {
   5699            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
   5700                if (attachmentObject->type() != GL_RENDERBUFFER &&
   5701                    attachmentObject->type() != GL_TEXTURE)
   5702                {
   5703                    context->validationError(entryPoint, GL_INVALID_ENUM,
   5704                                             kFramebufferIncompleteAttachment);
   5705                    return false;
   5706                }
   5707                break;
   5708 
   5709            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
   5710                if (attachmentObject->type() != GL_TEXTURE)
   5711                {
   5712                    context->validationError(entryPoint, GL_INVALID_ENUM,
   5713                                             kFramebufferIncompleteAttachment);
   5714                    return false;
   5715                }
   5716                break;
   5717 
   5718            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
   5719                if (attachmentObject->type() != GL_TEXTURE)
   5720                {
   5721                    context->validationError(entryPoint, GL_INVALID_ENUM,
   5722                                             kFramebufferIncompleteAttachment);
   5723                    return false;
   5724                }
   5725                break;
   5726 
   5727            case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
   5728                if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
   5729                {
   5730                    context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidAttachment);
   5731                    return false;
   5732                }
   5733                break;
   5734 
   5735            case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
   5736                if (attachmentObject->type() != GL_TEXTURE)
   5737                {
   5738                    context->validationError(entryPoint, GL_INVALID_ENUM,
   5739                                             kFramebufferIncompleteAttachment);
   5740                    return false;
   5741                }
   5742                break;
   5743 
   5744            default:
   5745                break;
   5746        }
   5747    }
   5748    else
   5749    {
   5750        // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
   5751        // is NONE, then querying any other pname will generate INVALID_ENUM.
   5752 
   5753        // ES 3.0.2 spec pg 235 states that if the attachment type is none,
   5754        // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
   5755        // INVALID_OPERATION for all other pnames
   5756 
   5757        switch (pname)
   5758        {
   5759            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
   5760                break;
   5761 
   5762            case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
   5763                if (clientVersion < 3)
   5764                {
   5765                    context->validationError(entryPoint, GL_INVALID_ENUM,
   5766                                             kInvalidFramebufferAttachmentParameter);
   5767                    return false;
   5768                }
   5769                break;
   5770 
   5771            default:
   5772                if (clientVersion < 3)
   5773                {
   5774                    context->validationError(entryPoint, GL_INVALID_ENUM,
   5775                                             kInvalidFramebufferAttachmentParameter);
   5776                    return false;
   5777                }
   5778                else
   5779                {
   5780                    context->validationError(entryPoint, GL_INVALID_OPERATION,
   5781                                             kInvalidFramebufferAttachmentParameter);
   5782                    return false;
   5783                }
   5784        }
   5785    }
   5786 
   5787    if (numParams)
   5788    {
   5789        *numParams = 1;
   5790    }
   5791 
   5792    return true;
   5793 }
   5794 
   5795 bool ValidateGetFramebufferParameterivBase(const Context *context,
   5796                                           angle::EntryPoint entryPoint,
   5797                                           GLenum target,
   5798                                           GLenum pname,
   5799                                           const GLint *params)
   5800 {
   5801    if (!ValidFramebufferTarget(context, target))
   5802    {
   5803        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFramebufferTarget);
   5804        return false;
   5805    }
   5806 
   5807    switch (pname)
   5808    {
   5809        case GL_FRAMEBUFFER_DEFAULT_WIDTH:
   5810        case GL_FRAMEBUFFER_DEFAULT_HEIGHT:
   5811        case GL_FRAMEBUFFER_DEFAULT_SAMPLES:
   5812        case GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS:
   5813            break;
   5814        case GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT:
   5815            if (!context->getExtensions().geometryShaderAny() &&
   5816                context->getClientVersion() < ES_3_2)
   5817            {
   5818                context->validationError(entryPoint, GL_INVALID_ENUM,
   5819                                         kGeometryShaderExtensionNotEnabled);
   5820                return false;
   5821            }
   5822            break;
   5823        case GL_FRAMEBUFFER_FLIP_Y_MESA:
   5824            if (!context->getExtensions().framebufferFlipYMESA)
   5825            {
   5826                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   5827                return false;
   5828            }
   5829            break;
   5830        default:
   5831            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   5832            return false;
   5833    }
   5834 
   5835    const Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
   5836    ASSERT(framebuffer);
   5837 
   5838    if (framebuffer->isDefault())
   5839    {
   5840        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultFramebuffer);
   5841        return false;
   5842    }
   5843    return true;
   5844 }
   5845 
   5846 bool ValidateGetFramebufferAttachmentParameterivRobustANGLE(const Context *context,
   5847                                                            angle::EntryPoint entryPoint,
   5848                                                            GLenum target,
   5849                                                            GLenum attachment,
   5850                                                            GLenum pname,
   5851                                                            GLsizei bufSize,
   5852                                                            const GLsizei *length,
   5853                                                            const GLint *params)
   5854 {
   5855    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   5856    {
   5857        return false;
   5858    }
   5859 
   5860    GLsizei numParams = 0;
   5861    if (!ValidateGetFramebufferAttachmentParameterivBase(context, entryPoint, target, attachment,
   5862                                                         pname, &numParams))
   5863    {
   5864        return false;
   5865    }
   5866 
   5867    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   5868    {
   5869        return false;
   5870    }
   5871 
   5872    SetRobustLengthParam(length, numParams);
   5873 
   5874    return true;
   5875 }
   5876 
   5877 bool ValidateGetBufferParameterivRobustANGLE(const Context *context,
   5878                                             angle::EntryPoint entryPoint,
   5879                                             BufferBinding target,
   5880                                             GLenum pname,
   5881                                             GLsizei bufSize,
   5882                                             const GLsizei *length,
   5883                                             const GLint *params)
   5884 {
   5885    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   5886    {
   5887        return false;
   5888    }
   5889 
   5890    GLsizei numParams = 0;
   5891 
   5892    if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
   5893    {
   5894        return false;
   5895    }
   5896 
   5897    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   5898    {
   5899        return false;
   5900    }
   5901 
   5902    SetRobustLengthParam(length, numParams);
   5903    return true;
   5904 }
   5905 
   5906 bool ValidateGetBufferParameteri64vRobustANGLE(const Context *context,
   5907                                               angle::EntryPoint entryPoint,
   5908                                               BufferBinding target,
   5909                                               GLenum pname,
   5910                                               GLsizei bufSize,
   5911                                               const GLsizei *length,
   5912                                               const GLint64 *params)
   5913 {
   5914    GLsizei numParams = 0;
   5915 
   5916    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   5917    {
   5918        return false;
   5919    }
   5920 
   5921    if (!ValidateGetBufferParameterBase(context, entryPoint, target, pname, false, &numParams))
   5922    {
   5923        return false;
   5924    }
   5925 
   5926    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   5927    {
   5928        return false;
   5929    }
   5930 
   5931    SetRobustLengthParam(length, numParams);
   5932 
   5933    return true;
   5934 }
   5935 
   5936 bool ValidateGetProgramivBase(const Context *context,
   5937                              angle::EntryPoint entryPoint,
   5938                              ShaderProgramID program,
   5939                              GLenum pname,
   5940                              GLsizei *numParams)
   5941 {
   5942    // Currently, all GetProgramiv queries return 1 parameter
   5943    if (numParams)
   5944    {
   5945        *numParams = 1;
   5946    }
   5947 
   5948    if (context->isContextLost())
   5949    {
   5950        context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
   5951 
   5952        if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
   5953        {
   5954            // Generate an error but still return true, the context still needs to return a
   5955            // value in this case.
   5956            return true;
   5957        }
   5958        else
   5959        {
   5960            return false;
   5961        }
   5962    }
   5963 
   5964    // Special case for GL_COMPLETION_STATUS_KHR: don't resolve the link. Otherwise resolve it now.
   5965    Program *programObject = (pname == GL_COMPLETION_STATUS_KHR)
   5966                                 ? GetValidProgramNoResolve(context, entryPoint, program)
   5967                                 : GetValidProgram(context, entryPoint, program);
   5968    if (!programObject)
   5969    {
   5970        return false;
   5971    }
   5972 
   5973    switch (pname)
   5974    {
   5975        case GL_DELETE_STATUS:
   5976        case GL_LINK_STATUS:
   5977        case GL_VALIDATE_STATUS:
   5978        case GL_INFO_LOG_LENGTH:
   5979        case GL_ATTACHED_SHADERS:
   5980        case GL_ACTIVE_ATTRIBUTES:
   5981        case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
   5982        case GL_ACTIVE_UNIFORMS:
   5983        case GL_ACTIVE_UNIFORM_MAX_LENGTH:
   5984            break;
   5985 
   5986        case GL_PROGRAM_BINARY_LENGTH:
   5987            if (context->getClientMajorVersion() < 3 &&
   5988                !context->getExtensions().getProgramBinaryOES)
   5989            {
   5990                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   5991                return false;
   5992            }
   5993            break;
   5994 
   5995        case GL_ACTIVE_UNIFORM_BLOCKS:
   5996        case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
   5997        case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
   5998        case GL_TRANSFORM_FEEDBACK_VARYINGS:
   5999        case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
   6000        case GL_PROGRAM_BINARY_RETRIEVABLE_HINT:
   6001            if (context->getClientMajorVersion() < 3)
   6002            {
   6003                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES30);
   6004                return false;
   6005            }
   6006            break;
   6007 
   6008        case GL_PROGRAM_SEPARABLE:
   6009        case GL_ACTIVE_ATOMIC_COUNTER_BUFFERS:
   6010            if (context->getClientVersion() < Version(3, 1))
   6011            {
   6012                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   6013                return false;
   6014            }
   6015            break;
   6016 
   6017        case GL_COMPUTE_WORK_GROUP_SIZE:
   6018            if (context->getClientVersion() < Version(3, 1))
   6019            {
   6020                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   6021                return false;
   6022            }
   6023 
   6024            // [OpenGL ES 3.1] Chapter 7.12 Page 122
   6025            // An INVALID_OPERATION error is generated if COMPUTE_WORK_GROUP_SIZE is queried for a
   6026            // program which has not been linked successfully, or which does not contain objects to
   6027            // form a compute shader.
   6028            if (!programObject->isLinked())
   6029            {
   6030                context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   6031                return false;
   6032            }
   6033            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Compute))
   6034            {
   6035                context->validationError(entryPoint, GL_INVALID_OPERATION,
   6036                                         kNoActiveComputeShaderStage);
   6037                return false;
   6038            }
   6039            break;
   6040 
   6041        case GL_GEOMETRY_LINKED_INPUT_TYPE_EXT:
   6042        case GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT:
   6043        case GL_GEOMETRY_LINKED_VERTICES_OUT_EXT:
   6044        case GL_GEOMETRY_SHADER_INVOCATIONS_EXT:
   6045            if (!context->getExtensions().geometryShaderAny() &&
   6046                context->getClientVersion() < ES_3_2)
   6047            {
   6048                context->validationError(entryPoint, GL_INVALID_ENUM,
   6049                                         kGeometryShaderExtensionNotEnabled);
   6050                return false;
   6051            }
   6052 
   6053            // [EXT_geometry_shader] Chapter 7.12
   6054            // An INVALID_OPERATION error is generated if GEOMETRY_LINKED_VERTICES_OUT_EXT,
   6055            // GEOMETRY_LINKED_INPUT_TYPE_EXT, GEOMETRY_LINKED_OUTPUT_TYPE_EXT, or
   6056            // GEOMETRY_SHADER_INVOCATIONS_EXT are queried for a program which has not been linked
   6057            // successfully, or which does not contain objects to form a geometry shader.
   6058            if (!programObject->isLinked())
   6059            {
   6060                context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   6061                return false;
   6062            }
   6063            if (!programObject->getExecutable().hasLinkedShaderStage(ShaderType::Geometry))
   6064            {
   6065                context->validationError(entryPoint, GL_INVALID_OPERATION,
   6066                                         kNoActiveGeometryShaderStage);
   6067                return false;
   6068            }
   6069            break;
   6070 
   6071        case GL_COMPLETION_STATUS_KHR:
   6072            if (!context->getExtensions().parallelShaderCompileKHR)
   6073            {
   6074                context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6075                return false;
   6076            }
   6077            break;
   6078        case GL_TESS_CONTROL_OUTPUT_VERTICES_EXT:
   6079        case GL_TESS_GEN_MODE_EXT:
   6080        case GL_TESS_GEN_SPACING_EXT:
   6081        case GL_TESS_GEN_VERTEX_ORDER_EXT:
   6082        case GL_TESS_GEN_POINT_MODE_EXT:
   6083            if (!context->getExtensions().tessellationShaderEXT &&
   6084                context->getClientVersion() < ES_3_2)
   6085            {
   6086                context->validationError(entryPoint, GL_INVALID_ENUM,
   6087                                         kTessellationShaderExtensionNotEnabled);
   6088                return false;
   6089            }
   6090            if (!programObject->isLinked())
   6091            {
   6092                context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   6093                return false;
   6094            }
   6095            break;
   6096        default:
   6097            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6098            return false;
   6099    }
   6100 
   6101    return true;
   6102 }
   6103 
   6104 bool ValidateGetProgramivRobustANGLE(const Context *context,
   6105                                     angle::EntryPoint entryPoint,
   6106                                     ShaderProgramID program,
   6107                                     GLenum pname,
   6108                                     GLsizei bufSize,
   6109                                     const GLsizei *length,
   6110                                     const GLint *params)
   6111 {
   6112    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6113    {
   6114        return false;
   6115    }
   6116 
   6117    GLsizei numParams = 0;
   6118 
   6119    if (!ValidateGetProgramivBase(context, entryPoint, program, pname, &numParams))
   6120    {
   6121        return false;
   6122    }
   6123 
   6124    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6125    {
   6126        return false;
   6127    }
   6128 
   6129    SetRobustLengthParam(length, numParams);
   6130 
   6131    return true;
   6132 }
   6133 
   6134 bool ValidateGetRenderbufferParameterivRobustANGLE(const Context *context,
   6135                                                   angle::EntryPoint entryPoint,
   6136                                                   GLenum target,
   6137                                                   GLenum pname,
   6138                                                   GLsizei bufSize,
   6139                                                   const GLsizei *length,
   6140                                                   const GLint *params)
   6141 {
   6142    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6143    {
   6144        return false;
   6145    }
   6146 
   6147    GLsizei numParams = 0;
   6148 
   6149    if (!ValidateGetRenderbufferParameterivBase(context, entryPoint, target, pname, &numParams))
   6150    {
   6151        return false;
   6152    }
   6153 
   6154    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6155    {
   6156        return false;
   6157    }
   6158 
   6159    SetRobustLengthParam(length, numParams);
   6160 
   6161    return true;
   6162 }
   6163 
   6164 bool ValidateGetShaderivRobustANGLE(const Context *context,
   6165                                    angle::EntryPoint entryPoint,
   6166                                    ShaderProgramID shader,
   6167                                    GLenum pname,
   6168                                    GLsizei bufSize,
   6169                                    const GLsizei *length,
   6170                                    const GLint *params)
   6171 {
   6172    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6173    {
   6174        return false;
   6175    }
   6176 
   6177    GLsizei numParams = 0;
   6178 
   6179    if (!ValidateGetShaderivBase(context, entryPoint, shader, pname, &numParams))
   6180    {
   6181        return false;
   6182    }
   6183 
   6184    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6185    {
   6186        return false;
   6187    }
   6188 
   6189    SetRobustLengthParam(length, numParams);
   6190 
   6191    return true;
   6192 }
   6193 
   6194 bool ValidateGetTexParameterfvRobustANGLE(const Context *context,
   6195                                          angle::EntryPoint entryPoint,
   6196                                          TextureType target,
   6197                                          GLenum pname,
   6198                                          GLsizei bufSize,
   6199                                          const GLsizei *length,
   6200                                          const GLfloat *params)
   6201 {
   6202    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6203    {
   6204        return false;
   6205    }
   6206 
   6207    GLsizei numParams = 0;
   6208 
   6209    if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
   6210    {
   6211        return false;
   6212    }
   6213 
   6214    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6215    {
   6216        return false;
   6217    }
   6218 
   6219    SetRobustLengthParam(length, numParams);
   6220 
   6221    return true;
   6222 }
   6223 
   6224 bool ValidateGetTexParameterivRobustANGLE(const Context *context,
   6225                                          angle::EntryPoint entryPoint,
   6226                                          TextureType target,
   6227                                          GLenum pname,
   6228                                          GLsizei bufSize,
   6229                                          const GLsizei *length,
   6230                                          const GLint *params)
   6231 {
   6232 
   6233    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6234    {
   6235        return false;
   6236    }
   6237    GLsizei numParams = 0;
   6238    if (!ValidateGetTexParameterBase(context, entryPoint, target, pname, &numParams))
   6239    {
   6240        return false;
   6241    }
   6242 
   6243    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6244    {
   6245        return false;
   6246    }
   6247 
   6248    SetRobustLengthParam(length, numParams);
   6249    return true;
   6250 }
   6251 
   6252 bool ValidateGetTexParameterIivRobustANGLE(const Context *context,
   6253                                           angle::EntryPoint entryPoint,
   6254                                           TextureType target,
   6255                                           GLenum pname,
   6256                                           GLsizei bufSize,
   6257                                           const GLsizei *length,
   6258                                           const GLint *params)
   6259 {
   6260    UNIMPLEMENTED();
   6261    return false;
   6262 }
   6263 
   6264 bool ValidateGetTexParameterIuivRobustANGLE(const Context *context,
   6265                                            angle::EntryPoint entryPoint,
   6266                                            TextureType target,
   6267                                            GLenum pname,
   6268                                            GLsizei bufSize,
   6269                                            const GLsizei *length,
   6270                                            const GLuint *params)
   6271 {
   6272    UNIMPLEMENTED();
   6273    return false;
   6274 }
   6275 
   6276 bool ValidateTexParameterfvRobustANGLE(const Context *context,
   6277                                       angle::EntryPoint entryPoint,
   6278                                       TextureType target,
   6279                                       GLenum pname,
   6280                                       GLsizei bufSize,
   6281                                       const GLfloat *params)
   6282 {
   6283    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6284    {
   6285        return false;
   6286    }
   6287 
   6288    return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
   6289 }
   6290 
   6291 bool ValidateTexParameterivRobustANGLE(const Context *context,
   6292                                       angle::EntryPoint entryPoint,
   6293                                       TextureType target,
   6294                                       GLenum pname,
   6295                                       GLsizei bufSize,
   6296                                       const GLint *params)
   6297 {
   6298    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6299    {
   6300        return false;
   6301    }
   6302 
   6303    return ValidateTexParameterBase(context, entryPoint, target, pname, bufSize, true, params);
   6304 }
   6305 
   6306 bool ValidateTexParameterIivRobustANGLE(const Context *context,
   6307                                        angle::EntryPoint entryPoint,
   6308                                        TextureType target,
   6309                                        GLenum pname,
   6310                                        GLsizei bufSize,
   6311                                        const GLint *params)
   6312 {
   6313    UNIMPLEMENTED();
   6314    return false;
   6315 }
   6316 
   6317 bool ValidateTexParameterIuivRobustANGLE(const Context *context,
   6318                                         angle::EntryPoint entryPoint,
   6319                                         TextureType target,
   6320                                         GLenum pname,
   6321                                         GLsizei bufSize,
   6322                                         const GLuint *params)
   6323 {
   6324    UNIMPLEMENTED();
   6325    return false;
   6326 }
   6327 
   6328 bool ValidateGetSamplerParameterfvRobustANGLE(const Context *context,
   6329                                              angle::EntryPoint entryPoint,
   6330                                              SamplerID sampler,
   6331                                              GLenum pname,
   6332                                              GLsizei bufSize,
   6333                                              const GLsizei *length,
   6334                                              const GLfloat *params)
   6335 {
   6336    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6337    {
   6338        return false;
   6339    }
   6340 
   6341    GLsizei numParams = 0;
   6342 
   6343    if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
   6344    {
   6345        return false;
   6346    }
   6347 
   6348    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6349    {
   6350        return false;
   6351    }
   6352 
   6353    SetRobustLengthParam(length, numParams);
   6354    return true;
   6355 }
   6356 
   6357 bool ValidateGetSamplerParameterivRobustANGLE(const Context *context,
   6358                                              angle::EntryPoint entryPoint,
   6359                                              SamplerID sampler,
   6360                                              GLenum pname,
   6361                                              GLsizei bufSize,
   6362                                              const GLsizei *length,
   6363                                              const GLint *params)
   6364 {
   6365    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6366    {
   6367        return false;
   6368    }
   6369 
   6370    GLsizei numParams = 0;
   6371 
   6372    if (!ValidateGetSamplerParameterBase(context, entryPoint, sampler, pname, &numParams))
   6373    {
   6374        return false;
   6375    }
   6376 
   6377    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6378    {
   6379        return false;
   6380    }
   6381 
   6382    SetRobustLengthParam(length, numParams);
   6383    return true;
   6384 }
   6385 
   6386 bool ValidateGetSamplerParameterIivRobustANGLE(const Context *context,
   6387                                               angle::EntryPoint entryPoint,
   6388                                               SamplerID sampler,
   6389                                               GLenum pname,
   6390                                               GLsizei bufSize,
   6391                                               const GLsizei *length,
   6392                                               const GLint *params)
   6393 {
   6394    UNIMPLEMENTED();
   6395    return false;
   6396 }
   6397 
   6398 bool ValidateGetSamplerParameterIuivRobustANGLE(const Context *context,
   6399                                                angle::EntryPoint entryPoint,
   6400                                                SamplerID sampler,
   6401                                                GLenum pname,
   6402                                                GLsizei bufSize,
   6403                                                const GLsizei *length,
   6404                                                const GLuint *params)
   6405 {
   6406    UNIMPLEMENTED();
   6407    return false;
   6408 }
   6409 
   6410 bool ValidateSamplerParameterfvRobustANGLE(const Context *context,
   6411                                           angle::EntryPoint entryPoint,
   6412                                           SamplerID sampler,
   6413                                           GLenum pname,
   6414                                           GLsizei bufSize,
   6415                                           const GLfloat *params)
   6416 {
   6417    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6418    {
   6419        return false;
   6420    }
   6421 
   6422    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
   6423 }
   6424 
   6425 bool ValidateSamplerParameterivRobustANGLE(const Context *context,
   6426                                           angle::EntryPoint entryPoint,
   6427                                           SamplerID sampler,
   6428                                           GLenum pname,
   6429                                           GLsizei bufSize,
   6430                                           const GLint *params)
   6431 {
   6432    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6433    {
   6434        return false;
   6435    }
   6436 
   6437    return ValidateSamplerParameterBase(context, entryPoint, sampler, pname, bufSize, true, params);
   6438 }
   6439 
   6440 bool ValidateSamplerParameterIivRobustANGLE(const Context *context,
   6441                                            angle::EntryPoint entryPoint,
   6442                                            SamplerID sampler,
   6443                                            GLenum pname,
   6444                                            GLsizei bufSize,
   6445                                            const GLint *param)
   6446 {
   6447    UNIMPLEMENTED();
   6448    return false;
   6449 }
   6450 
   6451 bool ValidateSamplerParameterIuivRobustANGLE(const Context *context,
   6452                                             angle::EntryPoint entryPoint,
   6453                                             SamplerID sampler,
   6454                                             GLenum pname,
   6455                                             GLsizei bufSize,
   6456                                             const GLuint *param)
   6457 {
   6458    UNIMPLEMENTED();
   6459    return false;
   6460 }
   6461 
   6462 bool ValidateGetVertexAttribfvRobustANGLE(const Context *context,
   6463                                          angle::EntryPoint entryPoint,
   6464                                          GLuint index,
   6465                                          GLenum pname,
   6466                                          GLsizei bufSize,
   6467                                          const GLsizei *length,
   6468                                          const GLfloat *params)
   6469 {
   6470    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6471    {
   6472        return false;
   6473    }
   6474 
   6475    GLsizei writeLength = 0;
   6476 
   6477    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
   6478    {
   6479        return false;
   6480    }
   6481 
   6482    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   6483    {
   6484        return false;
   6485    }
   6486 
   6487    SetRobustLengthParam(length, writeLength);
   6488    return true;
   6489 }
   6490 
   6491 bool ValidateGetVertexAttribivRobustANGLE(const Context *context,
   6492                                          angle::EntryPoint entryPoint,
   6493                                          GLuint index,
   6494                                          GLenum pname,
   6495                                          GLsizei bufSize,
   6496                                          const GLsizei *length,
   6497                                          const GLint *params)
   6498 {
   6499    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6500    {
   6501        return false;
   6502    }
   6503 
   6504    GLsizei writeLength = 0;
   6505 
   6506    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, false))
   6507    {
   6508        return false;
   6509    }
   6510 
   6511    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   6512    {
   6513        return false;
   6514    }
   6515 
   6516    SetRobustLengthParam(length, writeLength);
   6517 
   6518    return true;
   6519 }
   6520 
   6521 bool ValidateGetVertexAttribPointervRobustANGLE(const Context *context,
   6522                                                angle::EntryPoint entryPoint,
   6523                                                GLuint index,
   6524                                                GLenum pname,
   6525                                                GLsizei bufSize,
   6526                                                const GLsizei *length,
   6527                                                void *const *pointer)
   6528 {
   6529    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6530    {
   6531        return false;
   6532    }
   6533 
   6534    GLsizei writeLength = 0;
   6535 
   6536    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, true, false))
   6537    {
   6538        return false;
   6539    }
   6540 
   6541    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   6542    {
   6543        return false;
   6544    }
   6545 
   6546    SetRobustLengthParam(length, writeLength);
   6547 
   6548    return true;
   6549 }
   6550 
   6551 bool ValidateGetVertexAttribIivRobustANGLE(const Context *context,
   6552                                           angle::EntryPoint entryPoint,
   6553                                           GLuint index,
   6554                                           GLenum pname,
   6555                                           GLsizei bufSize,
   6556                                           const GLsizei *length,
   6557                                           const GLint *params)
   6558 {
   6559    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6560    {
   6561        return false;
   6562    }
   6563 
   6564    GLsizei writeLength = 0;
   6565 
   6566    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
   6567    {
   6568        return false;
   6569    }
   6570 
   6571    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   6572    {
   6573        return false;
   6574    }
   6575 
   6576    SetRobustLengthParam(length, writeLength);
   6577 
   6578    return true;
   6579 }
   6580 
   6581 bool ValidateGetVertexAttribIuivRobustANGLE(const Context *context,
   6582                                            angle::EntryPoint entryPoint,
   6583                                            GLuint index,
   6584                                            GLenum pname,
   6585                                            GLsizei bufSize,
   6586                                            const GLsizei *length,
   6587                                            const GLuint *params)
   6588 {
   6589    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6590    {
   6591        return false;
   6592    }
   6593 
   6594    GLsizei writeLength = 0;
   6595 
   6596    if (!ValidateGetVertexAttribBase(context, entryPoint, index, pname, &writeLength, false, true))
   6597    {
   6598        return false;
   6599    }
   6600 
   6601    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   6602    {
   6603        return false;
   6604    }
   6605 
   6606    SetRobustLengthParam(length, writeLength);
   6607 
   6608    return true;
   6609 }
   6610 
   6611 bool ValidateGetActiveUniformBlockivRobustANGLE(const Context *context,
   6612                                                angle::EntryPoint entryPoint,
   6613                                                ShaderProgramID program,
   6614                                                UniformBlockIndex uniformBlockIndex,
   6615                                                GLenum pname,
   6616                                                GLsizei bufSize,
   6617                                                const GLsizei *length,
   6618                                                const GLint *params)
   6619 {
   6620    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6621    {
   6622        return false;
   6623    }
   6624 
   6625    GLsizei writeLength = 0;
   6626 
   6627    if (!ValidateGetActiveUniformBlockivBase(context, entryPoint, program, uniformBlockIndex, pname,
   6628                                             &writeLength))
   6629    {
   6630        return false;
   6631    }
   6632 
   6633    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, writeLength))
   6634    {
   6635        return false;
   6636    }
   6637 
   6638    SetRobustLengthParam(length, writeLength);
   6639 
   6640    return true;
   6641 }
   6642 
   6643 bool ValidateGetInternalformativRobustANGLE(const Context *context,
   6644                                            angle::EntryPoint entryPoint,
   6645                                            GLenum target,
   6646                                            GLenum internalformat,
   6647                                            GLenum pname,
   6648                                            GLsizei bufSize,
   6649                                            const GLsizei *length,
   6650                                            const GLint *params)
   6651 {
   6652    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
   6653    {
   6654        return false;
   6655    }
   6656 
   6657    GLsizei numParams = 0;
   6658 
   6659    if (!ValidateGetInternalFormativBase(context, entryPoint, target, internalformat, pname,
   6660                                         bufSize, &numParams))
   6661    {
   6662        return false;
   6663    }
   6664 
   6665    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
   6666    {
   6667        return false;
   6668    }
   6669 
   6670    SetRobustLengthParam(length, numParams);
   6671 
   6672    return true;
   6673 }
   6674 
   6675 // Perform validation from WebGL 2 section 5.10 "Invalid Clears":
   6676 // In the WebGL 2 API, trying to perform a clear when there is a mismatch between the type of the
   6677 // specified clear value and the type of a buffer that is being cleared generates an
   6678 // INVALID_OPERATION error instead of producing undefined results
   6679 bool ValidateWebGLFramebufferAttachmentClearType(const Context *context,
   6680                                                 angle::EntryPoint entryPoint,
   6681                                                 GLint drawbuffer,
   6682                                                 const GLenum *validComponentTypes,
   6683                                                 size_t validComponentTypeCount)
   6684 {
   6685    const FramebufferAttachment *attachment =
   6686        context->getState().getDrawFramebuffer()->getDrawBuffer(drawbuffer);
   6687    if (attachment)
   6688    {
   6689        GLenum componentType = attachment->getFormat().info->componentType;
   6690        const GLenum *end    = validComponentTypes + validComponentTypeCount;
   6691        if (std::find(validComponentTypes, end, componentType) == end)
   6692        {
   6693            context->validationError(entryPoint, GL_INVALID_OPERATION, kNoDefinedClearConversion);
   6694            return false;
   6695        }
   6696    }
   6697 
   6698    return true;
   6699 }
   6700 
   6701 bool ValidateRobustCompressedTexImageBase(const Context *context,
   6702                                          angle::EntryPoint entryPoint,
   6703                                          GLsizei imageSize,
   6704                                          GLsizei dataSize)
   6705 {
   6706    if (!ValidateRobustEntryPoint(context, entryPoint, dataSize))
   6707    {
   6708        return false;
   6709    }
   6710 
   6711    Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
   6712    if (pixelUnpackBuffer == nullptr)
   6713    {
   6714        if (dataSize < imageSize)
   6715        {
   6716            context->validationError(entryPoint, GL_INVALID_OPERATION, kCompressedDataSizeTooSmall);
   6717        }
   6718    }
   6719    return true;
   6720 }
   6721 
   6722 bool ValidateGetBufferParameterBase(const Context *context,
   6723                                    angle::EntryPoint entryPoint,
   6724                                    BufferBinding target,
   6725                                    GLenum pname,
   6726                                    bool pointerVersion,
   6727                                    GLsizei *numParams)
   6728 {
   6729    if (numParams)
   6730    {
   6731        *numParams = 0;
   6732    }
   6733 
   6734    if (!context->isValidBufferBinding(target))
   6735    {
   6736        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidBufferTypes);
   6737        return false;
   6738    }
   6739 
   6740    const Buffer *buffer = context->getState().getTargetBuffer(target);
   6741    if (!buffer)
   6742    {
   6743        // A null buffer means that "0" is bound to the requested buffer target
   6744        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
   6745        return false;
   6746    }
   6747 
   6748    const Extensions &extensions = context->getExtensions();
   6749 
   6750    switch (pname)
   6751    {
   6752        case GL_BUFFER_USAGE:
   6753        case GL_BUFFER_SIZE:
   6754            break;
   6755 
   6756        case GL_BUFFER_ACCESS_OES:
   6757            if (!extensions.mapbufferOES)
   6758            {
   6759                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6760                return false;
   6761            }
   6762            break;
   6763 
   6764        case GL_BUFFER_MAPPED:
   6765            static_assert(GL_BUFFER_MAPPED == GL_BUFFER_MAPPED_OES, "GL enums should be equal.");
   6766            if (context->getClientMajorVersion() < 3 && !extensions.mapbufferOES &&
   6767                !extensions.mapBufferRangeEXT)
   6768            {
   6769                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6770                return false;
   6771            }
   6772            break;
   6773 
   6774        case GL_BUFFER_MAP_POINTER:
   6775            if (!pointerVersion)
   6776            {
   6777                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMapPointerQuery);
   6778                return false;
   6779            }
   6780            break;
   6781 
   6782        case GL_BUFFER_ACCESS_FLAGS:
   6783        case GL_BUFFER_MAP_OFFSET:
   6784        case GL_BUFFER_MAP_LENGTH:
   6785            if (context->getClientMajorVersion() < 3 && !extensions.mapBufferRangeEXT)
   6786            {
   6787                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6788                return false;
   6789            }
   6790            break;
   6791 
   6792        case GL_MEMORY_SIZE_ANGLE:
   6793            if (!context->getExtensions().memorySizeANGLE)
   6794            {
   6795                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   6796                return false;
   6797            }
   6798            break;
   6799 
   6800        case GL_RESOURCE_INITIALIZED_ANGLE:
   6801            if (!context->getExtensions().robustResourceInitializationANGLE)
   6802            {
   6803                context->validationError(entryPoint, GL_INVALID_ENUM,
   6804                                         kRobustResourceInitializationExtensionRequired);
   6805                return false;
   6806            }
   6807            break;
   6808 
   6809        default:
   6810            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6811            return false;
   6812    }
   6813 
   6814    // All buffer parameter queries return one value.
   6815    if (numParams)
   6816    {
   6817        *numParams = 1;
   6818    }
   6819 
   6820    return true;
   6821 }
   6822 
   6823 bool ValidateGetRenderbufferParameterivBase(const Context *context,
   6824                                            angle::EntryPoint entryPoint,
   6825                                            GLenum target,
   6826                                            GLenum pname,
   6827                                            GLsizei *length)
   6828 {
   6829    if (length)
   6830    {
   6831        *length = 0;
   6832    }
   6833 
   6834    if (target != GL_RENDERBUFFER)
   6835    {
   6836        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidRenderbufferTarget);
   6837        return false;
   6838    }
   6839 
   6840    Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
   6841    if (renderbuffer == nullptr)
   6842    {
   6843        context->validationError(entryPoint, GL_INVALID_OPERATION, kRenderbufferNotBound);
   6844        return false;
   6845    }
   6846 
   6847    switch (pname)
   6848    {
   6849        case GL_RENDERBUFFER_WIDTH:
   6850        case GL_RENDERBUFFER_HEIGHT:
   6851        case GL_RENDERBUFFER_INTERNAL_FORMAT:
   6852        case GL_RENDERBUFFER_RED_SIZE:
   6853        case GL_RENDERBUFFER_GREEN_SIZE:
   6854        case GL_RENDERBUFFER_BLUE_SIZE:
   6855        case GL_RENDERBUFFER_ALPHA_SIZE:
   6856        case GL_RENDERBUFFER_DEPTH_SIZE:
   6857        case GL_RENDERBUFFER_STENCIL_SIZE:
   6858            break;
   6859 
   6860        case GL_RENDERBUFFER_SAMPLES_ANGLE:
   6861            if (context->getClientMajorVersion() < 3 &&
   6862                !context->getExtensions().framebufferMultisampleANGLE)
   6863            {
   6864                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   6865                return false;
   6866            }
   6867            break;
   6868 
   6869        case GL_MEMORY_SIZE_ANGLE:
   6870            if (!context->getExtensions().memorySizeANGLE)
   6871            {
   6872                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   6873                return false;
   6874            }
   6875            break;
   6876 
   6877        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
   6878        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
   6879            if (!context->getExtensions().getImageANGLE)
   6880            {
   6881                context->validationError(entryPoint, GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
   6882                return false;
   6883            }
   6884            break;
   6885 
   6886        case GL_RESOURCE_INITIALIZED_ANGLE:
   6887            if (!context->getExtensions().robustResourceInitializationANGLE)
   6888            {
   6889                context->validationError(entryPoint, GL_INVALID_ENUM,
   6890                                         kRobustResourceInitializationExtensionRequired);
   6891                return false;
   6892            }
   6893            break;
   6894 
   6895        default:
   6896            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6897            return false;
   6898    }
   6899 
   6900    if (length)
   6901    {
   6902        *length = 1;
   6903    }
   6904    return true;
   6905 }
   6906 
   6907 bool ValidateGetShaderivBase(const Context *context,
   6908                             angle::EntryPoint entryPoint,
   6909                             ShaderProgramID shader,
   6910                             GLenum pname,
   6911                             GLsizei *length)
   6912 {
   6913    if (length)
   6914    {
   6915        *length = 0;
   6916    }
   6917 
   6918    if (context->isContextLost())
   6919    {
   6920        context->validationError(entryPoint, GL_CONTEXT_LOST, kContextLost);
   6921 
   6922        if (context->getExtensions().parallelShaderCompileKHR && pname == GL_COMPLETION_STATUS_KHR)
   6923        {
   6924            // Generate an error but still return true, the context still needs to return a
   6925            // value in this case.
   6926            return true;
   6927        }
   6928        else
   6929        {
   6930            return false;
   6931        }
   6932    }
   6933 
   6934    if (GetValidShader(context, entryPoint, shader) == nullptr)
   6935    {
   6936        return false;
   6937    }
   6938 
   6939    switch (pname)
   6940    {
   6941        case GL_SHADER_TYPE:
   6942        case GL_DELETE_STATUS:
   6943        case GL_COMPILE_STATUS:
   6944        case GL_INFO_LOG_LENGTH:
   6945        case GL_SHADER_SOURCE_LENGTH:
   6946            break;
   6947 
   6948        case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
   6949            if (!context->getExtensions().translatedShaderSourceANGLE)
   6950            {
   6951                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   6952                return false;
   6953            }
   6954            break;
   6955 
   6956        case GL_COMPLETION_STATUS_KHR:
   6957            if (!context->getExtensions().parallelShaderCompileKHR)
   6958            {
   6959                context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   6960                return false;
   6961            }
   6962            break;
   6963 
   6964        default:
   6965            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   6966            return false;
   6967    }
   6968 
   6969    if (length)
   6970    {
   6971        *length = 1;
   6972    }
   6973    return true;
   6974 }
   6975 
   6976 bool ValidateGetTexParameterBase(const Context *context,
   6977                                 angle::EntryPoint entryPoint,
   6978                                 TextureType target,
   6979                                 GLenum pname,
   6980                                 GLsizei *length)
   6981 {
   6982    if (length)
   6983    {
   6984        *length = 0;
   6985    }
   6986 
   6987    if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
   6988        target == TextureType::Buffer)
   6989    {
   6990        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   6991        return false;
   6992    }
   6993 
   6994    if (context->getTextureByType(target) == nullptr)
   6995    {
   6996        // Should only be possible for external textures
   6997        context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound);
   6998        return false;
   6999    }
   7000 
   7001    if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
   7002    {
   7003        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7004        return false;
   7005    }
   7006 
   7007    switch (pname)
   7008    {
   7009        case GL_TEXTURE_MAG_FILTER:
   7010        case GL_TEXTURE_MIN_FILTER:
   7011        case GL_TEXTURE_WRAP_S:
   7012        case GL_TEXTURE_WRAP_T:
   7013            break;
   7014 
   7015        case GL_TEXTURE_USAGE_ANGLE:
   7016            if (!context->getExtensions().textureUsageANGLE)
   7017            {
   7018                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7019                return false;
   7020            }
   7021            break;
   7022 
   7023        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   7024            if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
   7025            {
   7026                return false;
   7027            }
   7028            break;
   7029 
   7030        case GL_TEXTURE_IMMUTABLE_FORMAT:
   7031            if (context->getClientMajorVersion() < 3 && !context->getExtensions().textureStorageEXT)
   7032            {
   7033                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7034                return false;
   7035            }
   7036            break;
   7037 
   7038        case GL_TEXTURE_WRAP_R:
   7039        case GL_TEXTURE_IMMUTABLE_LEVELS:
   7040        case GL_TEXTURE_SWIZZLE_R:
   7041        case GL_TEXTURE_SWIZZLE_G:
   7042        case GL_TEXTURE_SWIZZLE_B:
   7043        case GL_TEXTURE_SWIZZLE_A:
   7044        case GL_TEXTURE_BASE_LEVEL:
   7045        case GL_TEXTURE_MAX_LEVEL:
   7046        case GL_TEXTURE_MIN_LOD:
   7047        case GL_TEXTURE_MAX_LOD:
   7048            if (context->getClientMajorVersion() < 3)
   7049            {
   7050                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES30);
   7051                return false;
   7052            }
   7053            break;
   7054 
   7055        case GL_TEXTURE_COMPARE_MODE:
   7056        case GL_TEXTURE_COMPARE_FUNC:
   7057            if (context->getClientMajorVersion() < 3 && !context->getExtensions().shadowSamplersEXT)
   7058            {
   7059                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7060                return false;
   7061            }
   7062            break;
   7063 
   7064        case GL_TEXTURE_SRGB_DECODE_EXT:
   7065            if (!context->getExtensions().textureSRGBDecodeEXT)
   7066            {
   7067                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7068                return false;
   7069            }
   7070            break;
   7071 
   7072        case GL_DEPTH_STENCIL_TEXTURE_MODE:
   7073        case GL_IMAGE_FORMAT_COMPATIBILITY_TYPE:
   7074            if (context->getClientVersion() < ES_3_1)
   7075            {
   7076                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   7077                return false;
   7078            }
   7079            break;
   7080 
   7081        case GL_GENERATE_MIPMAP:
   7082        case GL_TEXTURE_CROP_RECT_OES:
   7083            // TODO(lfy@google.com): Restrict to GL_OES_draw_texture
   7084            // after GL_OES_draw_texture functionality implemented
   7085            if (context->getClientMajorVersion() > 1)
   7086            {
   7087                context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
   7088                return false;
   7089            }
   7090            break;
   7091 
   7092        case GL_MEMORY_SIZE_ANGLE:
   7093            if (!context->getExtensions().memorySizeANGLE)
   7094            {
   7095                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7096                return false;
   7097            }
   7098            break;
   7099 
   7100        case GL_TEXTURE_BORDER_COLOR:
   7101            if (!context->getExtensions().textureBorderClampOES &&
   7102                context->getClientVersion() < ES_3_2)
   7103            {
   7104                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   7105                return false;
   7106            }
   7107            break;
   7108 
   7109        case GL_TEXTURE_NATIVE_ID_ANGLE:
   7110            if (!context->getExtensions().textureExternalUpdateANGLE)
   7111            {
   7112                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   7113                return false;
   7114            }
   7115            break;
   7116 
   7117        case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
   7118        case GL_IMPLEMENTATION_COLOR_READ_TYPE:
   7119            if (!context->getExtensions().getImageANGLE)
   7120            {
   7121                context->validationError(entryPoint, GL_INVALID_ENUM, kGetImageExtensionNotEnabled);
   7122                return false;
   7123            }
   7124            break;
   7125 
   7126        case GL_RESOURCE_INITIALIZED_ANGLE:
   7127            if (!context->getExtensions().robustResourceInitializationANGLE)
   7128            {
   7129                context->validationError(entryPoint, GL_INVALID_ENUM,
   7130                                         kRobustResourceInitializationExtensionRequired);
   7131                return false;
   7132            }
   7133            break;
   7134 
   7135        case GL_TEXTURE_PROTECTED_EXT:
   7136            if (!context->getExtensions().protectedTexturesEXT)
   7137            {
   7138                context->validationError(entryPoint, GL_INVALID_ENUM,
   7139                                         kProtectedTexturesExtensionRequired);
   7140                return false;
   7141            }
   7142            break;
   7143 
   7144        case GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES:
   7145            break;
   7146 
   7147        default:
   7148            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7149            return false;
   7150    }
   7151 
   7152    if (length)
   7153    {
   7154        *length = GetTexParameterCount(pname);
   7155    }
   7156    return true;
   7157 }
   7158 
   7159 bool ValidateGetVertexAttribBase(const Context *context,
   7160                                 angle::EntryPoint entryPoint,
   7161                                 GLuint index,
   7162                                 GLenum pname,
   7163                                 GLsizei *length,
   7164                                 bool pointer,
   7165                                 bool pureIntegerEntryPoint)
   7166 {
   7167    if (length)
   7168    {
   7169        *length = 0;
   7170    }
   7171 
   7172    if (pureIntegerEntryPoint && context->getClientMajorVersion() < 3)
   7173    {
   7174        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   7175        return false;
   7176    }
   7177 
   7178    if (index >= static_cast<GLuint>(context->getCaps().maxVertexAttributes))
   7179    {
   7180        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   7181        return false;
   7182    }
   7183 
   7184    if (pointer)
   7185    {
   7186        if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
   7187        {
   7188            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7189            return false;
   7190        }
   7191    }
   7192    else
   7193    {
   7194        switch (pname)
   7195        {
   7196            case GL_VERTEX_ATTRIB_ARRAY_ENABLED:
   7197            case GL_VERTEX_ATTRIB_ARRAY_SIZE:
   7198            case GL_VERTEX_ATTRIB_ARRAY_STRIDE:
   7199            case GL_VERTEX_ATTRIB_ARRAY_TYPE:
   7200            case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED:
   7201            case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING:
   7202            case GL_CURRENT_VERTEX_ATTRIB:
   7203                break;
   7204 
   7205            case GL_VERTEX_ATTRIB_ARRAY_DIVISOR:
   7206                static_assert(
   7207                    GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
   7208                    "ANGLE extension enums not equal to GL enums.");
   7209                if (context->getClientMajorVersion() < 3 &&
   7210                    !context->getExtensions().instancedArraysAny())
   7211                {
   7212                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   7213                                              pname);
   7214                    return false;
   7215                }
   7216                break;
   7217 
   7218            case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
   7219                if (context->getClientMajorVersion() < 3)
   7220                {
   7221                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   7222                                              pname);
   7223                    return false;
   7224                }
   7225                break;
   7226 
   7227            case GL_VERTEX_ATTRIB_BINDING:
   7228            case GL_VERTEX_ATTRIB_RELATIVE_OFFSET:
   7229                if (context->getClientVersion() < ES_3_1)
   7230                {
   7231                    context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   7232                    return false;
   7233                }
   7234                break;
   7235 
   7236            default:
   7237                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7238                return false;
   7239        }
   7240    }
   7241 
   7242    if (length)
   7243    {
   7244        if (pname == GL_CURRENT_VERTEX_ATTRIB)
   7245        {
   7246            *length = 4;
   7247        }
   7248        else
   7249        {
   7250            *length = 1;
   7251        }
   7252    }
   7253 
   7254    return true;
   7255 }
   7256 
   7257 bool ValidatePixelPack(const Context *context,
   7258                       angle::EntryPoint entryPoint,
   7259                       GLenum format,
   7260                       GLenum type,
   7261                       GLint x,
   7262                       GLint y,
   7263                       GLsizei width,
   7264                       GLsizei height,
   7265                       GLsizei bufSize,
   7266                       GLsizei *length,
   7267                       const void *pixels)
   7268 {
   7269    // Check for pixel pack buffer related API errors
   7270    Buffer *pixelPackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelPack);
   7271    if (pixelPackBuffer != nullptr && pixelPackBuffer->isMapped())
   7272    {
   7273        // ...the buffer object's data store is currently mapped.
   7274        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferMapped);
   7275        return false;
   7276    }
   7277    if (pixelPackBuffer != nullptr &&
   7278        pixelPackBuffer->hasWebGLXFBBindingConflict(context->isWebGL()))
   7279    {
   7280        context->validationError(entryPoint, GL_INVALID_OPERATION,
   7281                                 kPixelPackBufferBoundForTransformFeedback);
   7282        return false;
   7283    }
   7284 
   7285    // ..  the data would be packed to the buffer object such that the memory writes required
   7286    // would exceed the data store size.
   7287    const InternalFormat &formatInfo = GetInternalFormatInfo(format, type);
   7288    const Extents size(width, height, 1);
   7289    const auto &pack = context->getState().getPackState();
   7290 
   7291    GLuint endByte = 0;
   7292    if (!formatInfo.computePackUnpackEndByte(type, size, pack, false, &endByte))
   7293    {
   7294        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   7295        return false;
   7296    }
   7297 
   7298    if (bufSize >= 0)
   7299    {
   7300        if (pixelPackBuffer == nullptr && static_cast<size_t>(bufSize) < endByte)
   7301        {
   7302            context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
   7303            return false;
   7304        }
   7305    }
   7306 
   7307    if (pixelPackBuffer != nullptr)
   7308    {
   7309        CheckedNumeric<size_t> checkedEndByte(endByte);
   7310        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
   7311        checkedEndByte += checkedOffset;
   7312 
   7313        if (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelPackBuffer->getSize()))
   7314        {
   7315            // Overflow past the end of the buffer
   7316            context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow);
   7317            return false;
   7318        }
   7319    }
   7320 
   7321    if (pixelPackBuffer == nullptr && length != nullptr)
   7322    {
   7323        if (endByte > static_cast<size_t>(std::numeric_limits<GLsizei>::max()))
   7324        {
   7325            context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   7326            return false;
   7327        }
   7328 
   7329        *length = static_cast<GLsizei>(endByte);
   7330    }
   7331 
   7332    if (context->isWebGL())
   7333    {
   7334        // WebGL 2.0 disallows the scenario:
   7335        //   GL_PACK_SKIP_PIXELS + width > DataStoreWidth
   7336        // where:
   7337        //   DataStoreWidth = (GL_PACK_ROW_LENGTH ? GL_PACK_ROW_LENGTH : width)
   7338        // Since these two pack parameters can only be set to non-zero values
   7339        // on WebGL 2.0 contexts, verify them for all WebGL contexts.
   7340        GLint dataStoreWidth = pack.rowLength ? pack.rowLength : width;
   7341        if (pack.skipPixels + width > dataStoreWidth)
   7342        {
   7343            context->validationError(entryPoint, GL_INVALID_OPERATION,
   7344                                     kInvalidPackParametersForWebGL);
   7345            return false;
   7346        }
   7347    }
   7348 
   7349    return true;
   7350 }
   7351 
   7352 bool ValidateReadPixelsBase(const Context *context,
   7353                            angle::EntryPoint entryPoint,
   7354                            GLint x,
   7355                            GLint y,
   7356                            GLsizei width,
   7357                            GLsizei height,
   7358                            GLenum format,
   7359                            GLenum type,
   7360                            GLsizei bufSize,
   7361                            GLsizei *length,
   7362                            GLsizei *columns,
   7363                            GLsizei *rows,
   7364                            const void *pixels)
   7365 {
   7366    if (length != nullptr)
   7367    {
   7368        *length = 0;
   7369    }
   7370    if (rows != nullptr)
   7371    {
   7372        *rows = 0;
   7373    }
   7374    if (columns != nullptr)
   7375    {
   7376        *columns = 0;
   7377    }
   7378 
   7379    if (width < 0 || height < 0)
   7380    {
   7381        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   7382        return false;
   7383    }
   7384 
   7385    Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
   7386    ASSERT(readFramebuffer);
   7387 
   7388    if (!ValidateFramebufferComplete(context, entryPoint, readFramebuffer))
   7389    {
   7390        return false;
   7391    }
   7392 
   7393    // needIntrinsic = true. Treat renderToTexture textures as single sample since they will be
   7394    // resolved before reading.
   7395    if (!readFramebuffer->isDefault() &&
   7396        !ValidateFramebufferNotMultisampled(context, entryPoint, readFramebuffer, true))
   7397    {
   7398        return false;
   7399    }
   7400 
   7401    if (readFramebuffer->getReadBufferState() == GL_NONE)
   7402    {
   7403        context->validationError(entryPoint, GL_INVALID_OPERATION, kReadBufferNone);
   7404        return false;
   7405    }
   7406 
   7407    const FramebufferAttachment *readBuffer = nullptr;
   7408    switch (format)
   7409    {
   7410        case GL_DEPTH_COMPONENT:
   7411            readBuffer = readFramebuffer->getDepthAttachment();
   7412            break;
   7413        case GL_STENCIL_INDEX_OES:
   7414        case GL_DEPTH_STENCIL_OES:
   7415            readBuffer = readFramebuffer->getStencilOrDepthStencilAttachment();
   7416            break;
   7417        default:
   7418            readBuffer = readFramebuffer->getReadColorAttachment();
   7419            break;
   7420    }
   7421 
   7422    // OVR_multiview2, Revision 1:
   7423    // ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
   7424    // the number of views in the current read framebuffer is more than one.
   7425    if (readFramebuffer->readDisallowedByMultiview())
   7426    {
   7427        context->validationError(entryPoint, GL_INVALID_FRAMEBUFFER_OPERATION,
   7428                                 kMultiviewReadFramebuffer);
   7429        return false;
   7430    }
   7431 
   7432    if (context->isWebGL())
   7433    {
   7434        // The ES 2.0 spec states that the format must be "among those defined in table 3.4,
   7435        // excluding formats LUMINANCE and LUMINANCE_ALPHA.".  This requires validating the format
   7436        // and type before validating the combination of format and type.  However, the
   7437        // dEQP-GLES3.functional.negative_api.buffer.read_pixels passes GL_LUMINANCE as a format and
   7438        // verifies that GL_INVALID_OPERATION is generated.
   7439        // TODO(geofflang): Update this check to be done in all/no cases once this is resolved in
   7440        // dEQP/WebGL.
   7441        if (!ValidReadPixelsFormatEnum(context, format))
   7442        {
   7443            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidFormat);
   7444            return false;
   7445        }
   7446 
   7447        if (!ValidReadPixelsTypeEnum(context, type))
   7448        {
   7449            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidType);
   7450            return false;
   7451        }
   7452    }
   7453 
   7454    // WebGL 1.0 [Section 6.26] Reading From a Missing Attachment
   7455    // In OpenGL ES it is undefined what happens when an operation tries to read from a missing
   7456    // attachment and WebGL defines it to be an error. We do the check unconditionally as the
   7457    // situation is an application error that would lead to a crash in ANGLE.
   7458    if (readBuffer == nullptr)
   7459    {
   7460        context->validationError(entryPoint, GL_INVALID_OPERATION, kMissingReadAttachment);
   7461        return false;
   7462    }
   7463 
   7464    GLenum currentFormat = GL_NONE;
   7465    GLenum currentType   = GL_NONE;
   7466 
   7467    switch (format)
   7468    {
   7469        case GL_DEPTH_COMPONENT:
   7470        case GL_STENCIL_INDEX_OES:
   7471        case GL_DEPTH_STENCIL_OES:
   7472            // Only rely on ValidReadPixelsFormatType for depth/stencil formats
   7473            break;
   7474        default:
   7475            currentFormat = readFramebuffer->getImplementationColorReadFormat(context);
   7476            currentType   = readFramebuffer->getImplementationColorReadType(context);
   7477            break;
   7478    }
   7479 
   7480    bool validFormatTypeCombination =
   7481        ValidReadPixelsFormatType(context, readBuffer->getFormat().info, format, type);
   7482 
   7483    if (!(currentFormat == format && currentType == type) && !validFormatTypeCombination)
   7484    {
   7485        context->validationError(entryPoint, GL_INVALID_OPERATION, kMismatchedTypeAndFormat);
   7486        return false;
   7487    }
   7488 
   7489    if (!ValidatePixelPack(context, entryPoint, format, type, x, y, width, height, bufSize, length,
   7490                           pixels))
   7491    {
   7492        return false;
   7493    }
   7494 
   7495    auto getClippedExtent = [](GLint start, GLsizei length, int bufferSize, GLsizei *outExtent) {
   7496        angle::CheckedNumeric<int> clippedExtent(length);
   7497        if (start < 0)
   7498        {
   7499            // "subtract" the area that is less than 0
   7500            clippedExtent += start;
   7501        }
   7502 
   7503        angle::CheckedNumeric<int> readExtent = start;
   7504        readExtent += length;
   7505        if (!readExtent.IsValid())
   7506        {
   7507            return false;
   7508        }
   7509 
   7510        if (readExtent.ValueOrDie() > bufferSize)
   7511        {
   7512            // Subtract the region to the right of the read buffer
   7513            clippedExtent -= (readExtent - bufferSize);
   7514        }
   7515 
   7516        if (!clippedExtent.IsValid())
   7517        {
   7518            return false;
   7519        }
   7520 
   7521        *outExtent = std::max<int>(clippedExtent.ValueOrDie(), 0);
   7522        return true;
   7523    };
   7524 
   7525    GLsizei writtenColumns = 0;
   7526    if (!getClippedExtent(x, width, readBuffer->getSize().width, &writtenColumns))
   7527    {
   7528        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   7529        return false;
   7530    }
   7531 
   7532    GLsizei writtenRows = 0;
   7533    if (!getClippedExtent(y, height, readBuffer->getSize().height, &writtenRows))
   7534    {
   7535        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   7536        return false;
   7537    }
   7538 
   7539    if (columns != nullptr)
   7540    {
   7541        *columns = writtenColumns;
   7542    }
   7543 
   7544    if (rows != nullptr)
   7545    {
   7546        *rows = writtenRows;
   7547    }
   7548 
   7549    return true;
   7550 }
   7551 
   7552 template <typename ParamType>
   7553 bool ValidateTexParameterBase(const Context *context,
   7554                              angle::EntryPoint entryPoint,
   7555                              TextureType target,
   7556                              GLenum pname,
   7557                              GLsizei bufSize,
   7558                              bool vectorParams,
   7559                              const ParamType *params)
   7560 {
   7561    if ((!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target)) ||
   7562        target == TextureType::Buffer)
   7563    {
   7564        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   7565        return false;
   7566    }
   7567 
   7568    if (context->getTextureByType(target) == nullptr)
   7569    {
   7570        // Should only be possible for external textures
   7571        context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound);
   7572        return false;
   7573    }
   7574 
   7575    const GLsizei minBufSize = GetTexParameterCount(pname);
   7576    if (bufSize >= 0 && bufSize < minBufSize)
   7577    {
   7578        context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
   7579        return false;
   7580    }
   7581 
   7582    if (context->getClientMajorVersion() == 1 && !IsValidGLES1TextureParameter(pname))
   7583    {
   7584        context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7585        return false;
   7586    }
   7587 
   7588    switch (pname)
   7589    {
   7590        case GL_TEXTURE_WRAP_R:
   7591        case GL_TEXTURE_SWIZZLE_R:
   7592        case GL_TEXTURE_SWIZZLE_G:
   7593        case GL_TEXTURE_SWIZZLE_B:
   7594        case GL_TEXTURE_SWIZZLE_A:
   7595        case GL_TEXTURE_BASE_LEVEL:
   7596        case GL_TEXTURE_MAX_LEVEL:
   7597        case GL_TEXTURE_COMPARE_MODE:
   7598        case GL_TEXTURE_COMPARE_FUNC:
   7599        case GL_TEXTURE_MIN_LOD:
   7600        case GL_TEXTURE_MAX_LOD:
   7601            if (context->getClientMajorVersion() < 3 &&
   7602                !(pname == GL_TEXTURE_WRAP_R && context->getExtensions().texture3DOES))
   7603            {
   7604                context->validationError(entryPoint, GL_INVALID_ENUM, kES3Required);
   7605                return false;
   7606            }
   7607            if (target == TextureType::External &&
   7608                !context->getExtensions().EGLImageExternalEssl3OES)
   7609            {
   7610                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7611                return false;
   7612            }
   7613            if (target == TextureType::VideoImage && !context->getExtensions().videoTextureWEBGL)
   7614            {
   7615                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7616            }
   7617            break;
   7618 
   7619        case GL_GENERATE_MIPMAP:
   7620        case GL_TEXTURE_CROP_RECT_OES:
   7621            if (context->getClientMajorVersion() > 1)
   7622            {
   7623                context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
   7624                return false;
   7625            }
   7626            break;
   7627 
   7628        default:
   7629            break;
   7630    }
   7631 
   7632    if (target == TextureType::_2DMultisample || target == TextureType::_2DMultisampleArray)
   7633    {
   7634        switch (pname)
   7635        {
   7636            case GL_TEXTURE_MIN_FILTER:
   7637            case GL_TEXTURE_MAG_FILTER:
   7638            case GL_TEXTURE_WRAP_S:
   7639            case GL_TEXTURE_WRAP_T:
   7640            case GL_TEXTURE_WRAP_R:
   7641            case GL_TEXTURE_MIN_LOD:
   7642            case GL_TEXTURE_MAX_LOD:
   7643            case GL_TEXTURE_COMPARE_MODE:
   7644            case GL_TEXTURE_COMPARE_FUNC:
   7645            case GL_TEXTURE_BORDER_COLOR:
   7646                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   7647                return false;
   7648        }
   7649    }
   7650 
   7651    switch (pname)
   7652    {
   7653        case GL_TEXTURE_WRAP_S:
   7654        case GL_TEXTURE_WRAP_T:
   7655        case GL_TEXTURE_WRAP_R:
   7656        {
   7657            bool restrictedWrapModes = ((target == TextureType::External &&
   7658                                         !context->getExtensions().EGLImageExternalWrapModesEXT) ||
   7659                                        target == TextureType::Rectangle);
   7660            if (!ValidateTextureWrapModeValue(context, entryPoint, params, restrictedWrapModes))
   7661            {
   7662                return false;
   7663            }
   7664        }
   7665        break;
   7666 
   7667        case GL_TEXTURE_MIN_FILTER:
   7668        {
   7669            bool restrictedMinFilter =
   7670                target == TextureType::External || target == TextureType::Rectangle;
   7671            if (!ValidateTextureMinFilterValue(context, entryPoint, params, restrictedMinFilter))
   7672            {
   7673                return false;
   7674            }
   7675        }
   7676        break;
   7677 
   7678        case GL_TEXTURE_MAG_FILTER:
   7679            if (!ValidateTextureMagFilterValue(context, entryPoint, params))
   7680            {
   7681                return false;
   7682            }
   7683            break;
   7684 
   7685        case GL_TEXTURE_USAGE_ANGLE:
   7686            if (!context->getExtensions().textureUsageANGLE)
   7687            {
   7688                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7689                return false;
   7690            }
   7691 
   7692            switch (ConvertToGLenum(params[0]))
   7693            {
   7694                case GL_NONE:
   7695                case GL_FRAMEBUFFER_ATTACHMENT_ANGLE:
   7696                    break;
   7697 
   7698                default:
   7699                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   7700                                              pname);
   7701                    return false;
   7702            }
   7703            break;
   7704 
   7705        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   7706        {
   7707            GLfloat paramValue = static_cast<GLfloat>(params[0]);
   7708            if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
   7709            {
   7710                return false;
   7711            }
   7712            ASSERT(static_cast<ParamType>(paramValue) == params[0]);
   7713        }
   7714        break;
   7715 
   7716        case GL_TEXTURE_MIN_LOD:
   7717        case GL_TEXTURE_MAX_LOD:
   7718            // any value is permissible
   7719            break;
   7720 
   7721        case GL_TEXTURE_COMPARE_MODE:
   7722            if (!ValidateTextureCompareModeValue(context, entryPoint, params))
   7723            {
   7724                return false;
   7725            }
   7726            break;
   7727 
   7728        case GL_TEXTURE_COMPARE_FUNC:
   7729            if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
   7730            {
   7731                return false;
   7732            }
   7733            break;
   7734 
   7735        case GL_TEXTURE_SWIZZLE_R:
   7736        case GL_TEXTURE_SWIZZLE_G:
   7737        case GL_TEXTURE_SWIZZLE_B:
   7738        case GL_TEXTURE_SWIZZLE_A:
   7739            switch (ConvertToGLenum(params[0]))
   7740            {
   7741                case GL_RED:
   7742                case GL_GREEN:
   7743                case GL_BLUE:
   7744                case GL_ALPHA:
   7745                case GL_ZERO:
   7746                case GL_ONE:
   7747                    break;
   7748 
   7749                default:
   7750                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   7751                                              pname);
   7752                    return false;
   7753            }
   7754            break;
   7755 
   7756        case GL_TEXTURE_BASE_LEVEL:
   7757            if (ConvertToGLint(params[0]) < 0)
   7758            {
   7759                context->validationError(entryPoint, GL_INVALID_VALUE, kBaseLevelNegative);
   7760                return false;
   7761            }
   7762            if (target == TextureType::External && static_cast<GLuint>(params[0]) != 0)
   7763            {
   7764                context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero);
   7765                return false;
   7766            }
   7767            if ((target == TextureType::_2DMultisample ||
   7768                 target == TextureType::_2DMultisampleArray) &&
   7769                static_cast<GLuint>(params[0]) != 0)
   7770            {
   7771                context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero);
   7772                return false;
   7773            }
   7774            if (target == TextureType::Rectangle && static_cast<GLuint>(params[0]) != 0)
   7775            {
   7776                context->validationError(entryPoint, GL_INVALID_OPERATION, kBaseLevelNonZero);
   7777                return false;
   7778            }
   7779            break;
   7780 
   7781        case GL_TEXTURE_MAX_LEVEL:
   7782            if (ConvertToGLint(params[0]) < 0)
   7783            {
   7784                context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   7785                return false;
   7786            }
   7787            break;
   7788 
   7789        case GL_DEPTH_STENCIL_TEXTURE_MODE:
   7790            if (context->getClientVersion() < Version(3, 1))
   7791            {
   7792                context->validationError(entryPoint, GL_INVALID_ENUM, kEnumRequiresGLES31);
   7793                return false;
   7794            }
   7795            switch (ConvertToGLenum(params[0]))
   7796            {
   7797                case GL_DEPTH_COMPONENT:
   7798                case GL_STENCIL_INDEX:
   7799                    break;
   7800 
   7801                default:
   7802                    context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported,
   7803                                              pname);
   7804                    return false;
   7805            }
   7806            break;
   7807 
   7808        case GL_TEXTURE_SRGB_DECODE_EXT:
   7809            if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
   7810            {
   7811                return false;
   7812            }
   7813            break;
   7814 
   7815        case GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT:
   7816            if (!ValidateTextureSRGBOverrideValue(context, entryPoint, params))
   7817            {
   7818                return false;
   7819            }
   7820            break;
   7821 
   7822        case GL_GENERATE_MIPMAP:
   7823            if (context->getClientMajorVersion() > 1)
   7824            {
   7825                context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
   7826                return false;
   7827            }
   7828            break;
   7829 
   7830        case GL_TEXTURE_CROP_RECT_OES:
   7831            if (context->getClientMajorVersion() > 1)
   7832            {
   7833                context->validationError(entryPoint, GL_INVALID_ENUM, kGLES1Only);
   7834                return false;
   7835            }
   7836            if (!vectorParams)
   7837            {
   7838                context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
   7839                return false;
   7840            }
   7841            break;
   7842 
   7843        case GL_TEXTURE_BORDER_COLOR:
   7844            if (!context->getExtensions().textureBorderClampOES &&
   7845                context->getClientVersion() < ES_3_2)
   7846            {
   7847                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   7848                return false;
   7849            }
   7850            if (!vectorParams)
   7851            {
   7852                context->validationError(entryPoint, GL_INVALID_ENUM, kInsufficientBufferSize);
   7853                return false;
   7854            }
   7855            break;
   7856 
   7857        case GL_RESOURCE_INITIALIZED_ANGLE:
   7858            if (!context->getExtensions().robustResourceInitializationANGLE)
   7859            {
   7860                context->validationError(entryPoint, GL_INVALID_ENUM,
   7861                                         kRobustResourceInitializationExtensionRequired);
   7862                return false;
   7863            }
   7864            break;
   7865 
   7866        case GL_TEXTURE_PROTECTED_EXT:
   7867            if (!context->getExtensions().protectedTexturesEXT)
   7868            {
   7869                context->validationError(entryPoint, GL_INVALID_ENUM,
   7870                                         kProtectedTexturesExtensionRequired);
   7871                return false;
   7872            }
   7873            if (ConvertToBool(params[0]) != context->getState().hasProtectedContent())
   7874            {
   7875                context->validationError(entryPoint, GL_INVALID_OPERATION,
   7876                                         "Protected Texture must match Protected Context");
   7877                return false;
   7878            }
   7879            break;
   7880 
   7881        default:
   7882            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7883            return false;
   7884    }
   7885 
   7886    return true;
   7887 }
   7888 
   7889 template bool ValidateTexParameterBase(const Context *,
   7890                                       angle::EntryPoint,
   7891                                       TextureType,
   7892                                       GLenum,
   7893                                       GLsizei,
   7894                                       bool,
   7895                                       const GLfloat *);
   7896 template bool ValidateTexParameterBase(const Context *,
   7897                                       angle::EntryPoint,
   7898                                       TextureType,
   7899                                       GLenum,
   7900                                       GLsizei,
   7901                                       bool,
   7902                                       const GLint *);
   7903 template bool ValidateTexParameterBase(const Context *,
   7904                                       angle::EntryPoint,
   7905                                       TextureType,
   7906                                       GLenum,
   7907                                       GLsizei,
   7908                                       bool,
   7909                                       const GLuint *);
   7910 
   7911 bool ValidateGetActiveUniformBlockivBase(const Context *context,
   7912                                         angle::EntryPoint entryPoint,
   7913                                         ShaderProgramID program,
   7914                                         UniformBlockIndex uniformBlockIndex,
   7915                                         GLenum pname,
   7916                                         GLsizei *length)
   7917 {
   7918    if (length)
   7919    {
   7920        *length = 0;
   7921    }
   7922 
   7923    if (context->getClientMajorVersion() < 3)
   7924    {
   7925        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   7926        return false;
   7927    }
   7928 
   7929    Program *programObject = GetValidProgram(context, entryPoint, program);
   7930    if (!programObject)
   7931    {
   7932        return false;
   7933    }
   7934 
   7935    if (uniformBlockIndex.value >= programObject->getActiveUniformBlockCount())
   7936    {
   7937        context->validationError(entryPoint, GL_INVALID_VALUE,
   7938                                 kIndexExceedsActiveUniformBlockCount);
   7939        return false;
   7940    }
   7941 
   7942    switch (pname)
   7943    {
   7944        case GL_UNIFORM_BLOCK_BINDING:
   7945        case GL_UNIFORM_BLOCK_DATA_SIZE:
   7946        case GL_UNIFORM_BLOCK_NAME_LENGTH:
   7947        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
   7948        case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
   7949        case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
   7950        case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
   7951            break;
   7952 
   7953        default:
   7954            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   7955            return false;
   7956    }
   7957 
   7958    if (length)
   7959    {
   7960        if (pname == GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES)
   7961        {
   7962            const InterfaceBlock &uniformBlock =
   7963                programObject->getUniformBlockByIndex(uniformBlockIndex.value);
   7964            *length = static_cast<GLsizei>(uniformBlock.memberIndexes.size());
   7965        }
   7966        else
   7967        {
   7968            *length = 1;
   7969        }
   7970    }
   7971 
   7972    return true;
   7973 }
   7974 
   7975 template <typename ParamType>
   7976 bool ValidateSamplerParameterBase(const Context *context,
   7977                                  angle::EntryPoint entryPoint,
   7978                                  SamplerID sampler,
   7979                                  GLenum pname,
   7980                                  GLsizei bufSize,
   7981                                  bool vectorParams,
   7982                                  const ParamType *params)
   7983 {
   7984    if (context->getClientMajorVersion() < 3)
   7985    {
   7986        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   7987        return false;
   7988    }
   7989 
   7990    if (!context->isSampler(sampler))
   7991    {
   7992        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
   7993        return false;
   7994    }
   7995 
   7996    const GLsizei minBufSize = GetSamplerParameterCount(pname);
   7997    if (bufSize >= 0 && bufSize < minBufSize)
   7998    {
   7999        context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
   8000        return false;
   8001    }
   8002 
   8003    switch (pname)
   8004    {
   8005        case GL_TEXTURE_WRAP_S:
   8006        case GL_TEXTURE_WRAP_T:
   8007        case GL_TEXTURE_WRAP_R:
   8008            if (!ValidateTextureWrapModeValue(context, entryPoint, params, false))
   8009            {
   8010                return false;
   8011            }
   8012            break;
   8013 
   8014        case GL_TEXTURE_MIN_FILTER:
   8015            if (!ValidateTextureMinFilterValue(context, entryPoint, params, false))
   8016            {
   8017                return false;
   8018            }
   8019            break;
   8020 
   8021        case GL_TEXTURE_MAG_FILTER:
   8022            if (!ValidateTextureMagFilterValue(context, entryPoint, params))
   8023            {
   8024                return false;
   8025            }
   8026            break;
   8027 
   8028        case GL_TEXTURE_MIN_LOD:
   8029        case GL_TEXTURE_MAX_LOD:
   8030            // any value is permissible
   8031            break;
   8032 
   8033        case GL_TEXTURE_COMPARE_MODE:
   8034            if (!ValidateTextureCompareModeValue(context, entryPoint, params))
   8035            {
   8036                return false;
   8037            }
   8038            break;
   8039 
   8040        case GL_TEXTURE_COMPARE_FUNC:
   8041            if (!ValidateTextureCompareFuncValue(context, entryPoint, params))
   8042            {
   8043                return false;
   8044            }
   8045            break;
   8046 
   8047        case GL_TEXTURE_SRGB_DECODE_EXT:
   8048            if (!ValidateTextureSRGBDecodeValue(context, entryPoint, params))
   8049            {
   8050                return false;
   8051            }
   8052            break;
   8053 
   8054        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   8055        {
   8056            GLfloat paramValue = static_cast<GLfloat>(params[0]);
   8057            if (!ValidateTextureMaxAnisotropyValue(context, entryPoint, paramValue))
   8058            {
   8059                return false;
   8060            }
   8061        }
   8062        break;
   8063 
   8064        case GL_TEXTURE_BORDER_COLOR:
   8065            if (!context->getExtensions().textureBorderClampOES &&
   8066                context->getClientVersion() < ES_3_2)
   8067            {
   8068                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   8069                return false;
   8070            }
   8071            if (!vectorParams)
   8072            {
   8073                context->validationError(entryPoint, GL_INVALID_ENUM, kInsufficientBufferSize);
   8074                return false;
   8075            }
   8076            break;
   8077 
   8078        default:
   8079            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   8080            return false;
   8081    }
   8082 
   8083    return true;
   8084 }
   8085 
   8086 template bool ValidateSamplerParameterBase(const Context *,
   8087                                           angle::EntryPoint,
   8088                                           SamplerID,
   8089                                           GLenum,
   8090                                           GLsizei,
   8091                                           bool,
   8092                                           const GLfloat *);
   8093 template bool ValidateSamplerParameterBase(const Context *,
   8094                                           angle::EntryPoint,
   8095                                           SamplerID,
   8096                                           GLenum,
   8097                                           GLsizei,
   8098                                           bool,
   8099                                           const GLint *);
   8100 template bool ValidateSamplerParameterBase(const Context *,
   8101                                           angle::EntryPoint,
   8102                                           SamplerID,
   8103                                           GLenum,
   8104                                           GLsizei,
   8105                                           bool,
   8106                                           const GLuint *);
   8107 
   8108 bool ValidateGetSamplerParameterBase(const Context *context,
   8109                                     angle::EntryPoint entryPoint,
   8110                                     SamplerID sampler,
   8111                                     GLenum pname,
   8112                                     GLsizei *length)
   8113 {
   8114    if (length)
   8115    {
   8116        *length = 0;
   8117    }
   8118 
   8119    if (context->getClientMajorVersion() < 3)
   8120    {
   8121        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   8122        return false;
   8123    }
   8124 
   8125    if (!context->isSampler(sampler))
   8126    {
   8127        context->validationError(entryPoint, GL_INVALID_OPERATION, kInvalidSampler);
   8128        return false;
   8129    }
   8130 
   8131    switch (pname)
   8132    {
   8133        case GL_TEXTURE_WRAP_S:
   8134        case GL_TEXTURE_WRAP_T:
   8135        case GL_TEXTURE_WRAP_R:
   8136        case GL_TEXTURE_MIN_FILTER:
   8137        case GL_TEXTURE_MAG_FILTER:
   8138        case GL_TEXTURE_MIN_LOD:
   8139        case GL_TEXTURE_MAX_LOD:
   8140        case GL_TEXTURE_COMPARE_MODE:
   8141        case GL_TEXTURE_COMPARE_FUNC:
   8142            break;
   8143 
   8144        case GL_TEXTURE_MAX_ANISOTROPY_EXT:
   8145            if (!ValidateTextureMaxAnisotropyExtensionEnabled(context, entryPoint))
   8146            {
   8147                return false;
   8148            }
   8149            break;
   8150 
   8151        case GL_TEXTURE_SRGB_DECODE_EXT:
   8152            if (!context->getExtensions().textureSRGBDecodeEXT)
   8153            {
   8154                context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   8155                return false;
   8156            }
   8157            break;
   8158 
   8159        case GL_TEXTURE_BORDER_COLOR:
   8160            if (!context->getExtensions().textureBorderClampOES &&
   8161                context->getClientVersion() < ES_3_2)
   8162            {
   8163                context->validationError(entryPoint, GL_INVALID_ENUM, kExtensionNotEnabled);
   8164                return false;
   8165            }
   8166            break;
   8167 
   8168        default:
   8169            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   8170            return false;
   8171    }
   8172 
   8173    if (length)
   8174    {
   8175        *length = GetSamplerParameterCount(pname);
   8176    }
   8177    return true;
   8178 }
   8179 
   8180 bool ValidateGetInternalFormativBase(const Context *context,
   8181                                     angle::EntryPoint entryPoint,
   8182                                     GLenum target,
   8183                                     GLenum internalformat,
   8184                                     GLenum pname,
   8185                                     GLsizei bufSize,
   8186                                     GLsizei *numParams)
   8187 {
   8188    if (numParams)
   8189    {
   8190        *numParams = 0;
   8191    }
   8192 
   8193    if (context->getClientMajorVersion() < 3)
   8194    {
   8195        context->validationError(entryPoint, GL_INVALID_OPERATION, kES3Required);
   8196        return false;
   8197    }
   8198 
   8199    const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
   8200    if (!formatCaps.renderbuffer)
   8201    {
   8202        context->validationError(entryPoint, GL_INVALID_ENUM, kFormatNotRenderable);
   8203        return false;
   8204    }
   8205 
   8206    switch (target)
   8207    {
   8208        case GL_RENDERBUFFER:
   8209            break;
   8210 
   8211        case GL_TEXTURE_2D_MULTISAMPLE:
   8212            if (context->getClientVersion() < ES_3_1 &&
   8213                !context->getExtensions().textureMultisampleANGLE)
   8214            {
   8215                context->validationError(entryPoint, GL_INVALID_ENUM,
   8216                                         kMultisampleTextureExtensionOrES31Required);
   8217                return false;
   8218            }
   8219            break;
   8220        case GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES:
   8221            if (!context->getExtensions().textureStorageMultisample2dArrayOES)
   8222            {
   8223                context->validationError(entryPoint, GL_INVALID_ENUM,
   8224                                         kMultisampleArrayExtensionRequired);
   8225                return false;
   8226            }
   8227            break;
   8228        default:
   8229            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
   8230            return false;
   8231    }
   8232 
   8233    if (bufSize < 0)
   8234    {
   8235        context->validationError(entryPoint, GL_INVALID_VALUE, kInsufficientBufferSize);
   8236        return false;
   8237    }
   8238 
   8239    GLsizei maxWriteParams = 0;
   8240    switch (pname)
   8241    {
   8242        case GL_NUM_SAMPLE_COUNTS:
   8243            maxWriteParams = 1;
   8244            break;
   8245 
   8246        case GL_SAMPLES:
   8247            maxWriteParams = static_cast<GLsizei>(formatCaps.sampleCounts.size());
   8248            break;
   8249 
   8250        default:
   8251            context->validationErrorF(entryPoint, GL_INVALID_ENUM, kEnumNotSupported, pname);
   8252            return false;
   8253    }
   8254 
   8255    if (numParams)
   8256    {
   8257        // glGetInternalFormativ will not overflow bufSize
   8258        *numParams = std::min(bufSize, maxWriteParams);
   8259    }
   8260 
   8261    return true;
   8262 }
   8263 
   8264 bool ValidateFramebufferNotMultisampled(const Context *context,
   8265                                        angle::EntryPoint entryPoint,
   8266                                        const Framebuffer *framebuffer,
   8267                                        bool checkReadBufferResourceSamples)
   8268 {
   8269    int samples = checkReadBufferResourceSamples
   8270                      ? framebuffer->getReadBufferResourceSamples(context)
   8271                      : framebuffer->getSamples(context);
   8272    if (samples != 0)
   8273    {
   8274        context->validationError(entryPoint, GL_INVALID_OPERATION,
   8275                                 kInvalidMultisampledFramebufferOperation);
   8276        return false;
   8277    }
   8278    return true;
   8279 }
   8280 
   8281 bool ValidateMultitextureUnit(const Context *context, angle::EntryPoint entryPoint, GLenum texture)
   8282 {
   8283    if (texture < GL_TEXTURE0 || texture >= GL_TEXTURE0 + context->getCaps().maxMultitextureUnits)
   8284    {
   8285        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidMultitextureUnit);
   8286        return false;
   8287    }
   8288    return true;
   8289 }
   8290 
   8291 bool ValidateTexStorageMultisample(const Context *context,
   8292                                   angle::EntryPoint entryPoint,
   8293                                   TextureType target,
   8294                                   GLsizei samples,
   8295                                   GLint internalFormat,
   8296                                   GLsizei width,
   8297                                   GLsizei height)
   8298 {
   8299    const Caps &caps = context->getCaps();
   8300    if (width > caps.max2DTextureSize || height > caps.max2DTextureSize)
   8301    {
   8302        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureWidthOrHeightOutOfRange);
   8303        return false;
   8304    }
   8305 
   8306    if (samples == 0)
   8307    {
   8308        context->validationError(entryPoint, GL_INVALID_VALUE, kSamplesZero);
   8309        return false;
   8310    }
   8311 
   8312    const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
   8313    if (!formatCaps.textureAttachment)
   8314    {
   8315        context->validationError(entryPoint, GL_INVALID_ENUM, kRenderableInternalFormat);
   8316        return false;
   8317    }
   8318 
   8319    // The ES3.1 spec(section 8.8) states that an INVALID_ENUM error is generated if internalformat
   8320    // is one of the unsized base internalformats listed in table 8.11.
   8321    const InternalFormat &formatInfo = GetSizedInternalFormatInfo(internalFormat);
   8322    if (formatInfo.internalFormat == GL_NONE)
   8323    {
   8324        context->validationError(entryPoint, GL_INVALID_ENUM, kUnsizedInternalFormatUnsupported);
   8325        return false;
   8326    }
   8327 
   8328    if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
   8329    {
   8330        context->validationError(entryPoint, GL_INVALID_OPERATION, kSamplesOutOfRange);
   8331        return false;
   8332    }
   8333 
   8334    Texture *texture = context->getTextureByType(target);
   8335    if (!texture || texture->id().value == 0)
   8336    {
   8337        context->validationError(entryPoint, GL_INVALID_OPERATION, kZeroBoundToTarget);
   8338        return false;
   8339    }
   8340 
   8341    if (texture->getImmutableFormat())
   8342    {
   8343        context->validationError(entryPoint, GL_INVALID_OPERATION, kImmutableTextureBound);
   8344        return false;
   8345    }
   8346    return true;
   8347 }
   8348 
   8349 bool ValidateTexStorage2DMultisampleBase(const Context *context,
   8350                                         angle::EntryPoint entryPoint,
   8351                                         TextureType target,
   8352                                         GLsizei samples,
   8353                                         GLint internalFormat,
   8354                                         GLsizei width,
   8355                                         GLsizei height)
   8356 {
   8357    if (target != TextureType::_2DMultisample)
   8358    {
   8359        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTarget);
   8360        return false;
   8361    }
   8362 
   8363    if (width < 1 || height < 1)
   8364    {
   8365        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureSizeTooSmall);
   8366        return false;
   8367    }
   8368 
   8369    return ValidateTexStorageMultisample(context, entryPoint, target, samples, internalFormat,
   8370                                         width, height);
   8371 }
   8372 
   8373 bool ValidateGetTexLevelParameterBase(const Context *context,
   8374                                      angle::EntryPoint entryPoint,
   8375                                      TextureTarget target,
   8376                                      GLint level,
   8377                                      GLenum pname,
   8378                                      GLsizei *length)
   8379 {
   8380 
   8381    if (length)
   8382    {
   8383        *length = 0;
   8384    }
   8385 
   8386    TextureType type = TextureTargetToType(target);
   8387 
   8388    if (!ValidTexLevelDestinationTarget(context, type))
   8389    {
   8390        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   8391        return false;
   8392    }
   8393 
   8394    if (context->getTextureByType(type) == nullptr)
   8395    {
   8396        context->validationError(entryPoint, GL_INVALID_ENUM, kTextureNotBound);
   8397        return false;
   8398    }
   8399 
   8400    if (!ValidMipLevel(context, type, level))
   8401    {
   8402        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   8403        return false;
   8404    }
   8405 
   8406    switch (pname)
   8407    {
   8408        case GL_TEXTURE_RED_TYPE:
   8409        case GL_TEXTURE_GREEN_TYPE:
   8410        case GL_TEXTURE_BLUE_TYPE:
   8411        case GL_TEXTURE_ALPHA_TYPE:
   8412        case GL_TEXTURE_DEPTH_TYPE:
   8413        case GL_TEXTURE_RED_SIZE:
   8414        case GL_TEXTURE_GREEN_SIZE:
   8415        case GL_TEXTURE_BLUE_SIZE:
   8416        case GL_TEXTURE_ALPHA_SIZE:
   8417        case GL_TEXTURE_DEPTH_SIZE:
   8418        case GL_TEXTURE_STENCIL_SIZE:
   8419        case GL_TEXTURE_SHARED_SIZE:
   8420        case GL_TEXTURE_INTERNAL_FORMAT:
   8421        case GL_TEXTURE_WIDTH:
   8422        case GL_TEXTURE_HEIGHT:
   8423        case GL_TEXTURE_DEPTH:
   8424        case GL_TEXTURE_SAMPLES:
   8425        case GL_TEXTURE_FIXED_SAMPLE_LOCATIONS:
   8426        case GL_TEXTURE_COMPRESSED:
   8427            break;
   8428 
   8429        case GL_RESOURCE_INITIALIZED_ANGLE:
   8430            if (!context->getExtensions().robustResourceInitializationANGLE)
   8431            {
   8432                context->validationError(entryPoint, GL_INVALID_ENUM,
   8433                                         kRobustResourceInitializationExtensionRequired);
   8434                return false;
   8435            }
   8436            break;
   8437 
   8438        case GL_TEXTURE_BUFFER_DATA_STORE_BINDING:
   8439        case GL_TEXTURE_BUFFER_OFFSET:
   8440        case GL_TEXTURE_BUFFER_SIZE:
   8441            if (context->getClientVersion() < Version(3, 2) &&
   8442                !context->getExtensions().textureBufferAny())
   8443            {
   8444                context->validationError(entryPoint, GL_INVALID_ENUM,
   8445                                         kTextureBufferExtensionNotAvailable);
   8446                return false;
   8447            }
   8448            break;
   8449 
   8450        default:
   8451            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   8452            return false;
   8453    }
   8454 
   8455    if (length)
   8456    {
   8457        *length = 1;
   8458    }
   8459    return true;
   8460 }
   8461 
   8462 bool ValidateGetMultisamplefvBase(const Context *context,
   8463                                  angle::EntryPoint entryPoint,
   8464                                  GLenum pname,
   8465                                  GLuint index,
   8466                                  const GLfloat *val)
   8467 {
   8468    if (pname != GL_SAMPLE_POSITION)
   8469    {
   8470        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   8471        return false;
   8472    }
   8473 
   8474    Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
   8475    GLint samples            = framebuffer->getSamples(context);
   8476 
   8477    if (index >= static_cast<GLuint>(samples))
   8478    {
   8479        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsSamples);
   8480        return false;
   8481    }
   8482 
   8483    return true;
   8484 }
   8485 
   8486 bool ValidateSampleMaskiBase(const Context *context,
   8487                             angle::EntryPoint entryPoint,
   8488                             GLuint maskNumber,
   8489                             GLbitfield mask)
   8490 {
   8491    if (maskNumber >= static_cast<GLuint>(context->getCaps().maxSampleMaskWords))
   8492    {
   8493        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidSampleMaskNumber);
   8494        return false;
   8495    }
   8496 
   8497    return true;
   8498 }
   8499 
   8500 void RecordDrawAttribsError(const Context *context, angle::EntryPoint entryPoint)
   8501 {
   8502    // An overflow can happen when adding the offset. Check against a special constant.
   8503    if (context->getStateCache().getNonInstancedVertexElementLimit() ==
   8504            VertexAttribute::kIntegerOverflow ||
   8505        context->getStateCache().getInstancedVertexElementLimit() ==
   8506            VertexAttribute::kIntegerOverflow)
   8507    {
   8508        context->validationError(entryPoint, GL_INVALID_OPERATION, kIntegerOverflow);
   8509    }
   8510    else
   8511    {
   8512        // [OpenGL ES 3.0.2] section 2.9.4 page 40:
   8513        // We can return INVALID_OPERATION if our buffer does not have enough backing data.
   8514        context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientVertexBufferSize);
   8515    }
   8516 }
   8517 
   8518 bool ValidateLoseContextCHROMIUM(const Context *context,
   8519                                 angle::EntryPoint entryPoint,
   8520                                 GraphicsResetStatus current,
   8521                                 GraphicsResetStatus other)
   8522 {
   8523    if (!context->getExtensions().loseContextCHROMIUM)
   8524    {
   8525        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   8526        return false;
   8527    }
   8528 
   8529    switch (current)
   8530    {
   8531        case GraphicsResetStatus::GuiltyContextReset:
   8532        case GraphicsResetStatus::InnocentContextReset:
   8533        case GraphicsResetStatus::UnknownContextReset:
   8534            break;
   8535 
   8536        default:
   8537            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidResetStatus);
   8538    }
   8539 
   8540    switch (other)
   8541    {
   8542        case GraphicsResetStatus::GuiltyContextReset:
   8543        case GraphicsResetStatus::InnocentContextReset:
   8544        case GraphicsResetStatus::UnknownContextReset:
   8545            break;
   8546 
   8547        default:
   8548            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidResetStatus);
   8549    }
   8550 
   8551    return true;
   8552 }
   8553 
   8554 // GL_ANGLE_texture_storage_external
   8555 bool ValidateTexImage2DExternalANGLE(const Context *context,
   8556                                     angle::EntryPoint entryPoint,
   8557                                     TextureTarget target,
   8558                                     GLint level,
   8559                                     GLint internalformat,
   8560                                     GLsizei width,
   8561                                     GLsizei height,
   8562                                     GLint border,
   8563                                     GLenum format,
   8564                                     GLenum type)
   8565 {
   8566    if (!context->getExtensions().textureExternalUpdateANGLE)
   8567    {
   8568        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   8569        return false;
   8570    }
   8571 
   8572    if (!ValidTexture2DDestinationTarget(context, target) &&
   8573        !ValidTextureExternalTarget(context, target))
   8574    {
   8575        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   8576        return false;
   8577    }
   8578 
   8579    if (context->getClientMajorVersion() <= 2)
   8580    {
   8581        if (!ValidateES2TexImageParametersBase(context, entryPoint, target, level, internalformat,
   8582                                               false, false, 0, 0, width, height, border, format,
   8583                                               type, -1, nullptr))
   8584        {
   8585            return false;
   8586        }
   8587    }
   8588    else
   8589    {
   8590        if (!ValidateES3TexImageParametersBase(context, entryPoint, target, level, internalformat,
   8591                                               false, false, 0, 0, 0, width, height, 1, border,
   8592                                               format, type, -1, nullptr))
   8593        {
   8594            return false;
   8595        }
   8596    }
   8597 
   8598    return true;
   8599 }
   8600 
   8601 bool ValidateInvalidateTextureANGLE(const Context *context,
   8602                                    angle::EntryPoint entryPoint,
   8603                                    TextureType target)
   8604 {
   8605    if (!context->getExtensions().textureExternalUpdateANGLE)
   8606    {
   8607        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   8608        return false;
   8609    }
   8610 
   8611    if (!ValidTextureTarget(context, target) && !ValidTextureExternalTarget(context, target))
   8612    {
   8613        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidTextureTarget);
   8614        return false;
   8615    }
   8616 
   8617    return true;
   8618 }
   8619 
   8620 bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
   8621                                                const ProgramExecutable *programExecutable)
   8622 {
   8623    size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
   8624    const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
   8625    for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
   8626    {
   8627        const OffsetBindingPointer<Buffer> &buffer =
   8628            transformFeedback->getIndexedBuffer(programXfbIndex);
   8629        if (!buffer.get())
   8630        {
   8631            return false;
   8632        }
   8633    }
   8634 
   8635    return true;
   8636 }
   8637 
   8638 bool ValidateLogicOpCommon(const Context *context,
   8639                           angle::EntryPoint entryPoint,
   8640                           LogicalOperation opcodePacked)
   8641 {
   8642    switch (opcodePacked)
   8643    {
   8644        case LogicalOperation::And:
   8645        case LogicalOperation::AndInverted:
   8646        case LogicalOperation::AndReverse:
   8647        case LogicalOperation::Clear:
   8648        case LogicalOperation::Copy:
   8649        case LogicalOperation::CopyInverted:
   8650        case LogicalOperation::Equiv:
   8651        case LogicalOperation::Invert:
   8652        case LogicalOperation::Nand:
   8653        case LogicalOperation::Noop:
   8654        case LogicalOperation::Nor:
   8655        case LogicalOperation::Or:
   8656        case LogicalOperation::OrInverted:
   8657        case LogicalOperation::OrReverse:
   8658        case LogicalOperation::Set:
   8659        case LogicalOperation::Xor:
   8660            return true;
   8661        default:
   8662            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidLogicOp);
   8663            return false;
   8664    }
   8665 }
   8666 }  // namespace gl