tor-browser

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

validationES31.cpp (115998B)


      1 //
      2 // Copyright 2016 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 // validationES31.cpp: Validation functions for OpenGL ES 3.1 entry point parameters
      8 
      9 #include "libANGLE/validationES31_autogen.h"
     10 
     11 #include "libANGLE/Context.h"
     12 #include "libANGLE/ErrorStrings.h"
     13 #include "libANGLE/Framebuffer.h"
     14 #include "libANGLE/ProgramExecutable.h"
     15 #include "libANGLE/VertexArray.h"
     16 #include "libANGLE/validationES.h"
     17 #include "libANGLE/validationES2_autogen.h"
     18 #include "libANGLE/validationES31.h"
     19 #include "libANGLE/validationES3_autogen.h"
     20 
     21 #include "common/utilities.h"
     22 
     23 using namespace angle;
     24 
     25 namespace gl
     26 {
     27 using namespace err;
     28 
     29 namespace
     30 {
     31 
     32 bool ValidateNamedProgramInterface(GLenum programInterface)
     33 {
     34    switch (programInterface)
     35    {
     36        case GL_UNIFORM:
     37        case GL_UNIFORM_BLOCK:
     38        case GL_PROGRAM_INPUT:
     39        case GL_PROGRAM_OUTPUT:
     40        case GL_TRANSFORM_FEEDBACK_VARYING:
     41        case GL_BUFFER_VARIABLE:
     42        case GL_SHADER_STORAGE_BLOCK:
     43            return true;
     44        default:
     45            return false;
     46    }
     47 }
     48 
     49 bool ValidateLocationProgramInterface(GLenum programInterface)
     50 {
     51    switch (programInterface)
     52    {
     53        case GL_UNIFORM:
     54        case GL_PROGRAM_INPUT:
     55        case GL_PROGRAM_OUTPUT:
     56            return true;
     57        default:
     58            return false;
     59    }
     60 }
     61 
     62 bool ValidateProgramInterface(GLenum programInterface)
     63 {
     64    return (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
     65            ValidateNamedProgramInterface(programInterface));
     66 }
     67 
     68 bool ValidateProgramResourceProperty(const Context *context,
     69                                     angle::EntryPoint entryPoint,
     70                                     GLenum prop)
     71 {
     72    ASSERT(context);
     73    switch (prop)
     74    {
     75        case GL_ACTIVE_VARIABLES:
     76        case GL_BUFFER_BINDING:
     77        case GL_NUM_ACTIVE_VARIABLES:
     78 
     79        case GL_ARRAY_SIZE:
     80 
     81        case GL_ARRAY_STRIDE:
     82        case GL_BLOCK_INDEX:
     83        case GL_IS_ROW_MAJOR:
     84        case GL_MATRIX_STRIDE:
     85 
     86        case GL_ATOMIC_COUNTER_BUFFER_INDEX:
     87 
     88        case GL_BUFFER_DATA_SIZE:
     89 
     90        case GL_LOCATION:
     91 
     92        case GL_NAME_LENGTH:
     93 
     94        case GL_OFFSET:
     95 
     96        case GL_REFERENCED_BY_VERTEX_SHADER:
     97        case GL_REFERENCED_BY_FRAGMENT_SHADER:
     98        case GL_REFERENCED_BY_COMPUTE_SHADER:
     99 
    100        case GL_TOP_LEVEL_ARRAY_SIZE:
    101        case GL_TOP_LEVEL_ARRAY_STRIDE:
    102 
    103        case GL_TYPE:
    104            return true;
    105 
    106        case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
    107            return context->getExtensions().geometryShaderAny() ||
    108                   context->getClientVersion() >= ES_3_2;
    109 
    110        case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
    111        case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
    112        case GL_IS_PER_PATCH_EXT:
    113            return context->getExtensions().tessellationShaderEXT ||
    114                   context->getClientVersion() >= ES_3_2;
    115 
    116        case GL_LOCATION_INDEX_EXT:
    117            return context->getExtensions().blendFuncExtendedEXT;
    118 
    119        default:
    120            return false;
    121    }
    122 }
    123 
    124 // GLES 3.10 spec: Page 82 -- Table 7.2
    125 bool ValidateProgramResourcePropertyByInterface(GLenum prop, GLenum programInterface)
    126 {
    127    switch (prop)
    128    {
    129        case GL_ACTIVE_VARIABLES:
    130        case GL_BUFFER_BINDING:
    131        case GL_NUM_ACTIVE_VARIABLES:
    132        {
    133            switch (programInterface)
    134            {
    135                case GL_ATOMIC_COUNTER_BUFFER:
    136                case GL_SHADER_STORAGE_BLOCK:
    137                case GL_UNIFORM_BLOCK:
    138                    return true;
    139                default:
    140                    return false;
    141            }
    142        }
    143 
    144        case GL_ARRAY_SIZE:
    145        {
    146            switch (programInterface)
    147            {
    148                case GL_BUFFER_VARIABLE:
    149                case GL_PROGRAM_INPUT:
    150                case GL_PROGRAM_OUTPUT:
    151                case GL_TRANSFORM_FEEDBACK_VARYING:
    152                case GL_UNIFORM:
    153                    return true;
    154                default:
    155                    return false;
    156            }
    157        }
    158 
    159        case GL_ARRAY_STRIDE:
    160        case GL_BLOCK_INDEX:
    161        case GL_IS_ROW_MAJOR:
    162        case GL_MATRIX_STRIDE:
    163        {
    164            switch (programInterface)
    165            {
    166                case GL_BUFFER_VARIABLE:
    167                case GL_UNIFORM:
    168                    return true;
    169                default:
    170                    return false;
    171            }
    172        }
    173 
    174        case GL_ATOMIC_COUNTER_BUFFER_INDEX:
    175        {
    176            if (programInterface == GL_UNIFORM)
    177            {
    178                return true;
    179            }
    180            return false;
    181        }
    182 
    183        case GL_BUFFER_DATA_SIZE:
    184        {
    185            switch (programInterface)
    186            {
    187                case GL_ATOMIC_COUNTER_BUFFER:
    188                case GL_SHADER_STORAGE_BLOCK:
    189                case GL_UNIFORM_BLOCK:
    190                    return true;
    191                default:
    192                    return false;
    193            }
    194        }
    195 
    196        case GL_LOCATION:
    197        {
    198            return ValidateLocationProgramInterface(programInterface);
    199        }
    200 
    201        case GL_LOCATION_INDEX_EXT:
    202        {
    203            // EXT_blend_func_extended
    204            return (programInterface == GL_PROGRAM_OUTPUT);
    205        }
    206 
    207        case GL_NAME_LENGTH:
    208        {
    209            return ValidateNamedProgramInterface(programInterface);
    210        }
    211 
    212        case GL_OFFSET:
    213        {
    214            switch (programInterface)
    215            {
    216                case GL_BUFFER_VARIABLE:
    217                case GL_UNIFORM:
    218                    return true;
    219                default:
    220                    return false;
    221            }
    222        }
    223 
    224        case GL_REFERENCED_BY_VERTEX_SHADER:
    225        case GL_REFERENCED_BY_FRAGMENT_SHADER:
    226        case GL_REFERENCED_BY_COMPUTE_SHADER:
    227        case GL_REFERENCED_BY_GEOMETRY_SHADER_EXT:
    228        case GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT:
    229        case GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT:
    230        {
    231            switch (programInterface)
    232            {
    233                case GL_ATOMIC_COUNTER_BUFFER:
    234                case GL_BUFFER_VARIABLE:
    235                case GL_PROGRAM_INPUT:
    236                case GL_PROGRAM_OUTPUT:
    237                case GL_SHADER_STORAGE_BLOCK:
    238                case GL_UNIFORM:
    239                case GL_UNIFORM_BLOCK:
    240                    return true;
    241                default:
    242                    return false;
    243            }
    244        }
    245 
    246        case GL_TOP_LEVEL_ARRAY_SIZE:
    247        case GL_TOP_LEVEL_ARRAY_STRIDE:
    248        {
    249            if (programInterface == GL_BUFFER_VARIABLE)
    250            {
    251                return true;
    252            }
    253            return false;
    254        }
    255 
    256        case GL_TYPE:
    257        {
    258            switch (programInterface)
    259            {
    260                case GL_BUFFER_VARIABLE:
    261                case GL_PROGRAM_INPUT:
    262                case GL_PROGRAM_OUTPUT:
    263                case GL_TRANSFORM_FEEDBACK_VARYING:
    264                case GL_UNIFORM:
    265                    return true;
    266                default:
    267                    return false;
    268            }
    269        }
    270        case GL_IS_PER_PATCH_EXT:
    271            switch (programInterface)
    272            {
    273                case GL_PROGRAM_INPUT:
    274                case GL_PROGRAM_OUTPUT:
    275                    return true;
    276            }
    277            return false;
    278 
    279        default:
    280            return false;
    281    }
    282 }
    283 
    284 bool ValidateProgramResourceIndex(const Program *programObject,
    285                                  GLenum programInterface,
    286                                  GLuint index)
    287 {
    288    switch (programInterface)
    289    {
    290        case GL_PROGRAM_INPUT:
    291            return (index <
    292                    static_cast<GLuint>(programObject->getState().getProgramInputs().size()));
    293 
    294        case GL_PROGRAM_OUTPUT:
    295            return (index < static_cast<GLuint>(programObject->getOutputResourceCount()));
    296 
    297        case GL_UNIFORM:
    298            return (index < static_cast<GLuint>(programObject->getActiveUniformCount()));
    299 
    300        case GL_BUFFER_VARIABLE:
    301            return (index < static_cast<GLuint>(programObject->getActiveBufferVariableCount()));
    302 
    303        case GL_SHADER_STORAGE_BLOCK:
    304            return (index < static_cast<GLuint>(programObject->getActiveShaderStorageBlockCount()));
    305 
    306        case GL_UNIFORM_BLOCK:
    307            return (index < programObject->getActiveUniformBlockCount());
    308 
    309        case GL_ATOMIC_COUNTER_BUFFER:
    310            return (index < programObject->getActiveAtomicCounterBufferCount());
    311 
    312        case GL_TRANSFORM_FEEDBACK_VARYING:
    313            return (index < static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()));
    314 
    315        default:
    316            UNREACHABLE();
    317            return false;
    318    }
    319 }
    320 
    321 bool ValidateProgramUniformBase(const Context *context,
    322                                angle::EntryPoint entryPoint,
    323                                GLenum valueType,
    324                                ShaderProgramID program,
    325                                UniformLocation location,
    326                                GLsizei count)
    327 {
    328    const LinkedUniform *uniform = nullptr;
    329    Program *programObject       = GetValidProgram(context, entryPoint, program);
    330    return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
    331                                     &uniform) &&
    332           ValidateUniformValue(context, entryPoint, valueType, uniform->type);
    333 }
    334 
    335 bool ValidateProgramUniformMatrixBase(const Context *context,
    336                                      angle::EntryPoint entryPoint,
    337                                      GLenum valueType,
    338                                      ShaderProgramID program,
    339                                      UniformLocation location,
    340                                      GLsizei count,
    341                                      GLboolean transpose)
    342 {
    343    const LinkedUniform *uniform = nullptr;
    344    Program *programObject       = GetValidProgram(context, entryPoint, program);
    345    return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
    346                                     &uniform) &&
    347           ValidateUniformMatrixValue(context, entryPoint, valueType, uniform->type);
    348 }
    349 
    350 bool ValidateVertexAttribFormatCommon(const Context *context,
    351                                      angle::EntryPoint entryPoint,
    352                                      GLuint relativeOffset)
    353 {
    354    if (context->getClientVersion() < ES_3_1)
    355    {
    356        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
    357        return false;
    358    }
    359 
    360    const Caps &caps = context->getCaps();
    361    if (relativeOffset > static_cast<GLuint>(caps.maxVertexAttribRelativeOffset))
    362    {
    363        context->validationError(entryPoint, GL_INVALID_VALUE, kRelativeOffsetTooLarge);
    364        return false;
    365    }
    366 
    367    // [OpenGL ES 3.1] Section 10.3.1 page 243:
    368    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
    369    if (context->getState().getVertexArrayId().value == 0)
    370    {
    371        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
    372        return false;
    373    }
    374 
    375    return true;
    376 }
    377 
    378 }  // anonymous namespace
    379 
    380 bool ValidateGetBooleani_v(const Context *context,
    381                           angle::EntryPoint entryPoint,
    382                           GLenum target,
    383                           GLuint index,
    384                           const GLboolean *data)
    385 {
    386    if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny())
    387    {
    388        context->validationError(entryPoint, GL_INVALID_OPERATION,
    389                                 kES31OrDrawBuffersIndexedExtensionNotAvailable);
    390        return false;
    391    }
    392 
    393    if (!ValidateIndexedStateQuery(context, entryPoint, target, index, nullptr))
    394    {
    395        return false;
    396    }
    397 
    398    return true;
    399 }
    400 
    401 bool ValidateGetBooleani_vRobustANGLE(const Context *context,
    402                                      angle::EntryPoint entryPoint,
    403                                      GLenum target,
    404                                      GLuint index,
    405                                      GLsizei bufSize,
    406                                      const GLsizei *length,
    407                                      const GLboolean *data)
    408 {
    409    if (context->getClientVersion() < ES_3_1 && !context->getExtensions().drawBuffersIndexedAny())
    410    {
    411        context->validationError(entryPoint, GL_INVALID_OPERATION,
    412                                 kES31OrDrawBuffersIndexedExtensionNotAvailable);
    413        return false;
    414    }
    415 
    416    if (!ValidateRobustEntryPoint(context, entryPoint, bufSize))
    417    {
    418        return false;
    419    }
    420 
    421    GLsizei numParams = 0;
    422 
    423    if (!ValidateIndexedStateQuery(context, entryPoint, target, index, &numParams))
    424    {
    425        return false;
    426    }
    427 
    428    if (!ValidateRobustBufferSize(context, entryPoint, bufSize, numParams))
    429    {
    430        return false;
    431    }
    432 
    433    SetRobustLengthParam(length, numParams);
    434    return true;
    435 }
    436 
    437 bool ValidateDrawIndirectBase(const Context *context,
    438                              angle::EntryPoint entryPoint,
    439                              PrimitiveMode mode,
    440                              const void *indirect)
    441 {
    442    if (context->getClientVersion() < ES_3_1)
    443    {
    444        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
    445        return false;
    446    }
    447 
    448    // Here the third parameter 1 is only to pass the count validation.
    449    if (!ValidateDrawBase(context, entryPoint, mode))
    450    {
    451        return false;
    452    }
    453 
    454    const State &state = context->getState();
    455 
    456    // An INVALID_OPERATION error is generated if zero is bound to VERTEX_ARRAY_BINDING,
    457    // DRAW_INDIRECT_BUFFER or to any enabled vertex array.
    458    if (state.getVertexArrayId().value == 0)
    459    {
    460        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
    461        return false;
    462    }
    463 
    464    if (context->getStateCache().hasAnyActiveClientAttrib())
    465    {
    466        context->validationError(entryPoint, GL_INVALID_OPERATION, kClientDataInVertexArray);
    467        return false;
    468    }
    469 
    470    Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
    471    if (!drawIndirectBuffer)
    472    {
    473        context->validationError(entryPoint, GL_INVALID_OPERATION, kDrawIndirectBufferNotBound);
    474        return false;
    475    }
    476 
    477    // An INVALID_VALUE error is generated if indirect is not a multiple of the size, in basic
    478    // machine units, of uint.
    479    GLint64 offset = reinterpret_cast<GLint64>(indirect);
    480    if ((static_cast<GLuint>(offset) % sizeof(GLuint)) != 0)
    481    {
    482        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidIndirectOffset);
    483        return false;
    484    }
    485 
    486    return true;
    487 }
    488 
    489 bool ValidateDrawArraysIndirect(const Context *context,
    490                                angle::EntryPoint entryPoint,
    491                                PrimitiveMode mode,
    492                                const void *indirect)
    493 {
    494    const State &state                      = context->getState();
    495    TransformFeedback *curTransformFeedback = state.getCurrentTransformFeedback();
    496    if (curTransformFeedback && curTransformFeedback->isActive() &&
    497        !curTransformFeedback->isPaused())
    498    {
    499        // EXT_geometry_shader allows transform feedback to work with all draw commands.
    500        // [EXT_geometry_shader] Section 12.1, "Transform Feedback"
    501        if (context->getExtensions().geometryShaderAny() || context->getClientVersion() >= ES_3_2)
    502        {
    503            if (!ValidateTransformFeedbackPrimitiveMode(
    504                    context, entryPoint, curTransformFeedback->getPrimitiveMode(), mode))
    505            {
    506                context->validationError(entryPoint, GL_INVALID_OPERATION,
    507                                         kInvalidDrawModeTransformFeedback);
    508                return false;
    509            }
    510        }
    511        else
    512        {
    513            // An INVALID_OPERATION error is generated if transform feedback is active and not
    514            // paused.
    515            context->validationError(entryPoint, GL_INVALID_OPERATION,
    516                                     kUnsupportedDrawModeForTransformFeedback);
    517            return false;
    518        }
    519    }
    520 
    521    if (!ValidateDrawIndirectBase(context, entryPoint, mode, indirect))
    522        return false;
    523 
    524    Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
    525    CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
    526    // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawArraysIndirectCommand
    527    // which's size is 4 * sizeof(uint).
    528    auto checkedSum = checkedOffset + 4 * sizeof(GLuint);
    529    if (!checkedSum.IsValid() ||
    530        checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
    531    {
    532        context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow);
    533        return false;
    534    }
    535 
    536    return true;
    537 }
    538 
    539 bool ValidateDrawElementsIndirect(const Context *context,
    540                                  angle::EntryPoint entryPoint,
    541                                  PrimitiveMode mode,
    542                                  DrawElementsType type,
    543                                  const void *indirect)
    544 {
    545    if (!ValidateDrawElementsBase(context, entryPoint, mode, type))
    546    {
    547        return false;
    548    }
    549 
    550    const State &state         = context->getState();
    551    const VertexArray *vao     = state.getVertexArray();
    552    Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
    553    if (!elementArrayBuffer)
    554    {
    555        context->validationError(entryPoint, GL_INVALID_OPERATION, kMustHaveElementArrayBinding);
    556        return false;
    557    }
    558 
    559    if (!ValidateDrawIndirectBase(context, entryPoint, mode, indirect))
    560        return false;
    561 
    562    Buffer *drawIndirectBuffer = state.getTargetBuffer(BufferBinding::DrawIndirect);
    563    CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(indirect));
    564    // In OpenGL ES3.1 spec, session 10.5, it defines the struct of DrawElementsIndirectCommand
    565    // which's size is 5 * sizeof(uint).
    566    auto checkedSum = checkedOffset + 5 * sizeof(GLuint);
    567    if (!checkedSum.IsValid() ||
    568        checkedSum.ValueOrDie() > static_cast<size_t>(drawIndirectBuffer->getSize()))
    569    {
    570        context->validationError(entryPoint, GL_INVALID_OPERATION, kParamOverflow);
    571        return false;
    572    }
    573 
    574    return true;
    575 }
    576 
    577 bool ValidateMultiDrawIndirectBase(const Context *context,
    578                                   angle::EntryPoint entryPoint,
    579                                   GLsizei drawcount,
    580                                   GLsizei stride)
    581 {
    582    if (!context->getExtensions().multiDrawIndirectEXT)
    583    {
    584        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
    585        return false;
    586    }
    587 
    588    // An INVALID_VALUE error is generated if stride is neither 0 nor a multiple of 4.
    589    if ((stride & 3) != 0)
    590    {
    591        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidDrawBufferValue);
    592        return false;
    593    }
    594 
    595    // An INVALID_VALUE error is generated if drawcount is not positive.
    596    if (drawcount <= 0)
    597    {
    598        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidValueNonPositive);
    599        return false;
    600    }
    601 
    602    return true;
    603 }
    604 
    605 bool ValidateProgramUniform1iBase(const Context *context,
    606                                  angle::EntryPoint entryPoint,
    607                                  ShaderProgramID program,
    608                                  UniformLocation location,
    609                                  GLint v0)
    610 {
    611    return ValidateProgramUniform1ivBase(context, entryPoint, program, location, 1, &v0);
    612 }
    613 
    614 bool ValidateProgramUniform2iBase(const Context *context,
    615                                  angle::EntryPoint entryPoint,
    616                                  ShaderProgramID program,
    617                                  UniformLocation location,
    618                                  GLint v0,
    619                                  GLint v1)
    620 {
    621    GLint xy[2] = {v0, v1};
    622    return ValidateProgramUniform2ivBase(context, entryPoint, program, location, 1, xy);
    623 }
    624 
    625 bool ValidateProgramUniform3iBase(const Context *context,
    626                                  angle::EntryPoint entryPoint,
    627                                  ShaderProgramID program,
    628                                  UniformLocation location,
    629                                  GLint v0,
    630                                  GLint v1,
    631                                  GLint v2)
    632 {
    633    GLint xyz[3] = {v0, v1, v2};
    634    return ValidateProgramUniform3ivBase(context, entryPoint, program, location, 1, xyz);
    635 }
    636 
    637 bool ValidateProgramUniform4iBase(const Context *context,
    638                                  angle::EntryPoint entryPoint,
    639                                  ShaderProgramID program,
    640                                  UniformLocation location,
    641                                  GLint v0,
    642                                  GLint v1,
    643                                  GLint v2,
    644                                  GLint v3)
    645 {
    646    GLint xyzw[4] = {v0, v1, v2, v3};
    647    return ValidateProgramUniform4ivBase(context, entryPoint, program, location, 1, xyzw);
    648 }
    649 
    650 bool ValidateProgramUniform1uiBase(const Context *context,
    651                                   angle::EntryPoint entryPoint,
    652                                   ShaderProgramID program,
    653                                   UniformLocation location,
    654                                   GLuint v0)
    655 {
    656    return ValidateProgramUniform1uivBase(context, entryPoint, program, location, 1, &v0);
    657 }
    658 
    659 bool ValidateProgramUniform2uiBase(const Context *context,
    660                                   angle::EntryPoint entryPoint,
    661                                   ShaderProgramID program,
    662                                   UniformLocation location,
    663                                   GLuint v0,
    664                                   GLuint v1)
    665 {
    666    GLuint xy[2] = {v0, v1};
    667    return ValidateProgramUniform2uivBase(context, entryPoint, program, location, 1, xy);
    668 }
    669 
    670 bool ValidateProgramUniform3uiBase(const Context *context,
    671                                   angle::EntryPoint entryPoint,
    672                                   ShaderProgramID program,
    673                                   UniformLocation location,
    674                                   GLuint v0,
    675                                   GLuint v1,
    676                                   GLuint v2)
    677 {
    678    GLuint xyz[3] = {v0, v1, v2};
    679    return ValidateProgramUniform3uivBase(context, entryPoint, program, location, 1, xyz);
    680 }
    681 
    682 bool ValidateProgramUniform4uiBase(const Context *context,
    683                                   angle::EntryPoint entryPoint,
    684                                   ShaderProgramID program,
    685                                   UniformLocation location,
    686                                   GLuint v0,
    687                                   GLuint v1,
    688                                   GLuint v2,
    689                                   GLuint v3)
    690 {
    691    GLuint xyzw[4] = {v0, v1, v2, v3};
    692    return ValidateProgramUniform4uivBase(context, entryPoint, program, location, 1, xyzw);
    693 }
    694 
    695 bool ValidateProgramUniform1fBase(const Context *context,
    696                                  angle::EntryPoint entryPoint,
    697                                  ShaderProgramID program,
    698                                  UniformLocation location,
    699                                  GLfloat v0)
    700 {
    701    return ValidateProgramUniform1fvBase(context, entryPoint, program, location, 1, &v0);
    702 }
    703 
    704 bool ValidateProgramUniform2fBase(const Context *context,
    705                                  angle::EntryPoint entryPoint,
    706                                  ShaderProgramID program,
    707                                  UniformLocation location,
    708                                  GLfloat v0,
    709                                  GLfloat v1)
    710 {
    711    GLfloat xy[2] = {v0, v1};
    712    return ValidateProgramUniform2fvBase(context, entryPoint, program, location, 1, xy);
    713 }
    714 
    715 bool ValidateProgramUniform3fBase(const Context *context,
    716                                  angle::EntryPoint entryPoint,
    717                                  ShaderProgramID program,
    718                                  UniformLocation location,
    719                                  GLfloat v0,
    720                                  GLfloat v1,
    721                                  GLfloat v2)
    722 {
    723    GLfloat xyz[3] = {v0, v1, v2};
    724    return ValidateProgramUniform3fvBase(context, entryPoint, program, location, 1, xyz);
    725 }
    726 
    727 bool ValidateProgramUniform4fBase(const Context *context,
    728                                  angle::EntryPoint entryPoint,
    729                                  ShaderProgramID program,
    730                                  UniformLocation location,
    731                                  GLfloat v0,
    732                                  GLfloat v1,
    733                                  GLfloat v2,
    734                                  GLfloat v3)
    735 {
    736    GLfloat xyzw[4] = {v0, v1, v2, v3};
    737    return ValidateProgramUniform4fvBase(context, entryPoint, program, location, 1, xyzw);
    738 }
    739 
    740 bool ValidateProgramUniform1ivBase(const Context *context,
    741                                   angle::EntryPoint entryPoint,
    742                                   ShaderProgramID program,
    743                                   UniformLocation location,
    744                                   GLsizei count,
    745                                   const GLint *value)
    746 {
    747    const LinkedUniform *uniform = nullptr;
    748    Program *programObject       = GetValidProgram(context, entryPoint, program);
    749    return ValidateUniformCommonBase(context, entryPoint, programObject, location, count,
    750                                     &uniform) &&
    751           ValidateUniform1ivValue(context, entryPoint, uniform->type, count, value);
    752 }
    753 
    754 bool ValidateProgramUniform2ivBase(const Context *context,
    755                                   angle::EntryPoint entryPoint,
    756                                   ShaderProgramID program,
    757                                   UniformLocation location,
    758                                   GLsizei count,
    759                                   const GLint *value)
    760 {
    761    return ValidateProgramUniformBase(context, entryPoint, GL_INT_VEC2, program, location, count);
    762 }
    763 
    764 bool ValidateProgramUniform3ivBase(const Context *context,
    765                                   angle::EntryPoint entryPoint,
    766                                   ShaderProgramID program,
    767                                   UniformLocation location,
    768                                   GLsizei count,
    769                                   const GLint *value)
    770 {
    771    return ValidateProgramUniformBase(context, entryPoint, GL_INT_VEC3, program, location, count);
    772 }
    773 
    774 bool ValidateProgramUniform4ivBase(const Context *context,
    775                                   angle::EntryPoint entryPoint,
    776                                   ShaderProgramID program,
    777                                   UniformLocation location,
    778                                   GLsizei count,
    779                                   const GLint *value)
    780 {
    781    return ValidateProgramUniformBase(context, entryPoint, GL_INT_VEC4, program, location, count);
    782 }
    783 
    784 bool ValidateProgramUniform1uivBase(const Context *context,
    785                                    angle::EntryPoint entryPoint,
    786                                    ShaderProgramID program,
    787                                    UniformLocation location,
    788                                    GLsizei count,
    789                                    const GLuint *value)
    790 {
    791    return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT, program, location,
    792                                      count);
    793 }
    794 
    795 bool ValidateProgramUniform2uivBase(const Context *context,
    796                                    angle::EntryPoint entryPoint,
    797                                    ShaderProgramID program,
    798                                    UniformLocation location,
    799                                    GLsizei count,
    800                                    const GLuint *value)
    801 {
    802    return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT_VEC2, program, location,
    803                                      count);
    804 }
    805 
    806 bool ValidateProgramUniform3uivBase(const Context *context,
    807                                    angle::EntryPoint entryPoint,
    808                                    ShaderProgramID program,
    809                                    UniformLocation location,
    810                                    GLsizei count,
    811                                    const GLuint *value)
    812 {
    813    return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT_VEC3, program, location,
    814                                      count);
    815 }
    816 
    817 bool ValidateProgramUniform4uivBase(const Context *context,
    818                                    angle::EntryPoint entryPoint,
    819                                    ShaderProgramID program,
    820                                    UniformLocation location,
    821                                    GLsizei count,
    822                                    const GLuint *value)
    823 {
    824    return ValidateProgramUniformBase(context, entryPoint, GL_UNSIGNED_INT_VEC4, program, location,
    825                                      count);
    826 }
    827 
    828 bool ValidateProgramUniform1fvBase(const Context *context,
    829                                   angle::EntryPoint entryPoint,
    830                                   ShaderProgramID program,
    831                                   UniformLocation location,
    832                                   GLsizei count,
    833                                   const GLfloat *value)
    834 {
    835    return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT, program, location, count);
    836 }
    837 
    838 bool ValidateProgramUniform2fvBase(const Context *context,
    839                                   angle::EntryPoint entryPoint,
    840                                   ShaderProgramID program,
    841                                   UniformLocation location,
    842                                   GLsizei count,
    843                                   const GLfloat *value)
    844 {
    845    return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT_VEC2, program, location, count);
    846 }
    847 
    848 bool ValidateProgramUniform3fvBase(const Context *context,
    849                                   angle::EntryPoint entryPoint,
    850                                   ShaderProgramID program,
    851                                   UniformLocation location,
    852                                   GLsizei count,
    853                                   const GLfloat *value)
    854 {
    855    return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT_VEC3, program, location, count);
    856 }
    857 
    858 bool ValidateProgramUniform4fvBase(const Context *context,
    859                                   angle::EntryPoint entryPoint,
    860                                   ShaderProgramID program,
    861                                   UniformLocation location,
    862                                   GLsizei count,
    863                                   const GLfloat *value)
    864 {
    865    return ValidateProgramUniformBase(context, entryPoint, GL_FLOAT_VEC4, program, location, count);
    866 }
    867 
    868 bool ValidateProgramUniformMatrix2fvBase(const Context *context,
    869                                         angle::EntryPoint entryPoint,
    870                                         ShaderProgramID program,
    871                                         UniformLocation location,
    872                                         GLsizei count,
    873                                         GLboolean transpose,
    874                                         const GLfloat *value)
    875 {
    876    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT2, program, location,
    877                                            count, transpose);
    878 }
    879 
    880 bool ValidateProgramUniformMatrix3fvBase(const Context *context,
    881                                         angle::EntryPoint entryPoint,
    882                                         ShaderProgramID program,
    883                                         UniformLocation location,
    884                                         GLsizei count,
    885                                         GLboolean transpose,
    886                                         const GLfloat *value)
    887 {
    888    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT3, program, location,
    889                                            count, transpose);
    890 }
    891 
    892 bool ValidateProgramUniformMatrix4fvBase(const Context *context,
    893                                         angle::EntryPoint entryPoint,
    894                                         ShaderProgramID program,
    895                                         UniformLocation location,
    896                                         GLsizei count,
    897                                         GLboolean transpose,
    898                                         const GLfloat *value)
    899 {
    900    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT4, program, location,
    901                                            count, transpose);
    902 }
    903 
    904 bool ValidateProgramUniformMatrix2x3fvBase(const Context *context,
    905                                           angle::EntryPoint entryPoint,
    906                                           ShaderProgramID program,
    907                                           UniformLocation location,
    908                                           GLsizei count,
    909                                           GLboolean transpose,
    910                                           const GLfloat *value)
    911 {
    912    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT2x3, program, location,
    913                                            count, transpose);
    914 }
    915 
    916 bool ValidateProgramUniformMatrix3x2fvBase(const Context *context,
    917                                           angle::EntryPoint entryPoint,
    918                                           ShaderProgramID program,
    919                                           UniformLocation location,
    920                                           GLsizei count,
    921                                           GLboolean transpose,
    922                                           const GLfloat *value)
    923 {
    924    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT3x2, program, location,
    925                                            count, transpose);
    926 }
    927 
    928 bool ValidateProgramUniformMatrix2x4fvBase(const Context *context,
    929                                           angle::EntryPoint entryPoint,
    930                                           ShaderProgramID program,
    931                                           UniformLocation location,
    932                                           GLsizei count,
    933                                           GLboolean transpose,
    934                                           const GLfloat *value)
    935 {
    936    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT2x4, program, location,
    937                                            count, transpose);
    938 }
    939 
    940 bool ValidateProgramUniformMatrix4x2fvBase(const Context *context,
    941                                           angle::EntryPoint entryPoint,
    942                                           ShaderProgramID program,
    943                                           UniformLocation location,
    944                                           GLsizei count,
    945                                           GLboolean transpose,
    946                                           const GLfloat *value)
    947 {
    948    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT4x2, program, location,
    949                                            count, transpose);
    950 }
    951 
    952 bool ValidateProgramUniformMatrix3x4fvBase(const Context *context,
    953                                           angle::EntryPoint entryPoint,
    954                                           ShaderProgramID program,
    955                                           UniformLocation location,
    956                                           GLsizei count,
    957                                           GLboolean transpose,
    958                                           const GLfloat *value)
    959 {
    960    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT3x4, program, location,
    961                                            count, transpose);
    962 }
    963 
    964 bool ValidateProgramUniformMatrix4x3fvBase(const Context *context,
    965                                           angle::EntryPoint entryPoint,
    966                                           ShaderProgramID program,
    967                                           UniformLocation location,
    968                                           GLsizei count,
    969                                           GLboolean transpose,
    970                                           const GLfloat *value)
    971 {
    972    return ValidateProgramUniformMatrixBase(context, entryPoint, GL_FLOAT_MAT4x3, program, location,
    973                                            count, transpose);
    974 }
    975 
    976 bool ValidateGetTexLevelParameterfv(const Context *context,
    977                                    angle::EntryPoint entryPoint,
    978                                    TextureTarget target,
    979                                    GLint level,
    980                                    GLenum pname,
    981                                    const GLfloat *params)
    982 {
    983    if (context->getClientVersion() < ES_3_1)
    984    {
    985        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
    986        return false;
    987    }
    988 
    989    return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
    990 }
    991 
    992 bool ValidateGetTexLevelParameterfvRobustANGLE(const Context *context,
    993                                               angle::EntryPoint entryPoint,
    994                                               TextureTarget target,
    995                                               GLint level,
    996                                               GLenum pname,
    997                                               GLsizei bufSize,
    998                                               const GLsizei *length,
    999                                               const GLfloat *params)
   1000 {
   1001    UNIMPLEMENTED();
   1002    return false;
   1003 }
   1004 
   1005 bool ValidateGetTexLevelParameteriv(const Context *context,
   1006                                    angle::EntryPoint entryPoint,
   1007                                    TextureTarget target,
   1008                                    GLint level,
   1009                                    GLenum pname,
   1010                                    const GLint *params)
   1011 {
   1012    if (context->getClientVersion() < ES_3_1)
   1013    {
   1014        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1015        return false;
   1016    }
   1017 
   1018    return ValidateGetTexLevelParameterBase(context, entryPoint, target, level, pname, nullptr);
   1019 }
   1020 
   1021 bool ValidateGetTexLevelParameterivRobustANGLE(const Context *context,
   1022                                               angle::EntryPoint entryPoint,
   1023                                               TextureTarget target,
   1024                                               GLint level,
   1025                                               GLenum pname,
   1026                                               GLsizei bufSize,
   1027                                               const GLsizei *length,
   1028                                               const GLint *params)
   1029 {
   1030    UNIMPLEMENTED();
   1031    return false;
   1032 }
   1033 
   1034 bool ValidateTexStorage2DMultisample(const Context *context,
   1035                                     angle::EntryPoint entryPoint,
   1036                                     TextureType target,
   1037                                     GLsizei samples,
   1038                                     GLenum internalFormat,
   1039                                     GLsizei width,
   1040                                     GLsizei height,
   1041                                     GLboolean fixedSampleLocations)
   1042 {
   1043    if (context->getClientVersion() < ES_3_1)
   1044    {
   1045        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1046        return false;
   1047    }
   1048 
   1049    return ValidateTexStorage2DMultisampleBase(context, entryPoint, target, samples, internalFormat,
   1050                                               width, height);
   1051 }
   1052 
   1053 bool ValidateTexStorageMem2DMultisampleEXT(const Context *context,
   1054                                           angle::EntryPoint entryPoint,
   1055                                           TextureType target,
   1056                                           GLsizei samples,
   1057                                           GLenum internalFormat,
   1058                                           GLsizei width,
   1059                                           GLsizei height,
   1060                                           GLboolean fixedSampleLocations,
   1061                                           MemoryObjectID memory,
   1062                                           GLuint64 offset)
   1063 {
   1064    if (!context->getExtensions().memoryObjectEXT)
   1065    {
   1066        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   1067        return false;
   1068    }
   1069 
   1070    UNIMPLEMENTED();
   1071    return false;
   1072 }
   1073 
   1074 bool ValidateGetMultisamplefv(const Context *context,
   1075                              angle::EntryPoint entryPoint,
   1076                              GLenum pname,
   1077                              GLuint index,
   1078                              const GLfloat *val)
   1079 {
   1080    if (context->getClientVersion() < ES_3_1)
   1081    {
   1082        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1083        return false;
   1084    }
   1085 
   1086    return ValidateGetMultisamplefvBase(context, entryPoint, pname, index, val);
   1087 }
   1088 
   1089 bool ValidateGetMultisamplefvRobustANGLE(const Context *context,
   1090                                         angle::EntryPoint entryPoint,
   1091                                         GLenum pname,
   1092                                         GLuint index,
   1093                                         GLsizei bufSize,
   1094                                         const GLsizei *length,
   1095                                         const GLfloat *val)
   1096 {
   1097    UNIMPLEMENTED();
   1098    return false;
   1099 }
   1100 
   1101 bool ValidateFramebufferParameteri(const Context *context,
   1102                                   angle::EntryPoint entryPoint,
   1103                                   GLenum target,
   1104                                   GLenum pname,
   1105                                   GLint param)
   1106 {
   1107    if (context->getClientVersion() < ES_3_1)
   1108    {
   1109        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1110        return false;
   1111    }
   1112 
   1113    return ValidateFramebufferParameteriBase(context, entryPoint, target, pname, param);
   1114 }
   1115 
   1116 bool ValidateGetFramebufferParameteriv(const Context *context,
   1117                                       angle::EntryPoint entryPoint,
   1118                                       GLenum target,
   1119                                       GLenum pname,
   1120                                       const GLint *params)
   1121 {
   1122    if (context->getClientVersion() < ES_3_1)
   1123    {
   1124        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1125        return false;
   1126    }
   1127 
   1128    return ValidateGetFramebufferParameterivBase(context, entryPoint, target, pname, params);
   1129 }
   1130 
   1131 bool ValidateGetFramebufferParameterivRobustANGLE(const Context *context,
   1132                                                  angle::EntryPoint entryPoint,
   1133                                                  GLenum target,
   1134                                                  GLenum pname,
   1135                                                  GLsizei bufSize,
   1136                                                  const GLsizei *length,
   1137                                                  const GLint *params)
   1138 {
   1139    UNIMPLEMENTED();
   1140    return false;
   1141 }
   1142 
   1143 bool ValidateGetProgramResourceIndex(const Context *context,
   1144                                     angle::EntryPoint entryPoint,
   1145                                     ShaderProgramID program,
   1146                                     GLenum programInterface,
   1147                                     const GLchar *name)
   1148 {
   1149    if (context->getClientVersion() < ES_3_1)
   1150    {
   1151        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1152        return false;
   1153    }
   1154 
   1155    Program *programObject = GetValidProgram(context, entryPoint, program);
   1156    if (programObject == nullptr)
   1157    {
   1158        return false;
   1159    }
   1160 
   1161    if (!ValidateNamedProgramInterface(programInterface))
   1162    {
   1163        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
   1164        return false;
   1165    }
   1166 
   1167    return true;
   1168 }
   1169 
   1170 bool ValidateBindVertexBuffer(const Context *context,
   1171                              angle::EntryPoint entryPoint,
   1172                              GLuint bindingIndex,
   1173                              BufferID buffer,
   1174                              GLintptr offset,
   1175                              GLsizei stride)
   1176 {
   1177    if (context->getClientVersion() < ES_3_1)
   1178    {
   1179        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1180        return false;
   1181    }
   1182 
   1183    if (!context->isBufferGenerated(buffer))
   1184    {
   1185        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   1186        return false;
   1187    }
   1188 
   1189    const Caps &caps = context->getCaps();
   1190    if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
   1191    {
   1192        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
   1193        return false;
   1194    }
   1195 
   1196    if (offset < 0)
   1197    {
   1198        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   1199        return false;
   1200    }
   1201 
   1202    if (stride < 0 || stride > caps.maxVertexAttribStride)
   1203    {
   1204        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribStride);
   1205        return false;
   1206    }
   1207 
   1208    // [OpenGL ES 3.1] Section 10.3.1 page 244:
   1209    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
   1210    if (context->getState().getVertexArrayId().value == 0)
   1211    {
   1212        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
   1213        return false;
   1214    }
   1215 
   1216    return true;
   1217 }
   1218 
   1219 bool ValidateVertexBindingDivisor(const Context *context,
   1220                                  angle::EntryPoint entryPoint,
   1221                                  GLuint bindingIndex,
   1222                                  GLuint divisor)
   1223 {
   1224    if (context->getClientVersion() < ES_3_1)
   1225    {
   1226        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1227        return false;
   1228    }
   1229 
   1230    const Caps &caps = context->getCaps();
   1231    if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
   1232    {
   1233        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
   1234        return false;
   1235    }
   1236 
   1237    // [OpenGL ES 3.1] Section 10.3.1 page 243:
   1238    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
   1239    if (context->getState().getVertexArrayId().value == 0)
   1240    {
   1241        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
   1242        return false;
   1243    }
   1244 
   1245    return true;
   1246 }
   1247 
   1248 bool ValidateVertexAttribFormat(const Context *context,
   1249                                angle::EntryPoint entryPoint,
   1250                                GLuint attribindex,
   1251                                GLint size,
   1252                                VertexAttribType type,
   1253                                GLboolean normalized,
   1254                                GLuint relativeoffset)
   1255 {
   1256    if (!ValidateVertexAttribFormatCommon(context, entryPoint, relativeoffset))
   1257    {
   1258        return false;
   1259    }
   1260 
   1261    return ValidateFloatVertexFormat(context, entryPoint, attribindex, size, type);
   1262 }
   1263 
   1264 bool ValidateVertexAttribIFormat(const Context *context,
   1265                                 angle::EntryPoint entryPoint,
   1266                                 GLuint attribindex,
   1267                                 GLint size,
   1268                                 VertexAttribType type,
   1269                                 GLuint relativeoffset)
   1270 {
   1271    if (!ValidateVertexAttribFormatCommon(context, entryPoint, relativeoffset))
   1272    {
   1273        return false;
   1274    }
   1275 
   1276    return ValidateIntegerVertexFormat(context, entryPoint, attribindex, size, type);
   1277 }
   1278 
   1279 bool ValidateVertexAttribBinding(const Context *context,
   1280                                 angle::EntryPoint entryPoint,
   1281                                 GLuint attribIndex,
   1282                                 GLuint bindingIndex)
   1283 {
   1284    if (context->getClientVersion() < ES_3_1)
   1285    {
   1286        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1287        return false;
   1288    }
   1289 
   1290    // [OpenGL ES 3.1] Section 10.3.1 page 243:
   1291    // An INVALID_OPERATION error is generated if the default vertex array object is bound.
   1292    if (context->getState().getVertexArrayId().value == 0)
   1293    {
   1294        context->validationError(entryPoint, GL_INVALID_OPERATION, kDefaultVertexArray);
   1295        return false;
   1296    }
   1297 
   1298    const Caps &caps = context->getCaps();
   1299    if (attribIndex >= static_cast<GLuint>(caps.maxVertexAttributes))
   1300    {
   1301        context->validationError(entryPoint, GL_INVALID_VALUE, kIndexExceedsMaxVertexAttribute);
   1302        return false;
   1303    }
   1304 
   1305    if (bindingIndex >= static_cast<GLuint>(caps.maxVertexAttribBindings))
   1306    {
   1307        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxVertexAttribBindings);
   1308        return false;
   1309    }
   1310 
   1311    return true;
   1312 }
   1313 
   1314 bool ValidateGetProgramResourceName(const Context *context,
   1315                                    angle::EntryPoint entryPoint,
   1316                                    ShaderProgramID program,
   1317                                    GLenum programInterface,
   1318                                    GLuint index,
   1319                                    GLsizei bufSize,
   1320                                    const GLsizei *length,
   1321                                    const GLchar *name)
   1322 {
   1323    if (context->getClientVersion() < ES_3_1)
   1324    {
   1325        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1326        return false;
   1327    }
   1328 
   1329    Program *programObject = GetValidProgram(context, entryPoint, program);
   1330    if (programObject == nullptr)
   1331    {
   1332        return false;
   1333    }
   1334 
   1335    if (!ValidateNamedProgramInterface(programInterface))
   1336    {
   1337        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
   1338        return false;
   1339    }
   1340 
   1341    if (!ValidateProgramResourceIndex(programObject, programInterface, index))
   1342    {
   1343        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramResourceIndex);
   1344        return false;
   1345    }
   1346 
   1347    if (bufSize < 0)
   1348    {
   1349        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   1350        return false;
   1351    }
   1352 
   1353    return true;
   1354 }
   1355 
   1356 bool ValidateDispatchCompute(const Context *context,
   1357                             angle::EntryPoint entryPoint,
   1358                             GLuint numGroupsX,
   1359                             GLuint numGroupsY,
   1360                             GLuint numGroupsZ)
   1361 {
   1362    if (context->getClientVersion() < ES_3_1)
   1363    {
   1364        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1365        return false;
   1366    }
   1367 
   1368    const State &state                  = context->getState();
   1369    const ProgramExecutable *executable = state.getProgramExecutable();
   1370 
   1371    if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
   1372    {
   1373        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1374                                 kNoActiveProgramWithComputeShader);
   1375        return false;
   1376    }
   1377 
   1378    const Caps &caps = context->getCaps();
   1379    if (numGroupsX > static_cast<GLuint>(caps.maxComputeWorkGroupCount[0]))
   1380    {
   1381        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsComputeWorkGroupCountX);
   1382        return false;
   1383    }
   1384    if (numGroupsY > static_cast<GLuint>(caps.maxComputeWorkGroupCount[1]))
   1385    {
   1386        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsComputeWorkGroupCountY);
   1387        return false;
   1388    }
   1389    if (numGroupsZ > static_cast<GLuint>(caps.maxComputeWorkGroupCount[2]))
   1390    {
   1391        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsComputeWorkGroupCountZ);
   1392        return false;
   1393    }
   1394 
   1395    return true;
   1396 }
   1397 
   1398 bool ValidateDispatchComputeIndirect(const Context *context,
   1399                                     angle::EntryPoint entryPoint,
   1400                                     GLintptr indirect)
   1401 {
   1402    if (context->getClientVersion() < ES_3_1)
   1403    {
   1404        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1405        return false;
   1406    }
   1407 
   1408    const State &state                  = context->getState();
   1409    const ProgramExecutable *executable = state.getProgramExecutable();
   1410 
   1411    if (executable == nullptr || !executable->hasLinkedShaderStage(ShaderType::Compute))
   1412    {
   1413        context->validationError(entryPoint, GL_INVALID_OPERATION,
   1414                                 kNoActiveProgramWithComputeShader);
   1415        return false;
   1416    }
   1417 
   1418    if (indirect < 0)
   1419    {
   1420        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeOffset);
   1421        return false;
   1422    }
   1423 
   1424    if ((indirect & (sizeof(GLuint) - 1)) != 0)
   1425    {
   1426        context->validationError(entryPoint, GL_INVALID_VALUE, kOffsetMustBeMultipleOfUint);
   1427        return false;
   1428    }
   1429 
   1430    Buffer *dispatchIndirectBuffer = state.getTargetBuffer(BufferBinding::DispatchIndirect);
   1431    if (!dispatchIndirectBuffer)
   1432    {
   1433        context->validationError(entryPoint, GL_INVALID_OPERATION, kDispatchIndirectBufferNotBound);
   1434        return false;
   1435    }
   1436 
   1437    CheckedNumeric<GLuint64> checkedOffset(static_cast<GLuint64>(indirect));
   1438    auto checkedSum = checkedOffset + static_cast<GLuint64>(3 * sizeof(GLuint));
   1439    if (!checkedSum.IsValid() ||
   1440        checkedSum.ValueOrDie() > static_cast<GLuint64>(dispatchIndirectBuffer->getSize()))
   1441    {
   1442        context->validationError(entryPoint, GL_INVALID_OPERATION, kInsufficientBufferSize);
   1443        return false;
   1444    }
   1445 
   1446    return true;
   1447 }
   1448 
   1449 bool ValidateBindImageTexture(const Context *context,
   1450                              angle::EntryPoint entryPoint,
   1451                              GLuint unit,
   1452                              TextureID texture,
   1453                              GLint level,
   1454                              GLboolean layered,
   1455                              GLint layer,
   1456                              GLenum access,
   1457                              GLenum format)
   1458 {
   1459    if (context->getClientVersion() < ES_3_1)
   1460    {
   1461        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1462        return false;
   1463    }
   1464 
   1465    GLuint maxImageUnits = static_cast<GLuint>(context->getCaps().maxImageUnits);
   1466    if (unit >= maxImageUnits)
   1467    {
   1468        context->validationError(entryPoint, GL_INVALID_VALUE, kExceedsMaxImageUnits);
   1469        return false;
   1470    }
   1471 
   1472    if (level < 0)
   1473    {
   1474        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLevel);
   1475        return false;
   1476    }
   1477 
   1478    if (layer < 0)
   1479    {
   1480        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeLayer);
   1481        return false;
   1482    }
   1483 
   1484    if (access != GL_READ_ONLY && access != GL_WRITE_ONLY && access != GL_READ_WRITE)
   1485    {
   1486        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidImageAccess);
   1487        return false;
   1488    }
   1489 
   1490    switch (format)
   1491    {
   1492        case GL_RGBA32F:
   1493        case GL_RGBA16F:
   1494        case GL_R32F:
   1495        case GL_RGBA32UI:
   1496        case GL_RGBA16UI:
   1497        case GL_RGBA8UI:
   1498        case GL_R32UI:
   1499        case GL_RGBA32I:
   1500        case GL_RGBA16I:
   1501        case GL_RGBA8I:
   1502        case GL_R32I:
   1503        case GL_RGBA8:
   1504        case GL_RGBA8_SNORM:
   1505            break;
   1506        default:
   1507            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidImageFormat);
   1508            return false;
   1509    }
   1510 
   1511    if (texture.value != 0)
   1512    {
   1513        Texture *tex = context->getTexture(texture);
   1514 
   1515        if (tex == nullptr)
   1516        {
   1517            context->validationError(entryPoint, GL_INVALID_VALUE, kMissingTextureName);
   1518            return false;
   1519        }
   1520 
   1521        if (!tex->getImmutableFormat() && tex->getType() != gl::TextureType::Buffer)
   1522        {
   1523            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1524                                     kTextureIsNeitherImmutableNorTextureBuffer);
   1525            return false;
   1526        }
   1527    }
   1528 
   1529    return true;
   1530 }
   1531 
   1532 bool ValidateGetProgramResourceLocation(const Context *context,
   1533                                        angle::EntryPoint entryPoint,
   1534                                        ShaderProgramID program,
   1535                                        GLenum programInterface,
   1536                                        const GLchar *name)
   1537 {
   1538    if (context->getClientVersion() < ES_3_1)
   1539    {
   1540        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1541        return false;
   1542    }
   1543 
   1544    Program *programObject = GetValidProgram(context, entryPoint, program);
   1545    if (programObject == nullptr)
   1546    {
   1547        return false;
   1548    }
   1549 
   1550    if (!programObject->isLinked())
   1551    {
   1552        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   1553        return false;
   1554    }
   1555 
   1556    if (!ValidateLocationProgramInterface(programInterface))
   1557    {
   1558        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
   1559        return false;
   1560    }
   1561    return true;
   1562 }
   1563 
   1564 bool ValidateGetProgramResourceiv(const Context *context,
   1565                                  angle::EntryPoint entryPoint,
   1566                                  ShaderProgramID program,
   1567                                  GLenum programInterface,
   1568                                  GLuint index,
   1569                                  GLsizei propCount,
   1570                                  const GLenum *props,
   1571                                  GLsizei bufSize,
   1572                                  const GLsizei *length,
   1573                                  const GLint *params)
   1574 {
   1575    if (context->getClientVersion() < ES_3_1)
   1576    {
   1577        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1578        return false;
   1579    }
   1580 
   1581    Program *programObject = GetValidProgram(context, entryPoint, program);
   1582    if (programObject == nullptr)
   1583    {
   1584        return false;
   1585    }
   1586    if (!ValidateProgramInterface(programInterface))
   1587    {
   1588        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
   1589        return false;
   1590    }
   1591    if (propCount <= 0)
   1592    {
   1593        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidPropCount);
   1594        return false;
   1595    }
   1596    if (bufSize < 0)
   1597    {
   1598        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufSize);
   1599        return false;
   1600    }
   1601    if (!ValidateProgramResourceIndex(programObject, programInterface, index))
   1602    {
   1603        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidProgramResourceIndex);
   1604        return false;
   1605    }
   1606    for (GLsizei i = 0; i < propCount; i++)
   1607    {
   1608        if (!ValidateProgramResourceProperty(context, entryPoint, props[i]))
   1609        {
   1610            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramResourceProperty);
   1611            return false;
   1612        }
   1613        if (!ValidateProgramResourcePropertyByInterface(props[i], programInterface))
   1614        {
   1615            context->validationError(entryPoint, GL_INVALID_OPERATION,
   1616                                     kInvalidPropertyForProgramInterface);
   1617            return false;
   1618        }
   1619    }
   1620    return true;
   1621 }
   1622 
   1623 bool ValidateGetProgramInterfaceiv(const Context *context,
   1624                                   angle::EntryPoint entryPoint,
   1625                                   ShaderProgramID program,
   1626                                   GLenum programInterface,
   1627                                   GLenum pname,
   1628                                   const GLint *params)
   1629 {
   1630    if (context->getClientVersion() < ES_3_1)
   1631    {
   1632        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1633        return false;
   1634    }
   1635 
   1636    Program *programObject = GetValidProgram(context, entryPoint, program);
   1637    if (programObject == nullptr)
   1638    {
   1639        return false;
   1640    }
   1641 
   1642    if (!ValidateProgramInterface(programInterface))
   1643    {
   1644        context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidProgramInterface);
   1645        return false;
   1646    }
   1647 
   1648    switch (pname)
   1649    {
   1650        case GL_ACTIVE_RESOURCES:
   1651        case GL_MAX_NAME_LENGTH:
   1652        case GL_MAX_NUM_ACTIVE_VARIABLES:
   1653            break;
   1654 
   1655        default:
   1656            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   1657            return false;
   1658    }
   1659 
   1660    if (pname == GL_MAX_NAME_LENGTH && programInterface == GL_ATOMIC_COUNTER_BUFFER)
   1661    {
   1662        context->validationError(entryPoint, GL_INVALID_OPERATION, kAtomicCounterResourceName);
   1663        return false;
   1664    }
   1665 
   1666    if (pname == GL_MAX_NUM_ACTIVE_VARIABLES)
   1667    {
   1668        switch (programInterface)
   1669        {
   1670            case GL_ATOMIC_COUNTER_BUFFER:
   1671            case GL_SHADER_STORAGE_BLOCK:
   1672            case GL_UNIFORM_BLOCK:
   1673                break;
   1674 
   1675            default:
   1676                context->validationError(entryPoint, GL_INVALID_OPERATION,
   1677                                         kMaxActiveVariablesInterface);
   1678                return false;
   1679        }
   1680    }
   1681 
   1682    return true;
   1683 }
   1684 
   1685 bool ValidateGetProgramInterfaceivRobustANGLE(const Context *context,
   1686                                              angle::EntryPoint entryPoint,
   1687                                              ShaderProgramID program,
   1688                                              GLenum programInterface,
   1689                                              GLenum pname,
   1690                                              GLsizei bufSize,
   1691                                              const GLsizei *length,
   1692                                              const GLint *params)
   1693 {
   1694    UNIMPLEMENTED();
   1695    return false;
   1696 }
   1697 
   1698 bool ValidateGenProgramPipelinesBase(const Context *context,
   1699                                     angle::EntryPoint entryPoint,
   1700                                     GLsizei n,
   1701                                     const ProgramPipelineID *pipelines)
   1702 {
   1703    return ValidateGenOrDelete(context, entryPoint, n);
   1704 }
   1705 
   1706 bool ValidateDeleteProgramPipelinesBase(const Context *context,
   1707                                        angle::EntryPoint entryPoint,
   1708                                        GLsizei n,
   1709                                        const ProgramPipelineID *pipelines)
   1710 {
   1711    return ValidateGenOrDelete(context, entryPoint, n);
   1712 }
   1713 
   1714 bool ValidateBindProgramPipelineBase(const Context *context,
   1715                                     angle::EntryPoint entryPoint,
   1716                                     ProgramPipelineID pipeline)
   1717 {
   1718    if (!context->isProgramPipelineGenerated({pipeline}))
   1719    {
   1720        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   1721        return false;
   1722    }
   1723 
   1724    return true;
   1725 }
   1726 
   1727 bool ValidateIsProgramPipelineBase(const Context *context,
   1728                                   angle::EntryPoint entryPoint,
   1729                                   ProgramPipelineID pipeline)
   1730 {
   1731    return true;
   1732 }
   1733 
   1734 bool ValidateUseProgramStagesBase(const Context *context,
   1735                                  angle::EntryPoint entryPoint,
   1736                                  ProgramPipelineID pipeline,
   1737                                  GLbitfield stages,
   1738                                  ShaderProgramID programId)
   1739 {
   1740    // GL_INVALID_VALUE is generated if shaders contains set bits that are not recognized, and is
   1741    // not the reserved value GL_ALL_SHADER_BITS.
   1742    GLbitfield knownShaderBits =
   1743        GL_VERTEX_SHADER_BIT | GL_FRAGMENT_SHADER_BIT | GL_COMPUTE_SHADER_BIT;
   1744 
   1745    if (context->getClientVersion() >= ES_3_2 || context->getExtensions().geometryShaderAny())
   1746    {
   1747        knownShaderBits |= GL_GEOMETRY_SHADER_BIT;
   1748    }
   1749 
   1750    if (context->getClientVersion() >= ES_3_2 || context->getExtensions().tessellationShaderEXT)
   1751    {
   1752        knownShaderBits |= GL_TESS_CONTROL_SHADER_BIT;
   1753        knownShaderBits |= GL_TESS_EVALUATION_SHADER_BIT;
   1754    }
   1755 
   1756    if ((stages & ~knownShaderBits) && (stages != GL_ALL_SHADER_BITS))
   1757    {
   1758        context->validationError(entryPoint, GL_INVALID_VALUE, kUnrecognizedShaderStageBit);
   1759        return false;
   1760    }
   1761 
   1762    // GL_INVALID_OPERATION is generated if pipeline is not a name previously returned from a call
   1763    // to glGenProgramPipelines or if such a name has been deleted by a call to
   1764    // glDeleteProgramPipelines.
   1765    if (!context->isProgramPipelineGenerated({pipeline}))
   1766    {
   1767        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   1768        return false;
   1769    }
   1770 
   1771    // If program is zero, or refers to a program object with no valid shader executable for a given
   1772    // stage, it is as if the pipeline object has no programmable stage configured for the indicated
   1773    // shader stages.
   1774    if (programId.value == 0)
   1775    {
   1776        return true;
   1777    }
   1778 
   1779    Program *program = context->getProgramNoResolveLink(programId);
   1780    if (!program)
   1781    {
   1782        context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist);
   1783        return false;
   1784    }
   1785 
   1786    // GL_INVALID_OPERATION is generated if program refers to a program object that was not linked
   1787    // with its GL_PROGRAM_SEPARABLE status set.
   1788    // resolveLink() may not have been called if glCreateShaderProgramv() was not used and
   1789    // glDetachShader() was not called.
   1790    program->resolveLink(context);
   1791    if (!program->isSeparable())
   1792    {
   1793        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotSeparable);
   1794        return false;
   1795    }
   1796 
   1797    // GL_INVALID_OPERATION is generated if program refers to a program object that has not been
   1798    // successfully linked.
   1799    if (!program->isLinked())
   1800    {
   1801        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   1802        return false;
   1803    }
   1804 
   1805    return true;
   1806 }
   1807 
   1808 bool ValidateActiveShaderProgramBase(const Context *context,
   1809                                     angle::EntryPoint entryPoint,
   1810                                     ProgramPipelineID pipeline,
   1811                                     ShaderProgramID programId)
   1812 {
   1813    // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
   1814    // call to GenProgramPipelines or if such a name has since been deleted by
   1815    // DeleteProgramPipelines.
   1816    if (!context->isProgramPipelineGenerated({pipeline}))
   1817    {
   1818        context->validationError(entryPoint, GL_INVALID_OPERATION, kObjectNotGenerated);
   1819        return false;
   1820    }
   1821 
   1822    // An INVALID_VALUE error is generated if program is not zero and is not the name of either a
   1823    // program or shader object.
   1824    if ((programId.value != 0) && !context->isProgram(programId) && !context->isShader(programId))
   1825    {
   1826        context->validationError(entryPoint, GL_INVALID_VALUE, kProgramDoesNotExist);
   1827        return false;
   1828    }
   1829 
   1830    // An INVALID_OPERATION error is generated if program is the name of a shader object.
   1831    if (context->isShader(programId))
   1832    {
   1833        context->validationError(entryPoint, GL_INVALID_OPERATION, kExpectedProgramName);
   1834        return false;
   1835    }
   1836 
   1837    // An INVALID_OPERATION error is generated if program is not zero and has not been linked, or
   1838    // was last linked unsuccessfully. The active program is not modified.
   1839    Program *program = context->getProgramNoResolveLink(programId);
   1840    if ((programId.value != 0) && !program->isLinked())
   1841    {
   1842        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   1843        return false;
   1844    }
   1845 
   1846    return true;
   1847 }
   1848 
   1849 bool ValidateCreateShaderProgramvBase(const Context *context,
   1850                                      angle::EntryPoint entryPoint,
   1851                                      ShaderType type,
   1852                                      GLsizei count,
   1853                                      const GLchar *const *strings)
   1854 {
   1855    switch (type)
   1856    {
   1857        case ShaderType::InvalidEnum:
   1858            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   1859            return false;
   1860        case ShaderType::Vertex:
   1861        case ShaderType::Fragment:
   1862        case ShaderType::Compute:
   1863            break;
   1864        case ShaderType::Geometry:
   1865            if (!context->getExtensions().geometryShaderAny() &&
   1866                context->getClientVersion() < ES_3_2)
   1867            {
   1868                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   1869                return false;
   1870            }
   1871            break;
   1872        case ShaderType::TessControl:
   1873        case ShaderType::TessEvaluation:
   1874            if (!context->getExtensions().tessellationShaderEXT &&
   1875                context->getClientVersion() < ES_3_2)
   1876            {
   1877                context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidShaderType);
   1878                return false;
   1879            }
   1880            break;
   1881        default:
   1882            UNREACHABLE();
   1883    }
   1884 
   1885    // GL_INVALID_VALUE is generated if count is negative.
   1886    if (count < 0)
   1887    {
   1888        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeCount);
   1889        return false;
   1890    }
   1891 
   1892    return true;
   1893 }
   1894 
   1895 bool ValidateCreateShaderProgramvBase(const Context *context,
   1896                                      angle::EntryPoint entryPoint,
   1897                                      ShaderType type,
   1898                                      GLsizei count,
   1899                                      const GLchar **strings)
   1900 {
   1901    const GLchar *const *tmpStrings = strings;
   1902    return ValidateCreateShaderProgramvBase(context, entryPoint, type, count, tmpStrings);
   1903 }
   1904 
   1905 bool ValidateGetProgramPipelineivBase(const Context *context,
   1906                                      angle::EntryPoint entryPoint,
   1907                                      ProgramPipelineID pipeline,
   1908                                      GLenum pname,
   1909                                      const GLint *params)
   1910 {
   1911    // An INVALID_OPERATION error is generated if pipeline is not a name returned from a previous
   1912    // call to GenProgramPipelines or if such a name has since been deleted by
   1913    // DeleteProgramPipelines.
   1914    if ((pipeline.value == 0) || (!context->isProgramPipelineGenerated(pipeline)))
   1915    {
   1916        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
   1917        return false;
   1918    }
   1919 
   1920    // An INVALID_ENUM error is generated if pname is not ACTIVE_PROGRAM,
   1921    // INFO_LOG_LENGTH, VALIDATE_STATUS, or one of the type arguments in
   1922    // table 7.1.
   1923    switch (pname)
   1924    {
   1925        case GL_ACTIVE_PROGRAM:
   1926        case GL_INFO_LOG_LENGTH:
   1927        case GL_VALIDATE_STATUS:
   1928        case GL_VERTEX_SHADER:
   1929        case GL_FRAGMENT_SHADER:
   1930        case GL_COMPUTE_SHADER:
   1931            break;
   1932        case GL_GEOMETRY_SHADER:
   1933            return context->getExtensions().geometryShaderAny() ||
   1934                   context->getClientVersion() >= ES_3_2;
   1935        case GL_TESS_CONTROL_SHADER:
   1936        case GL_TESS_EVALUATION_SHADER:
   1937            return context->getExtensions().tessellationShaderEXT ||
   1938                   context->getClientVersion() >= ES_3_2;
   1939 
   1940        default:
   1941            context->validationError(entryPoint, GL_INVALID_ENUM, kInvalidPname);
   1942            return false;
   1943    }
   1944 
   1945    return true;
   1946 }
   1947 
   1948 bool ValidateValidateProgramPipelineBase(const Context *context,
   1949                                         angle::EntryPoint entryPoint,
   1950                                         ProgramPipelineID pipeline)
   1951 {
   1952    if (pipeline.value == 0)
   1953    {
   1954        return false;
   1955    }
   1956 
   1957    if (!context->isProgramPipelineGenerated(pipeline))
   1958    {
   1959        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramPipelineDoesNotExist);
   1960        return false;
   1961    }
   1962 
   1963    return true;
   1964 }
   1965 
   1966 bool ValidateGetProgramPipelineInfoLogBase(const Context *context,
   1967                                           angle::EntryPoint entryPoint,
   1968                                           ProgramPipelineID pipeline,
   1969                                           GLsizei bufSize,
   1970                                           const GLsizei *length,
   1971                                           const GLchar *infoLog)
   1972 {
   1973    if (bufSize < 0)
   1974    {
   1975        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeBufferSize);
   1976        return false;
   1977    }
   1978 
   1979    if (!context->isProgramPipelineGenerated(pipeline))
   1980    {
   1981        context->validationError(entryPoint, GL_INVALID_VALUE, kProgramPipelineDoesNotExist);
   1982        return false;
   1983    }
   1984 
   1985    return true;
   1986 }
   1987 
   1988 bool ValidateActiveShaderProgram(const Context *context,
   1989                                 angle::EntryPoint entryPoint,
   1990                                 ProgramPipelineID pipelinePacked,
   1991                                 ShaderProgramID programPacked)
   1992 {
   1993    if (context->getClientVersion() < ES_3_1)
   1994    {
   1995        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   1996        return false;
   1997    }
   1998 
   1999    return ValidateActiveShaderProgramBase(context, entryPoint, pipelinePacked, programPacked);
   2000 }
   2001 
   2002 bool ValidateBindProgramPipeline(const Context *context,
   2003                                 angle::EntryPoint entryPoint,
   2004                                 ProgramPipelineID pipelinePacked)
   2005 {
   2006    if (context->getClientVersion() < ES_3_1)
   2007    {
   2008        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2009        return false;
   2010    }
   2011 
   2012    return ValidateBindProgramPipelineBase(context, entryPoint, pipelinePacked);
   2013 }
   2014 
   2015 bool ValidateCreateShaderProgramv(const Context *context,
   2016                                  angle::EntryPoint entryPoint,
   2017                                  ShaderType typePacked,
   2018                                  GLsizei count,
   2019                                  const GLchar *const *strings)
   2020 {
   2021    if (context->getClientVersion() < ES_3_1)
   2022    {
   2023        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2024        return false;
   2025    }
   2026 
   2027    return ValidateCreateShaderProgramvBase(context, entryPoint, typePacked, count, strings);
   2028 }
   2029 
   2030 bool ValidateDeleteProgramPipelines(const Context *context,
   2031                                    angle::EntryPoint entryPoint,
   2032                                    GLsizei n,
   2033                                    const ProgramPipelineID *pipelinesPacked)
   2034 {
   2035    if (context->getClientVersion() < ES_3_1)
   2036    {
   2037        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2038        return false;
   2039    }
   2040 
   2041    return ValidateDeleteProgramPipelinesBase(context, entryPoint, n, pipelinesPacked);
   2042 }
   2043 
   2044 bool ValidateGenProgramPipelines(const Context *context,
   2045                                 angle::EntryPoint entryPoint,
   2046                                 GLsizei n,
   2047                                 const ProgramPipelineID *pipelinesPacked)
   2048 {
   2049    if (context->getClientVersion() < ES_3_1)
   2050    {
   2051        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2052        return false;
   2053    }
   2054 
   2055    return ValidateGenProgramPipelinesBase(context, entryPoint, n, pipelinesPacked);
   2056 }
   2057 
   2058 bool ValidateGetProgramPipelineInfoLog(const Context *context,
   2059                                       angle::EntryPoint entryPoint,
   2060                                       ProgramPipelineID pipelinePacked,
   2061                                       GLsizei bufSize,
   2062                                       const GLsizei *length,
   2063                                       const GLchar *infoLog)
   2064 {
   2065    if (context->getClientVersion() < ES_3_1)
   2066    {
   2067        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2068        return false;
   2069    }
   2070 
   2071    return ValidateGetProgramPipelineInfoLogBase(context, entryPoint, pipelinePacked, bufSize,
   2072                                                 length, infoLog);
   2073 }
   2074 
   2075 bool ValidateGetProgramPipelineiv(const Context *context,
   2076                                  angle::EntryPoint entryPoint,
   2077                                  ProgramPipelineID pipelinePacked,
   2078                                  GLenum pname,
   2079                                  const GLint *params)
   2080 {
   2081    if (context->getClientVersion() < ES_3_1)
   2082    {
   2083        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2084        return false;
   2085    }
   2086 
   2087    return ValidateGetProgramPipelineivBase(context, entryPoint, pipelinePacked, pname, params);
   2088 }
   2089 
   2090 bool ValidateIsProgramPipeline(const Context *context,
   2091                               angle::EntryPoint entryPoint,
   2092                               ProgramPipelineID pipelinePacked)
   2093 {
   2094    if (context->getClientVersion() < ES_3_1)
   2095    {
   2096        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2097        return false;
   2098    }
   2099 
   2100    return ValidateIsProgramPipelineBase(context, entryPoint, pipelinePacked);
   2101 }
   2102 
   2103 bool ValidateProgramUniform1f(const Context *context,
   2104                              angle::EntryPoint entryPoint,
   2105                              ShaderProgramID programPacked,
   2106                              UniformLocation locationPacked,
   2107                              GLfloat v0)
   2108 {
   2109    if (context->getClientVersion() < ES_3_1)
   2110    {
   2111        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2112        return false;
   2113    }
   2114 
   2115    return ValidateProgramUniform1fBase(context, entryPoint, programPacked, locationPacked, v0);
   2116 }
   2117 
   2118 bool ValidateProgramUniform1fv(const Context *context,
   2119                               angle::EntryPoint entryPoint,
   2120                               ShaderProgramID programPacked,
   2121                               UniformLocation locationPacked,
   2122                               GLsizei count,
   2123                               const GLfloat *value)
   2124 {
   2125    if (context->getClientVersion() < ES_3_1)
   2126    {
   2127        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2128        return false;
   2129    }
   2130 
   2131    return ValidateProgramUniform1fvBase(context, entryPoint, programPacked, locationPacked, count,
   2132                                         value);
   2133 }
   2134 
   2135 bool ValidateProgramUniform1i(const Context *context,
   2136                              angle::EntryPoint entryPoint,
   2137                              ShaderProgramID programPacked,
   2138                              UniformLocation locationPacked,
   2139                              GLint v0)
   2140 {
   2141    if (context->getClientVersion() < ES_3_1)
   2142    {
   2143        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2144        return false;
   2145    }
   2146 
   2147    return ValidateProgramUniform1iBase(context, entryPoint, programPacked, locationPacked, v0);
   2148 }
   2149 
   2150 bool ValidateProgramUniform1iv(const Context *context,
   2151                               angle::EntryPoint entryPoint,
   2152                               ShaderProgramID programPacked,
   2153                               UniformLocation locationPacked,
   2154                               GLsizei count,
   2155                               const GLint *value)
   2156 {
   2157    if (context->getClientVersion() < ES_3_1)
   2158    {
   2159        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2160        return false;
   2161    }
   2162 
   2163    return ValidateProgramUniform1ivBase(context, entryPoint, programPacked, locationPacked, count,
   2164                                         value);
   2165 }
   2166 
   2167 bool ValidateProgramUniform1ui(const Context *context,
   2168                               angle::EntryPoint entryPoint,
   2169                               ShaderProgramID programPacked,
   2170                               UniformLocation locationPacked,
   2171                               GLuint v0)
   2172 {
   2173    if (context->getClientVersion() < ES_3_1)
   2174    {
   2175        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2176        return false;
   2177    }
   2178 
   2179    return ValidateProgramUniform1uiBase(context, entryPoint, programPacked, locationPacked, v0);
   2180 }
   2181 
   2182 bool ValidateProgramUniform1uiv(const Context *context,
   2183                                angle::EntryPoint entryPoint,
   2184                                ShaderProgramID programPacked,
   2185                                UniformLocation locationPacked,
   2186                                GLsizei count,
   2187                                const GLuint *value)
   2188 {
   2189    if (context->getClientVersion() < ES_3_1)
   2190    {
   2191        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2192        return false;
   2193    }
   2194 
   2195    return ValidateProgramUniform1uivBase(context, entryPoint, programPacked, locationPacked, count,
   2196                                          value);
   2197 }
   2198 
   2199 bool ValidateProgramUniform2f(const Context *context,
   2200                              angle::EntryPoint entryPoint,
   2201                              ShaderProgramID programPacked,
   2202                              UniformLocation locationPacked,
   2203                              GLfloat v0,
   2204                              GLfloat v1)
   2205 {
   2206    if (context->getClientVersion() < ES_3_1)
   2207    {
   2208        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2209        return false;
   2210    }
   2211 
   2212    return ValidateProgramUniform2fBase(context, entryPoint, programPacked, locationPacked, v0, v1);
   2213 }
   2214 
   2215 bool ValidateProgramUniform2fv(const Context *context,
   2216                               angle::EntryPoint entryPoint,
   2217                               ShaderProgramID programPacked,
   2218                               UniformLocation locationPacked,
   2219                               GLsizei count,
   2220                               const GLfloat *value)
   2221 {
   2222    if (context->getClientVersion() < ES_3_1)
   2223    {
   2224        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2225        return false;
   2226    }
   2227 
   2228    return ValidateProgramUniform2fvBase(context, entryPoint, programPacked, locationPacked, count,
   2229                                         value);
   2230 }
   2231 
   2232 bool ValidateProgramUniform2i(const Context *context,
   2233                              angle::EntryPoint entryPoint,
   2234                              ShaderProgramID programPacked,
   2235                              UniformLocation locationPacked,
   2236                              GLint v0,
   2237                              GLint v1)
   2238 {
   2239    if (context->getClientVersion() < ES_3_1)
   2240    {
   2241        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2242        return false;
   2243    }
   2244 
   2245    return ValidateProgramUniform2iBase(context, entryPoint, programPacked, locationPacked, v0, v1);
   2246 }
   2247 
   2248 bool ValidateProgramUniform2iv(const Context *context,
   2249                               angle::EntryPoint entryPoint,
   2250                               ShaderProgramID programPacked,
   2251                               UniformLocation locationPacked,
   2252                               GLsizei count,
   2253                               const GLint *value)
   2254 {
   2255    if (context->getClientVersion() < ES_3_1)
   2256    {
   2257        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2258        return false;
   2259    }
   2260 
   2261    return ValidateProgramUniform2ivBase(context, entryPoint, programPacked, locationPacked, count,
   2262                                         value);
   2263 }
   2264 
   2265 bool ValidateProgramUniform2ui(const Context *context,
   2266                               angle::EntryPoint entryPoint,
   2267                               ShaderProgramID programPacked,
   2268                               UniformLocation locationPacked,
   2269                               GLuint v0,
   2270                               GLuint v1)
   2271 {
   2272    if (context->getClientVersion() < ES_3_1)
   2273    {
   2274        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2275        return false;
   2276    }
   2277 
   2278    return ValidateProgramUniform2uiBase(context, entryPoint, programPacked, locationPacked, v0,
   2279                                         v1);
   2280 }
   2281 
   2282 bool ValidateProgramUniform2uiv(const Context *context,
   2283                                angle::EntryPoint entryPoint,
   2284                                ShaderProgramID programPacked,
   2285                                UniformLocation locationPacked,
   2286                                GLsizei count,
   2287                                const GLuint *value)
   2288 {
   2289    if (context->getClientVersion() < ES_3_1)
   2290    {
   2291        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2292        return false;
   2293    }
   2294 
   2295    return ValidateProgramUniform2uivBase(context, entryPoint, programPacked, locationPacked, count,
   2296                                          value);
   2297 }
   2298 
   2299 bool ValidateProgramUniform3f(const Context *context,
   2300                              angle::EntryPoint entryPoint,
   2301                              ShaderProgramID programPacked,
   2302                              UniformLocation locationPacked,
   2303                              GLfloat v0,
   2304                              GLfloat v1,
   2305                              GLfloat v2)
   2306 {
   2307    if (context->getClientVersion() < ES_3_1)
   2308    {
   2309        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2310        return false;
   2311    }
   2312 
   2313    return ValidateProgramUniform3fBase(context, entryPoint, programPacked, locationPacked, v0, v1,
   2314                                        v2);
   2315 }
   2316 
   2317 bool ValidateProgramUniform3fv(const Context *context,
   2318                               angle::EntryPoint entryPoint,
   2319                               ShaderProgramID programPacked,
   2320                               UniformLocation locationPacked,
   2321                               GLsizei count,
   2322                               const GLfloat *value)
   2323 {
   2324    if (context->getClientVersion() < ES_3_1)
   2325    {
   2326        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2327        return false;
   2328    }
   2329 
   2330    return ValidateProgramUniform3fvBase(context, entryPoint, programPacked, locationPacked, count,
   2331                                         value);
   2332 }
   2333 
   2334 bool ValidateProgramUniform3i(const Context *context,
   2335                              angle::EntryPoint entryPoint,
   2336                              ShaderProgramID programPacked,
   2337                              UniformLocation locationPacked,
   2338                              GLint v0,
   2339                              GLint v1,
   2340                              GLint v2)
   2341 {
   2342    if (context->getClientVersion() < ES_3_1)
   2343    {
   2344        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2345        return false;
   2346    }
   2347 
   2348    return ValidateProgramUniform3iBase(context, entryPoint, programPacked, locationPacked, v0, v1,
   2349                                        v2);
   2350 }
   2351 
   2352 bool ValidateProgramUniform3iv(const Context *context,
   2353                               angle::EntryPoint entryPoint,
   2354                               ShaderProgramID programPacked,
   2355                               UniformLocation locationPacked,
   2356                               GLsizei count,
   2357                               const GLint *value)
   2358 {
   2359    if (context->getClientVersion() < ES_3_1)
   2360    {
   2361        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2362        return false;
   2363    }
   2364 
   2365    return ValidateProgramUniform3ivBase(context, entryPoint, programPacked, locationPacked, count,
   2366                                         value);
   2367 }
   2368 
   2369 bool ValidateProgramUniform3ui(const Context *context,
   2370                               angle::EntryPoint entryPoint,
   2371                               ShaderProgramID programPacked,
   2372                               UniformLocation locationPacked,
   2373                               GLuint v0,
   2374                               GLuint v1,
   2375                               GLuint v2)
   2376 {
   2377    if (context->getClientVersion() < ES_3_1)
   2378    {
   2379        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2380        return false;
   2381    }
   2382 
   2383    return ValidateProgramUniform3uiBase(context, entryPoint, programPacked, locationPacked, v0, v1,
   2384                                         v2);
   2385 }
   2386 
   2387 bool ValidateProgramUniform3uiv(const Context *context,
   2388                                angle::EntryPoint entryPoint,
   2389                                ShaderProgramID programPacked,
   2390                                UniformLocation locationPacked,
   2391                                GLsizei count,
   2392                                const GLuint *value)
   2393 {
   2394    if (context->getClientVersion() < ES_3_1)
   2395    {
   2396        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2397        return false;
   2398    }
   2399 
   2400    return ValidateProgramUniform3uivBase(context, entryPoint, programPacked, locationPacked, count,
   2401                                          value);
   2402 }
   2403 
   2404 bool ValidateProgramUniform4f(const Context *context,
   2405                              angle::EntryPoint entryPoint,
   2406                              ShaderProgramID programPacked,
   2407                              UniformLocation locationPacked,
   2408                              GLfloat v0,
   2409                              GLfloat v1,
   2410                              GLfloat v2,
   2411                              GLfloat v3)
   2412 {
   2413    if (context->getClientVersion() < ES_3_1)
   2414    {
   2415        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2416        return false;
   2417    }
   2418 
   2419    return ValidateProgramUniform4fBase(context, entryPoint, programPacked, locationPacked, v0, v1,
   2420                                        v2, v3);
   2421 }
   2422 
   2423 bool ValidateProgramUniform4fv(const Context *context,
   2424                               angle::EntryPoint entryPoint,
   2425                               ShaderProgramID programPacked,
   2426                               UniformLocation locationPacked,
   2427                               GLsizei count,
   2428                               const GLfloat *value)
   2429 {
   2430    if (context->getClientVersion() < ES_3_1)
   2431    {
   2432        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2433        return false;
   2434    }
   2435 
   2436    return ValidateProgramUniform4fvBase(context, entryPoint, programPacked, locationPacked, count,
   2437                                         value);
   2438 }
   2439 
   2440 bool ValidateProgramUniform4i(const Context *context,
   2441                              angle::EntryPoint entryPoint,
   2442                              ShaderProgramID programPacked,
   2443                              UniformLocation locationPacked,
   2444                              GLint v0,
   2445                              GLint v1,
   2446                              GLint v2,
   2447                              GLint v3)
   2448 {
   2449    if (context->getClientVersion() < ES_3_1)
   2450    {
   2451        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2452        return false;
   2453    }
   2454 
   2455    return ValidateProgramUniform4iBase(context, entryPoint, programPacked, locationPacked, v0, v1,
   2456                                        v2, v3);
   2457 }
   2458 
   2459 bool ValidateProgramUniform4iv(const Context *context,
   2460                               angle::EntryPoint entryPoint,
   2461                               ShaderProgramID programPacked,
   2462                               UniformLocation locationPacked,
   2463                               GLsizei count,
   2464                               const GLint *value)
   2465 {
   2466    if (context->getClientVersion() < ES_3_1)
   2467    {
   2468        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2469        return false;
   2470    }
   2471 
   2472    return ValidateProgramUniform4ivBase(context, entryPoint, programPacked, locationPacked, count,
   2473                                         value);
   2474 }
   2475 
   2476 bool ValidateProgramUniform4ui(const Context *context,
   2477                               angle::EntryPoint entryPoint,
   2478                               ShaderProgramID programPacked,
   2479                               UniformLocation locationPacked,
   2480                               GLuint v0,
   2481                               GLuint v1,
   2482                               GLuint v2,
   2483                               GLuint v3)
   2484 {
   2485    if (context->getClientVersion() < ES_3_1)
   2486    {
   2487        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2488        return false;
   2489    }
   2490 
   2491    return ValidateProgramUniform4uiBase(context, entryPoint, programPacked, locationPacked, v0, v1,
   2492                                         v2, v3);
   2493 }
   2494 
   2495 bool ValidateProgramUniform4uiv(const Context *context,
   2496                                angle::EntryPoint entryPoint,
   2497                                ShaderProgramID programPacked,
   2498                                UniformLocation locationPacked,
   2499                                GLsizei count,
   2500                                const GLuint *value)
   2501 {
   2502    if (context->getClientVersion() < ES_3_1)
   2503    {
   2504        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2505        return false;
   2506    }
   2507 
   2508    return ValidateProgramUniform4uivBase(context, entryPoint, programPacked, locationPacked, count,
   2509                                          value);
   2510 }
   2511 
   2512 bool ValidateProgramUniformMatrix2fv(const Context *context,
   2513                                     angle::EntryPoint entryPoint,
   2514                                     ShaderProgramID programPacked,
   2515                                     UniformLocation locationPacked,
   2516                                     GLsizei count,
   2517                                     GLboolean transpose,
   2518                                     const GLfloat *value)
   2519 {
   2520    if (context->getClientVersion() < ES_3_1)
   2521    {
   2522        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2523        return false;
   2524    }
   2525 
   2526    return ValidateProgramUniformMatrix2fvBase(context, entryPoint, programPacked, locationPacked,
   2527                                               count, transpose, value);
   2528 }
   2529 
   2530 bool ValidateProgramUniformMatrix2x3fv(const Context *context,
   2531                                       angle::EntryPoint entryPoint,
   2532                                       ShaderProgramID programPacked,
   2533                                       UniformLocation locationPacked,
   2534                                       GLsizei count,
   2535                                       GLboolean transpose,
   2536                                       const GLfloat *value)
   2537 {
   2538    if (context->getClientVersion() < ES_3_1)
   2539    {
   2540        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2541        return false;
   2542    }
   2543 
   2544    return ValidateProgramUniformMatrix2x3fvBase(context, entryPoint, programPacked, locationPacked,
   2545                                                 count, transpose, value);
   2546 }
   2547 
   2548 bool ValidateProgramUniformMatrix2x4fv(const Context *context,
   2549                                       angle::EntryPoint entryPoint,
   2550                                       ShaderProgramID programPacked,
   2551                                       UniformLocation locationPacked,
   2552                                       GLsizei count,
   2553                                       GLboolean transpose,
   2554                                       const GLfloat *value)
   2555 {
   2556    if (context->getClientVersion() < ES_3_1)
   2557    {
   2558        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2559        return false;
   2560    }
   2561 
   2562    return ValidateProgramUniformMatrix2x4fvBase(context, entryPoint, programPacked, locationPacked,
   2563                                                 count, transpose, value);
   2564 }
   2565 
   2566 bool ValidateProgramUniformMatrix3fv(const Context *context,
   2567                                     angle::EntryPoint entryPoint,
   2568                                     ShaderProgramID programPacked,
   2569                                     UniformLocation locationPacked,
   2570                                     GLsizei count,
   2571                                     GLboolean transpose,
   2572                                     const GLfloat *value)
   2573 {
   2574    if (context->getClientVersion() < ES_3_1)
   2575    {
   2576        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2577        return false;
   2578    }
   2579 
   2580    return ValidateProgramUniformMatrix3fvBase(context, entryPoint, programPacked, locationPacked,
   2581                                               count, transpose, value);
   2582 }
   2583 
   2584 bool ValidateProgramUniformMatrix3x2fv(const Context *context,
   2585                                       angle::EntryPoint entryPoint,
   2586                                       ShaderProgramID programPacked,
   2587                                       UniformLocation locationPacked,
   2588                                       GLsizei count,
   2589                                       GLboolean transpose,
   2590                                       const GLfloat *value)
   2591 {
   2592    if (context->getClientVersion() < ES_3_1)
   2593    {
   2594        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2595        return false;
   2596    }
   2597 
   2598    return ValidateProgramUniformMatrix3x2fvBase(context, entryPoint, programPacked, locationPacked,
   2599                                                 count, transpose, value);
   2600 }
   2601 
   2602 bool ValidateProgramUniformMatrix3x4fv(const Context *context,
   2603                                       angle::EntryPoint entryPoint,
   2604                                       ShaderProgramID programPacked,
   2605                                       UniformLocation locationPacked,
   2606                                       GLsizei count,
   2607                                       GLboolean transpose,
   2608                                       const GLfloat *value)
   2609 {
   2610    if (context->getClientVersion() < ES_3_1)
   2611    {
   2612        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2613        return false;
   2614    }
   2615 
   2616    return ValidateProgramUniformMatrix3x4fvBase(context, entryPoint, programPacked, locationPacked,
   2617                                                 count, transpose, value);
   2618 }
   2619 
   2620 bool ValidateProgramUniformMatrix4fv(const Context *context,
   2621                                     angle::EntryPoint entryPoint,
   2622                                     ShaderProgramID programPacked,
   2623                                     UniformLocation locationPacked,
   2624                                     GLsizei count,
   2625                                     GLboolean transpose,
   2626                                     const GLfloat *value)
   2627 {
   2628    if (context->getClientVersion() < ES_3_1)
   2629    {
   2630        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2631        return false;
   2632    }
   2633 
   2634    return ValidateProgramUniformMatrix4fvBase(context, entryPoint, programPacked, locationPacked,
   2635                                               count, transpose, value);
   2636 }
   2637 
   2638 bool ValidateProgramUniformMatrix4x2fv(const Context *context,
   2639                                       angle::EntryPoint entryPoint,
   2640                                       ShaderProgramID programPacked,
   2641                                       UniformLocation locationPacked,
   2642                                       GLsizei count,
   2643                                       GLboolean transpose,
   2644                                       const GLfloat *value)
   2645 {
   2646    if (context->getClientVersion() < ES_3_1)
   2647    {
   2648        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2649        return false;
   2650    }
   2651 
   2652    return ValidateProgramUniformMatrix4x2fvBase(context, entryPoint, programPacked, locationPacked,
   2653                                                 count, transpose, value);
   2654 }
   2655 
   2656 bool ValidateProgramUniformMatrix4x3fv(const Context *context,
   2657                                       angle::EntryPoint entryPoint,
   2658                                       ShaderProgramID programPacked,
   2659                                       UniformLocation locationPacked,
   2660                                       GLsizei count,
   2661                                       GLboolean transpose,
   2662                                       const GLfloat *value)
   2663 {
   2664    if (context->getClientVersion() < ES_3_1)
   2665    {
   2666        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2667        return false;
   2668    }
   2669 
   2670    return ValidateProgramUniformMatrix4x3fvBase(context, entryPoint, programPacked, locationPacked,
   2671                                                 count, transpose, value);
   2672 }
   2673 
   2674 bool ValidateUseProgramStages(const Context *context,
   2675                              angle::EntryPoint entryPoint,
   2676                              ProgramPipelineID pipelinePacked,
   2677                              GLbitfield stages,
   2678                              ShaderProgramID programPacked)
   2679 {
   2680    if (context->getClientVersion() < ES_3_1)
   2681    {
   2682        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2683        return false;
   2684    }
   2685 
   2686    return ValidateUseProgramStagesBase(context, entryPoint, pipelinePacked, stages, programPacked);
   2687 }
   2688 
   2689 bool ValidateValidateProgramPipeline(const Context *context,
   2690                                     angle::EntryPoint entryPoint,
   2691                                     ProgramPipelineID pipelinePacked)
   2692 {
   2693    if (context->getClientVersion() < ES_3_1)
   2694    {
   2695        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2696        return false;
   2697    }
   2698 
   2699    return ValidateValidateProgramPipelineBase(context, entryPoint, pipelinePacked);
   2700 }
   2701 
   2702 bool ValidateMemoryBarrier(const Context *context,
   2703                           angle::EntryPoint entryPoint,
   2704                           GLbitfield barriers)
   2705 {
   2706    if (context->getClientVersion() < ES_3_1)
   2707    {
   2708        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2709        return false;
   2710    }
   2711 
   2712    if (barriers == GL_ALL_BARRIER_BITS)
   2713    {
   2714        return true;
   2715    }
   2716 
   2717    GLbitfield supported_barrier_bits =
   2718        GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT | GL_ELEMENT_ARRAY_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT |
   2719        GL_TEXTURE_FETCH_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_COMMAND_BARRIER_BIT |
   2720        GL_PIXEL_BUFFER_BARRIER_BIT | GL_TEXTURE_UPDATE_BARRIER_BIT | GL_BUFFER_UPDATE_BARRIER_BIT |
   2721        GL_FRAMEBUFFER_BARRIER_BIT | GL_TRANSFORM_FEEDBACK_BARRIER_BIT |
   2722        GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT;
   2723 
   2724    if (context->getExtensions().bufferStorageEXT)
   2725    {
   2726        supported_barrier_bits |= GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT;
   2727    }
   2728 
   2729    if (barriers == 0 || (barriers & ~supported_barrier_bits) != 0)
   2730    {
   2731        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
   2732        return false;
   2733    }
   2734 
   2735    return true;
   2736 }
   2737 
   2738 bool ValidateMemoryBarrierByRegion(const Context *context,
   2739                                   angle::EntryPoint entryPoint,
   2740                                   GLbitfield barriers)
   2741 {
   2742    if (context->getClientVersion() < ES_3_1)
   2743    {
   2744        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2745        return false;
   2746    }
   2747 
   2748    if (barriers == GL_ALL_BARRIER_BITS)
   2749    {
   2750        return true;
   2751    }
   2752 
   2753    GLbitfield supported_barrier_bits = GL_ATOMIC_COUNTER_BARRIER_BIT | GL_FRAMEBUFFER_BARRIER_BIT |
   2754                                        GL_SHADER_IMAGE_ACCESS_BARRIER_BIT |
   2755                                        GL_SHADER_STORAGE_BARRIER_BIT |
   2756                                        GL_TEXTURE_FETCH_BARRIER_BIT | GL_UNIFORM_BARRIER_BIT;
   2757    if (barriers == 0 || (barriers & ~supported_barrier_bits) != 0)
   2758    {
   2759        context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMemoryBarrierBit);
   2760        return false;
   2761    }
   2762 
   2763    return true;
   2764 }
   2765 
   2766 bool ValidateSampleMaski(const Context *context,
   2767                         angle::EntryPoint entryPoint,
   2768                         GLuint maskNumber,
   2769                         GLbitfield mask)
   2770 {
   2771    if (context->getClientVersion() < ES_3_1)
   2772    {
   2773        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2774        return false;
   2775    }
   2776 
   2777    return ValidateSampleMaskiBase(context, entryPoint, maskNumber, mask);
   2778 }
   2779 
   2780 bool ValidateMinSampleShadingOES(const Context *context,
   2781                                 angle::EntryPoint entryPoint,
   2782                                 GLfloat value)
   2783 {
   2784    if (!context->getExtensions().sampleShadingOES)
   2785    {
   2786        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2787        return false;
   2788    }
   2789 
   2790    return true;
   2791 }
   2792 
   2793 bool ValidateFramebufferTextureCommon(const Context *context,
   2794                                      angle::EntryPoint entryPoint,
   2795                                      GLenum target,
   2796                                      GLenum attachment,
   2797                                      TextureID texture,
   2798                                      GLint level)
   2799 {
   2800    if (texture.value != 0)
   2801    {
   2802        Texture *tex = context->getTexture(texture);
   2803 
   2804        // [EXT_geometry_shader] Section 9.2.8 "Attaching Texture Images to a Framebuffer"
   2805        // An INVALID_VALUE error is generated if <texture> is not the name of a texture object.
   2806        // We put this validation before ValidateFramebufferTextureBase because it is an
   2807        // INVALID_OPERATION error for both FramebufferTexture2D and FramebufferTextureLayer:
   2808        // [OpenGL ES 3.1] Chapter 9.2.8 (FramebufferTexture2D)
   2809        // An INVALID_OPERATION error is generated if texture is not zero, and does not name an
   2810        // existing texture object of type matching textarget.
   2811        // [OpenGL ES 3.1 Chapter 9.2.8 (FramebufferTextureLayer)
   2812        // An INVALID_OPERATION error is generated if texture is non-zero and is not the name of a
   2813        // three-dimensional or two-dimensional array texture.
   2814        if (tex == nullptr)
   2815        {
   2816            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidTextureName);
   2817            return false;
   2818        }
   2819 
   2820        if (!ValidMipLevel(context, tex->getType(), level))
   2821        {
   2822            context->validationError(entryPoint, GL_INVALID_VALUE, kInvalidMipLevel);
   2823            return false;
   2824        }
   2825 
   2826        // GLES spec 3.1, Section 9.2.8 "Attaching Texture Images to a Framebuffer"
   2827        // If textarget is TEXTURE_2D_MULTISAMPLE, then level must be zero.
   2828        if (tex->getType() == TextureType::_2DMultisample && level != 0)
   2829        {
   2830            context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero);
   2831            return false;
   2832        }
   2833 
   2834        // [OES_texture_storage_multisample_2d_array] Section 9.2.2 "Attaching Images to Framebuffer
   2835        // Objects"
   2836        // If texture is a two-dimensional multisample array texture, then level must be zero.
   2837        if (context->getExtensions().textureStorageMultisample2dArrayOES &&
   2838            tex->getType() == TextureType::_2DMultisampleArray && level != 0)
   2839        {
   2840            context->validationError(entryPoint, GL_INVALID_VALUE, kLevelNotZero);
   2841            return false;
   2842        }
   2843    }
   2844 
   2845    if (!ValidateFramebufferTextureBase(context, entryPoint, target, attachment, texture, level))
   2846    {
   2847        return false;
   2848    }
   2849 
   2850    return true;
   2851 }
   2852 
   2853 bool ValidateFramebufferTextureEXT(const Context *context,
   2854                                   angle::EntryPoint entryPoint,
   2855                                   GLenum target,
   2856                                   GLenum attachment,
   2857                                   TextureID texture,
   2858                                   GLint level)
   2859 {
   2860    if (!context->getExtensions().geometryShaderEXT)
   2861    {
   2862        context->validationError(entryPoint, GL_INVALID_OPERATION,
   2863                                 kGeometryShaderExtensionNotEnabled);
   2864        return false;
   2865    }
   2866 
   2867    return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture,
   2868                                            level);
   2869 }
   2870 
   2871 bool ValidateFramebufferTextureOES(const Context *context,
   2872                                   angle::EntryPoint entryPoint,
   2873                                   GLenum target,
   2874                                   GLenum attachment,
   2875                                   TextureID texture,
   2876                                   GLint level)
   2877 {
   2878    if (!context->getExtensions().geometryShaderOES)
   2879    {
   2880        context->validationError(entryPoint, GL_INVALID_OPERATION,
   2881                                 kGeometryShaderExtensionNotEnabled);
   2882        return false;
   2883    }
   2884 
   2885    return ValidateFramebufferTextureCommon(context, entryPoint, target, attachment, texture,
   2886                                            level);
   2887 }
   2888 
   2889 // GL_OES_texture_storage_multisample_2d_array
   2890 bool ValidateTexStorage3DMultisampleOES(const Context *context,
   2891                                        angle::EntryPoint entryPoint,
   2892                                        TextureType target,
   2893                                        GLsizei samples,
   2894                                        GLenum sizedinternalformat,
   2895                                        GLsizei width,
   2896                                        GLsizei height,
   2897                                        GLsizei depth,
   2898                                        GLboolean fixedsamplelocations)
   2899 {
   2900    if (!context->getExtensions().textureStorageMultisample2dArrayOES)
   2901    {
   2902        context->validationError(entryPoint, GL_INVALID_ENUM, kMultisampleArrayExtensionRequired);
   2903        return false;
   2904    }
   2905 
   2906    if (target != TextureType::_2DMultisampleArray)
   2907    {
   2908        context->validationError(entryPoint, GL_INVALID_ENUM,
   2909                                 kTargetMustBeTexture2DMultisampleArrayOES);
   2910        return false;
   2911    }
   2912 
   2913    if (width < 1 || height < 1 || depth < 1)
   2914    {
   2915        context->validationError(entryPoint, GL_INVALID_VALUE, kNegativeSize);
   2916        return false;
   2917    }
   2918 
   2919    if (depth > context->getCaps().maxArrayTextureLayers)
   2920    {
   2921        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureDepthOutOfRange);
   2922        return false;
   2923    }
   2924 
   2925    return ValidateTexStorageMultisample(context, entryPoint, target, samples, sizedinternalformat,
   2926                                         width, height);
   2927 }
   2928 
   2929 bool ValidateTexStorageMem3DMultisampleEXT(const Context *context,
   2930                                           angle::EntryPoint entryPoint,
   2931                                           TextureType target,
   2932                                           GLsizei samples,
   2933                                           GLenum internalFormat,
   2934                                           GLsizei width,
   2935                                           GLsizei height,
   2936                                           GLsizei depth,
   2937                                           GLboolean fixedSampleLocations,
   2938                                           MemoryObjectID memory,
   2939                                           GLuint64 offset)
   2940 {
   2941    if (!context->getExtensions().memoryObjectEXT)
   2942    {
   2943        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2944        return false;
   2945    }
   2946 
   2947    UNIMPLEMENTED();
   2948    return false;
   2949 }
   2950 
   2951 bool ValidateGetProgramResourceLocationIndexEXT(const Context *context,
   2952                                                angle::EntryPoint entryPoint,
   2953                                                ShaderProgramID program,
   2954                                                GLenum programInterface,
   2955                                                const char *name)
   2956 {
   2957    if (!context->getExtensions().blendFuncExtendedEXT)
   2958    {
   2959        context->validationError(entryPoint, GL_INVALID_OPERATION, kExtensionNotEnabled);
   2960        return false;
   2961    }
   2962    if (context->getClientVersion() < ES_3_1)
   2963    {
   2964        context->validationError(entryPoint, GL_INVALID_OPERATION, kES31Required);
   2965        return false;
   2966    }
   2967    if (programInterface != GL_PROGRAM_OUTPUT)
   2968    {
   2969        context->validationError(entryPoint, GL_INVALID_ENUM, kProgramInterfaceMustBeProgramOutput);
   2970        return false;
   2971    }
   2972    Program *programObject = GetValidProgram(context, entryPoint, program);
   2973    if (!programObject)
   2974    {
   2975        return false;
   2976    }
   2977    if (!programObject->isLinked())
   2978    {
   2979        context->validationError(entryPoint, GL_INVALID_OPERATION, kProgramNotLinked);
   2980        return false;
   2981    }
   2982    return true;
   2983 }
   2984 
   2985 // GL_OES_texture_buffer
   2986 bool ValidateTexBufferOES(const Context *context,
   2987                          angle::EntryPoint entryPoint,
   2988                          TextureType target,
   2989                          GLenum internalformat,
   2990                          BufferID bufferPacked)
   2991 {
   2992    if (!context->getExtensions().textureBufferOES)
   2993    {
   2994        context->validationError(entryPoint, GL_INVALID_OPERATION,
   2995                                 kTextureBufferExtensionNotAvailable);
   2996        return false;
   2997    }
   2998 
   2999    return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked);
   3000 }
   3001 
   3002 bool ValidateTexBufferRangeOES(const Context *context,
   3003                               angle::EntryPoint entryPoint,
   3004                               TextureType target,
   3005                               GLenum internalformat,
   3006                               BufferID bufferPacked,
   3007                               GLintptr offset,
   3008                               GLsizeiptr size)
   3009 {
   3010    if (!context->getExtensions().textureBufferOES)
   3011    {
   3012        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3013                                 kTextureBufferExtensionNotAvailable);
   3014        return false;
   3015    }
   3016 
   3017    return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, bufferPacked,
   3018                                      offset, size);
   3019 }
   3020 
   3021 // GL_EXT_texture_buffer
   3022 bool ValidateTexBufferEXT(const Context *context,
   3023                          angle::EntryPoint entryPoint,
   3024                          TextureType target,
   3025                          GLenum internalformat,
   3026                          BufferID bufferPacked)
   3027 {
   3028    if (!context->getExtensions().textureBufferEXT)
   3029    {
   3030        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3031                                 kTextureBufferExtensionNotAvailable);
   3032        return false;
   3033    }
   3034 
   3035    return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked);
   3036 }
   3037 
   3038 bool ValidateTexBufferRangeEXT(const Context *context,
   3039                               angle::EntryPoint entryPoint,
   3040                               TextureType target,
   3041                               GLenum internalformat,
   3042                               BufferID bufferPacked,
   3043                               GLintptr offset,
   3044                               GLsizeiptr size)
   3045 {
   3046    if (!context->getExtensions().textureBufferEXT)
   3047    {
   3048        context->validationError(entryPoint, GL_INVALID_OPERATION,
   3049                                 kTextureBufferExtensionNotAvailable);
   3050        return false;
   3051    }
   3052 
   3053    return ValidateTexBufferRangeBase(context, entryPoint, target, internalformat, bufferPacked,
   3054                                      offset, size);
   3055 }
   3056 
   3057 bool ValidateTexBufferBase(const Context *context,
   3058                           angle::EntryPoint entryPoint,
   3059                           TextureType target,
   3060                           GLenum internalformat,
   3061                           BufferID bufferPacked)
   3062 {
   3063    if (target != TextureType::Buffer)
   3064    {
   3065        context->validationError(entryPoint, GL_INVALID_ENUM, kTextureBufferTarget);
   3066        return false;
   3067    }
   3068 
   3069    switch (internalformat)
   3070    {
   3071        case GL_R8:
   3072        case GL_R16F:
   3073        case GL_R32F:
   3074        case GL_R8I:
   3075        case GL_R16I:
   3076        case GL_R32I:
   3077        case GL_R8UI:
   3078        case GL_R16UI:
   3079        case GL_R32UI:
   3080        case GL_RG8:
   3081        case GL_RG16F:
   3082        case GL_RG32F:
   3083        case GL_RG8I:
   3084        case GL_RG16I:
   3085        case GL_RG32I:
   3086        case GL_RG8UI:
   3087        case GL_RG16UI:
   3088        case GL_RG32UI:
   3089        case GL_RGB32F:
   3090        case GL_RGB32I:
   3091        case GL_RGB32UI:
   3092        case GL_RGBA8:
   3093        case GL_RGBA16F:
   3094        case GL_RGBA32F:
   3095        case GL_RGBA8I:
   3096        case GL_RGBA16I:
   3097        case GL_RGBA32I:
   3098        case GL_RGBA8UI:
   3099        case GL_RGBA16UI:
   3100        case GL_RGBA32UI:
   3101            break;
   3102 
   3103        default:
   3104            context->validationError(entryPoint, GL_INVALID_ENUM, kTextureBufferInternalFormat);
   3105            return false;
   3106    }
   3107 
   3108    if (bufferPacked.value != 0)
   3109    {
   3110        if (!context->isBufferGenerated(bufferPacked))
   3111        {
   3112            context->validationError(entryPoint, GL_INVALID_OPERATION, kTextureBufferInvalidBuffer);
   3113            return false;
   3114        }
   3115    }
   3116 
   3117    return true;
   3118 }
   3119 
   3120 bool ValidateTexBufferRangeBase(const Context *context,
   3121                                angle::EntryPoint entryPoint,
   3122                                TextureType target,
   3123                                GLenum internalformat,
   3124                                BufferID bufferPacked,
   3125                                GLintptr offset,
   3126                                GLsizeiptr size)
   3127 {
   3128    const Caps &caps = context->getCaps();
   3129 
   3130    if (offset < 0 || (offset % caps.textureBufferOffsetAlignment) != 0)
   3131    {
   3132        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureBufferOffsetAlignment);
   3133        return false;
   3134    }
   3135    if (size <= 0)
   3136    {
   3137        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureBufferSize);
   3138        return false;
   3139    }
   3140    const Buffer *buffer = context->getBuffer(bufferPacked);
   3141 
   3142    if (!buffer)
   3143    {
   3144        context->validationError(entryPoint, GL_INVALID_OPERATION, kBufferNotBound);
   3145        return false;
   3146    }
   3147 
   3148    if (offset + size > buffer->getSize())
   3149    {
   3150        context->validationError(entryPoint, GL_INVALID_VALUE, kTextureBufferSizeOffset);
   3151        return false;
   3152    }
   3153 
   3154    return ValidateTexBufferBase(context, entryPoint, target, internalformat, bufferPacked);
   3155 }
   3156 
   3157 }  // namespace gl