tor-browser

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

validationEGL.cpp (232294B)


      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 // validationEGL.cpp: Validation functions for generic EGL entry point parameters
      8 
      9 #include "libANGLE/validationEGL_autogen.h"
     10 
     11 #include "common/utilities.h"
     12 #include "libANGLE/Config.h"
     13 #include "libANGLE/Context.h"
     14 #include "libANGLE/Device.h"
     15 #include "libANGLE/Display.h"
     16 #include "libANGLE/EGLSync.h"
     17 #include "libANGLE/Image.h"
     18 #include "libANGLE/Stream.h"
     19 #include "libANGLE/Surface.h"
     20 #include "libANGLE/Texture.h"
     21 #include "libANGLE/Thread.h"
     22 #include "libANGLE/formatutils.h"
     23 #include "libANGLE/renderer/DisplayImpl.h"
     24 
     25 #include <EGL/eglext.h>
     26 
     27 namespace egl
     28 {
     29 namespace
     30 {
     31 size_t GetMaximumMipLevel(const gl::Context *context, gl::TextureType type)
     32 {
     33    const gl::Caps &caps = context->getCaps();
     34 
     35    int maxDimension = 0;
     36    switch (type)
     37    {
     38        case gl::TextureType::_2D:
     39        case gl::TextureType::_2DArray:
     40        case gl::TextureType::_2DMultisample:
     41            maxDimension = caps.max2DTextureSize;
     42            break;
     43        case gl::TextureType::Rectangle:
     44            maxDimension = caps.maxRectangleTextureSize;
     45            break;
     46        case gl::TextureType::CubeMap:
     47            maxDimension = caps.maxCubeMapTextureSize;
     48            break;
     49        case gl::TextureType::_3D:
     50            maxDimension = caps.max3DTextureSize;
     51            break;
     52 
     53        default:
     54            UNREACHABLE();
     55    }
     56 
     57    return gl::log2(maxDimension);
     58 }
     59 
     60 bool TextureHasNonZeroMipLevelsSpecified(const gl::Context *context, const gl::Texture *texture)
     61 {
     62    size_t maxMip = GetMaximumMipLevel(context, texture->getType());
     63    for (size_t level = 1; level < maxMip; level++)
     64    {
     65        if (texture->getType() == gl::TextureType::CubeMap)
     66        {
     67            for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
     68            {
     69                if (texture->getFormat(face, level).valid())
     70                {
     71                    return true;
     72                }
     73            }
     74        }
     75        else
     76        {
     77            if (texture->getFormat(gl::NonCubeTextureTypeToTarget(texture->getType()), level)
     78                    .valid())
     79            {
     80                return true;
     81            }
     82        }
     83    }
     84 
     85    return false;
     86 }
     87 
     88 bool CubeTextureHasUnspecifiedLevel0Face(const gl::Texture *texture)
     89 {
     90    ASSERT(texture->getType() == gl::TextureType::CubeMap);
     91    for (gl::TextureTarget face : gl::AllCubeFaceTextureTargets())
     92    {
     93        if (!texture->getFormat(face, 0).valid())
     94        {
     95            return true;
     96        }
     97    }
     98 
     99    return false;
    100 }
    101 
    102 bool ValidateStreamAttribute(const ValidationContext *val,
    103                             const EGLAttrib attribute,
    104                             const EGLAttrib value,
    105                             const DisplayExtensions &extensions)
    106 {
    107    switch (attribute)
    108    {
    109        case EGL_STREAM_STATE_KHR:
    110        case EGL_PRODUCER_FRAME_KHR:
    111        case EGL_CONSUMER_FRAME_KHR:
    112            val->setError(EGL_BAD_ACCESS, "Attempt to initialize readonly parameter");
    113            return false;
    114        case EGL_CONSUMER_LATENCY_USEC_KHR:
    115            // Technically not in spec but a latency < 0 makes no sense so we check it
    116            if (value < 0)
    117            {
    118                val->setError(EGL_BAD_PARAMETER, "Latency must be positive");
    119                return false;
    120            }
    121            break;
    122        case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
    123            if (!extensions.streamConsumerGLTexture)
    124            {
    125                val->setError(EGL_BAD_ATTRIBUTE, "Consumer GL extension not enabled");
    126                return false;
    127            }
    128            // Again not in spec but it should be positive anyways
    129            if (value < 0)
    130            {
    131                val->setError(EGL_BAD_PARAMETER, "Timeout must be positive");
    132                return false;
    133            }
    134            break;
    135        default:
    136            val->setError(EGL_BAD_ATTRIBUTE, "Invalid stream attribute");
    137            return false;
    138    }
    139    return true;
    140 }
    141 
    142 bool ValidateCreateImageMipLevelCommon(const ValidationContext *val,
    143                                       const gl::Context *context,
    144                                       const gl::Texture *texture,
    145                                       EGLAttrib level)
    146 {
    147    // Note that the spec EGL_create_image spec does not explicitly specify an error
    148    // when the level is outside the base/max level range, but it does mention that the
    149    // level "must be a part of the complete texture object <buffer>". It can be argued
    150    // that out-of-range levels are not a part of the complete texture.
    151    const GLuint effectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
    152    if (level > 0 &&
    153        (!texture->isMipmapComplete() || static_cast<GLuint>(level) < effectiveBaseLevel ||
    154         static_cast<GLuint>(level) > texture->getTextureState().getMipmapMaxLevel()))
    155    {
    156        val->setError(EGL_BAD_PARAMETER, "texture must be complete if level is non-zero.");
    157        return false;
    158    }
    159 
    160    if (level == 0 && !texture->isMipmapComplete() &&
    161        TextureHasNonZeroMipLevelsSpecified(context, texture))
    162    {
    163        val->setError(EGL_BAD_PARAMETER,
    164                      "if level is zero and the texture is incomplete, it must "
    165                      "have no mip levels specified except zero.");
    166        return false;
    167    }
    168 
    169    return true;
    170 }
    171 
    172 bool ValidateConfigAttribute(const ValidationContext *val,
    173                             const Display *display,
    174                             EGLAttrib attribute)
    175 {
    176    switch (attribute)
    177    {
    178        case EGL_BUFFER_SIZE:
    179        case EGL_ALPHA_SIZE:
    180        case EGL_BLUE_SIZE:
    181        case EGL_GREEN_SIZE:
    182        case EGL_RED_SIZE:
    183        case EGL_DEPTH_SIZE:
    184        case EGL_STENCIL_SIZE:
    185        case EGL_CONFIG_CAVEAT:
    186        case EGL_CONFIG_ID:
    187        case EGL_LEVEL:
    188        case EGL_NATIVE_RENDERABLE:
    189        case EGL_NATIVE_VISUAL_ID:
    190        case EGL_NATIVE_VISUAL_TYPE:
    191        case EGL_SAMPLES:
    192        case EGL_SAMPLE_BUFFERS:
    193        case EGL_SURFACE_TYPE:
    194        case EGL_TRANSPARENT_TYPE:
    195        case EGL_TRANSPARENT_BLUE_VALUE:
    196        case EGL_TRANSPARENT_GREEN_VALUE:
    197        case EGL_TRANSPARENT_RED_VALUE:
    198        case EGL_BIND_TO_TEXTURE_RGB:
    199        case EGL_BIND_TO_TEXTURE_RGBA:
    200        case EGL_MIN_SWAP_INTERVAL:
    201        case EGL_MAX_SWAP_INTERVAL:
    202        case EGL_LUMINANCE_SIZE:
    203        case EGL_ALPHA_MASK_SIZE:
    204        case EGL_COLOR_BUFFER_TYPE:
    205        case EGL_RENDERABLE_TYPE:
    206        case EGL_MATCH_NATIVE_PIXMAP:
    207        case EGL_CONFORMANT:
    208        case EGL_MAX_PBUFFER_WIDTH:
    209        case EGL_MAX_PBUFFER_HEIGHT:
    210        case EGL_MAX_PBUFFER_PIXELS:
    211            break;
    212 
    213        case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
    214            if (!display->getExtensions().surfaceOrientation)
    215            {
    216                val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_surface_orientation is not enabled.");
    217                return false;
    218            }
    219            break;
    220 
    221        case EGL_COLOR_COMPONENT_TYPE_EXT:
    222            if (!display->getExtensions().pixelFormatFloat)
    223            {
    224                val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_pixel_format_float is not enabled.");
    225                return false;
    226            }
    227            break;
    228 
    229        case EGL_RECORDABLE_ANDROID:
    230            if (!display->getExtensions().recordable)
    231            {
    232                val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_recordable is not enabled.");
    233                return false;
    234            }
    235            break;
    236 
    237        case EGL_FRAMEBUFFER_TARGET_ANDROID:
    238            if (!display->getExtensions().framebufferTargetANDROID)
    239            {
    240                val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANDROID_framebuffer_target is not enabled.");
    241                return false;
    242            }
    243            break;
    244 
    245        case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
    246            if (!display->getExtensions().iosurfaceClientBuffer)
    247            {
    248                val->setError(EGL_BAD_ATTRIBUTE,
    249                              "EGL_ANGLE_iosurface_client_buffer is not enabled.");
    250                return false;
    251            }
    252            break;
    253 
    254        case EGL_Y_INVERTED_NOK:
    255            if (!display->getExtensions().textureFromPixmapNOK)
    256            {
    257                val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
    258                return false;
    259            }
    260            break;
    261 
    262        case EGL_MATCH_FORMAT_KHR:
    263            if (!display->getExtensions().lockSurface3KHR)
    264            {
    265                val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not enabled.");
    266                return false;
    267            }
    268            break;
    269 
    270        default:
    271            val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
    272            return false;
    273    }
    274 
    275    return true;
    276 }
    277 
    278 bool ValidateConfigAttributeValue(const ValidationContext *val,
    279                                  const Display *display,
    280                                  EGLAttrib attribute,
    281                                  EGLAttrib value)
    282 {
    283    switch (attribute)
    284    {
    285 
    286        case EGL_BIND_TO_TEXTURE_RGB:
    287        case EGL_BIND_TO_TEXTURE_RGBA:
    288            switch (value)
    289            {
    290                case EGL_DONT_CARE:
    291                case EGL_TRUE:
    292                case EGL_FALSE:
    293                    break;
    294                default:
    295                    val->setError(EGL_BAD_ATTRIBUTE, "EGL_bind_to_texture invalid attribute: 0x%X",
    296                                  static_cast<uint32_t>(value));
    297                    return false;
    298            }
    299            break;
    300 
    301        case EGL_COLOR_BUFFER_TYPE:
    302            switch (value)
    303            {
    304                case EGL_RGB_BUFFER:
    305                case EGL_LUMINANCE_BUFFER:
    306                // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
    307                case EGL_DONT_CARE:
    308                    break;
    309                default:
    310                    val->setError(EGL_BAD_ATTRIBUTE,
    311                                  "EGL_color_buffer_type invalid attribute: 0x%X",
    312                                  static_cast<uint32_t>(value));
    313                    return false;
    314            }
    315            break;
    316 
    317        case EGL_NATIVE_RENDERABLE:
    318            switch (value)
    319            {
    320                case EGL_DONT_CARE:
    321                case EGL_TRUE:
    322                case EGL_FALSE:
    323                    break;
    324                default:
    325                    val->setError(EGL_BAD_ATTRIBUTE,
    326                                  "EGL_native_renderable invalid attribute: 0x%X",
    327                                  static_cast<uint32_t>(value));
    328                    return false;
    329            }
    330            break;
    331 
    332        case EGL_TRANSPARENT_TYPE:
    333            switch (value)
    334            {
    335                case EGL_NONE:
    336                case EGL_TRANSPARENT_RGB:
    337                // EGL_DONT_CARE doesn't match the spec, but does match dEQP usage
    338                case EGL_DONT_CARE:
    339                    break;
    340                default:
    341                    val->setError(EGL_BAD_ATTRIBUTE, "EGL_transparent_type invalid attribute: 0x%X",
    342                                  static_cast<uint32_t>(value));
    343                    return false;
    344            }
    345            break;
    346 
    347        case EGL_RECORDABLE_ANDROID:
    348            switch (value)
    349            {
    350                case EGL_TRUE:
    351                case EGL_FALSE:
    352                case EGL_DONT_CARE:
    353                    break;
    354                default:
    355                    val->setError(EGL_BAD_ATTRIBUTE,
    356                                  "EGL_RECORDABLE_ANDROID invalid attribute: 0x%X",
    357                                  static_cast<uint32_t>(value));
    358                    return false;
    359            }
    360            break;
    361 
    362        case EGL_COLOR_COMPONENT_TYPE_EXT:
    363            switch (value)
    364            {
    365                case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:
    366                case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:
    367                case EGL_DONT_CARE:
    368                    break;
    369                default:
    370                    val->setError(EGL_BAD_ATTRIBUTE,
    371                                  "EGL_COLOR_COMPONENT_TYPE_EXT invalid attribute: 0x%X",
    372                                  static_cast<uint32_t>(value));
    373                    return false;
    374            }
    375            break;
    376 
    377        case EGL_MATCH_FORMAT_KHR:
    378            switch (value)
    379            {
    380                case EGL_FORMAT_RGB_565_KHR:
    381                case EGL_FORMAT_RGBA_8888_KHR:
    382                case EGL_FORMAT_RGB_565_EXACT_KHR:
    383                case EGL_FORMAT_RGBA_8888_EXACT_KHR:
    384                    break;
    385                default:
    386                    val->setError(EGL_BAD_ATTRIBUTE,
    387                                  "EGL_KHR_lock_surface3 invalid attribute: 0x%X",
    388                                  static_cast<uint32_t>(value));
    389                    return false;
    390            }
    391            break;
    392 
    393        default:
    394            break;
    395    }
    396 
    397    return true;
    398 }
    399 
    400 bool ValidateConfigAttributes(const ValidationContext *val,
    401                              const Display *display,
    402                              const AttributeMap &attributes)
    403 {
    404    ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateConfigAttribute));
    405 
    406    for (const auto &attrib : attributes)
    407    {
    408        EGLAttrib pname = attrib.first;
    409        EGLAttrib value = attrib.second;
    410        ANGLE_VALIDATION_TRY(ValidateConfigAttributeValue(val, display, pname, value));
    411    }
    412 
    413    return true;
    414 }
    415 
    416 bool ValidateColorspaceAttribute(const ValidationContext *val,
    417                                 const DisplayExtensions &displayExtensions,
    418                                 EGLAttrib colorSpace)
    419 {
    420    switch (colorSpace)
    421    {
    422        case EGL_GL_COLORSPACE_SRGB:
    423            break;
    424        case EGL_GL_COLORSPACE_LINEAR:
    425            break;
    426        case EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT:
    427            if (!displayExtensions.glColorspaceDisplayP3Linear &&
    428                !displayExtensions.eglColorspaceAttributePassthroughANGLE)
    429            {
    430                val->setError(EGL_BAD_ATTRIBUTE,
    431                              "EXT_gl_colorspace_display_p3_linear is not available.");
    432                return false;
    433            }
    434            break;
    435        case EGL_GL_COLORSPACE_DISPLAY_P3_EXT:
    436            if (!displayExtensions.glColorspaceDisplayP3 &&
    437                !displayExtensions.eglColorspaceAttributePassthroughANGLE)
    438            {
    439                val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_display_p3 is not available.");
    440                return false;
    441            }
    442            break;
    443        case EGL_GL_COLORSPACE_DISPLAY_P3_PASSTHROUGH_EXT:
    444            if (!displayExtensions.glColorspaceDisplayP3Passthrough &&
    445                !displayExtensions.eglColorspaceAttributePassthroughANGLE)
    446            {
    447                val->setError(EGL_BAD_ATTRIBUTE,
    448                              "EGL_EXT_gl_colorspace_display_p3_passthrough is not available.");
    449                return false;
    450            }
    451            break;
    452        case EGL_GL_COLORSPACE_SCRGB_EXT:
    453            if (!displayExtensions.glColorspaceScrgb &&
    454                !displayExtensions.eglColorspaceAttributePassthroughANGLE)
    455            {
    456                val->setError(EGL_BAD_ATTRIBUTE, "EXT_gl_colorspace_scrgb is not available.");
    457                return false;
    458            }
    459            break;
    460        case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
    461            if (!displayExtensions.glColorspaceScrgbLinear &&
    462                !displayExtensions.eglColorspaceAttributePassthroughANGLE)
    463            {
    464                val->setError(EGL_BAD_ATTRIBUTE,
    465                              "EXT_gl_colorspace_scrgb_linear is not available.");
    466                return false;
    467            }
    468            break;
    469        default:
    470            val->setError(EGL_BAD_ATTRIBUTE);
    471            return false;
    472    }
    473    return true;
    474 }
    475 bool ValidatePlatformType(const ValidationContext *val,
    476                          const ClientExtensions &clientExtensions,
    477                          EGLAttrib platformType)
    478 {
    479    switch (platformType)
    480    {
    481        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
    482            break;
    483 
    484        case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
    485        case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
    486            if (!clientExtensions.platformANGLED3D)
    487            {
    488                val->setError(EGL_BAD_ATTRIBUTE, "Direct3D platform is unsupported.");
    489                return false;
    490            }
    491            break;
    492 
    493        case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
    494        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
    495            if (!clientExtensions.platformANGLEOpenGL)
    496            {
    497                val->setError(EGL_BAD_ATTRIBUTE, "OpenGL platform is unsupported.");
    498                return false;
    499            }
    500            break;
    501 
    502        case EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE:
    503            if (!clientExtensions.platformANGLENULL)
    504            {
    505                val->setError(EGL_BAD_ATTRIBUTE,
    506                              "Display type EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE "
    507                              "requires EGL_ANGLE_platform_angle_null.");
    508                return false;
    509            }
    510            break;
    511 
    512        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
    513            if (!clientExtensions.platformANGLEVulkan)
    514            {
    515                val->setError(EGL_BAD_ATTRIBUTE, "Vulkan platform is unsupported.");
    516                return false;
    517            }
    518            break;
    519 
    520        case EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE:
    521            if (!clientExtensions.platformANGLEMetal)
    522            {
    523                val->setError(EGL_BAD_ATTRIBUTE, "Metal platform is unsupported.");
    524                return false;
    525            }
    526            break;
    527 
    528        default:
    529            val->setError(EGL_BAD_ATTRIBUTE, "Unknown platform type.");
    530            return false;
    531    }
    532 
    533    return true;
    534 }
    535 
    536 bool ValidateGetPlatformDisplayCommon(const ValidationContext *val,
    537                                      EGLenum platform,
    538                                      const void *native_display,
    539                                      const AttributeMap &attribMap)
    540 {
    541    const ClientExtensions &clientExtensions = Display::GetClientExtensions();
    542 
    543    switch (platform)
    544    {
    545        case EGL_PLATFORM_ANGLE_ANGLE:
    546            if (!clientExtensions.platformANGLE)
    547            {
    548                val->setError(EGL_BAD_PARAMETER, "Platform ANGLE extension is not active");
    549                return false;
    550            }
    551            break;
    552        case EGL_PLATFORM_DEVICE_EXT:
    553            if (!clientExtensions.platformDevice)
    554            {
    555                val->setError(EGL_BAD_PARAMETER, "Platform Device extension is not active");
    556                return false;
    557            }
    558            break;
    559        case EGL_PLATFORM_GBM_KHR:
    560            if (!clientExtensions.platformGbmKHR)
    561            {
    562                val->setError(EGL_BAD_PARAMETER, "Platform GBM extension is not active");
    563                return false;
    564            }
    565            break;
    566        case EGL_PLATFORM_WAYLAND_EXT:
    567            if (!clientExtensions.platformWaylandEXT)
    568            {
    569                val->setError(EGL_BAD_PARAMETER, "Platform Wayland extension is not active");
    570                return false;
    571            }
    572            break;
    573        default:
    574            val->setError(EGL_BAD_CONFIG, "Bad platform type.");
    575            return false;
    576    }
    577 
    578    attribMap.initializeWithoutValidation();
    579 
    580    if (platform != EGL_PLATFORM_DEVICE_EXT)
    581    {
    582        EGLAttrib platformType       = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
    583        bool enableAutoTrimSpecified = false;
    584        bool enableD3D11on12         = false;
    585        bool presentPathSpecified    = false;
    586        bool luidSpecified           = false;
    587        bool deviceIdSpecified       = false;
    588 
    589        Optional<EGLAttrib> majorVersion;
    590        Optional<EGLAttrib> minorVersion;
    591        Optional<EGLAttrib> deviceType;
    592        Optional<EGLAttrib> eglHandle;
    593 
    594        for (const auto &curAttrib : attribMap)
    595        {
    596            const EGLAttrib value = curAttrib.second;
    597 
    598            switch (curAttrib.first)
    599            {
    600                case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
    601                {
    602                    ANGLE_VALIDATION_TRY(ValidatePlatformType(val, clientExtensions, value));
    603                    platformType = value;
    604                    break;
    605                }
    606 
    607                case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
    608                    if (value != EGL_DONT_CARE)
    609                    {
    610                        majorVersion = value;
    611                    }
    612                    break;
    613 
    614                case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
    615                    if (value != EGL_DONT_CARE)
    616                    {
    617                        minorVersion = value;
    618                    }
    619                    break;
    620 
    621                case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
    622                    switch (value)
    623                    {
    624                        case EGL_TRUE:
    625                        case EGL_FALSE:
    626                            break;
    627                        default:
    628                            val->setError(EGL_BAD_ATTRIBUTE, "Invalid automatic trim attribute");
    629                            return false;
    630                    }
    631                    enableAutoTrimSpecified = true;
    632                    break;
    633 
    634                case EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE:
    635                    if (!clientExtensions.platformANGLED3D ||
    636                        !clientExtensions.platformANGLED3D11ON12)
    637                    {
    638                        val->setError(EGL_BAD_ATTRIBUTE,
    639                                      "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE extension not active.");
    640                        return false;
    641                    }
    642 
    643                    switch (value)
    644                    {
    645                        case EGL_TRUE:
    646                        case EGL_FALSE:
    647                            break;
    648                        default:
    649                            val->setError(EGL_BAD_ATTRIBUTE, "Invalid D3D11on12 attribute");
    650                            return false;
    651                    }
    652                    enableD3D11on12 = true;
    653                    break;
    654 
    655                case EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE:
    656                    if (!clientExtensions.experimentalPresentPath)
    657                    {
    658                        val->setError(EGL_BAD_ATTRIBUTE,
    659                                      "EGL_ANGLE_experimental_present_path extension not active");
    660                        return false;
    661                    }
    662 
    663                    switch (value)
    664                    {
    665                        case EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE:
    666                        case EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE:
    667                            break;
    668                        default:
    669                            val->setError(EGL_BAD_ATTRIBUTE,
    670                                          "Invalid value for EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE");
    671                            return false;
    672                    }
    673                    presentPathSpecified = true;
    674                    break;
    675 
    676                case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
    677                    switch (value)
    678                    {
    679                        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
    680                        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
    681                            break;
    682 
    683                        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
    684                        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
    685                            if (!clientExtensions.platformANGLED3D)
    686                            {
    687                                val->setError(EGL_BAD_ATTRIBUTE,
    688                                              "EGL_ANGLE_platform_angle_d3d is not supported");
    689                                return false;
    690                            }
    691                            break;
    692 
    693                        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_EGL_ANGLE:
    694                            if (!clientExtensions.platformANGLEDeviceTypeEGLANGLE)
    695                            {
    696                                val->setError(EGL_BAD_ATTRIBUTE,
    697                                              "EGL_ANGLE_platform_angle_device_type_"
    698                                              "egl_angle is not supported");
    699                                return false;
    700                            }
    701                            break;
    702 
    703                        case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
    704                            if (!clientExtensions.platformANGLEDeviceTypeSwiftShader)
    705                            {
    706                                val->setError(EGL_BAD_ATTRIBUTE,
    707                                              "EGL_ANGLE_platform_angle_device_type_"
    708                                              "swiftshader is not supported");
    709                                return false;
    710                            }
    711                            break;
    712 
    713                        default:
    714                            val->setError(EGL_BAD_ATTRIBUTE,
    715                                          "Invalid value for "
    716                                          "EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE "
    717                                          "attrib");
    718                            return false;
    719                    }
    720                    deviceType = value;
    721                    break;
    722 
    723                case EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE:
    724                    if (!clientExtensions.platformANGLE)
    725                    {
    726                        val->setError(EGL_BAD_ATTRIBUTE,
    727                                      "EGL_ANGLE_platform_angle extension not active");
    728                        return false;
    729                    }
    730                    if (value != EGL_TRUE && value != EGL_FALSE && value != EGL_DONT_CARE)
    731                    {
    732                        val->setError(EGL_BAD_ATTRIBUTE,
    733                                      "EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE "
    734                                      "must be EGL_TRUE, EGL_FALSE, or "
    735                                      "EGL_DONT_CARE.");
    736                        return false;
    737                    }
    738                    break;
    739 
    740                case EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE:
    741                    if (value != EGL_DONT_CARE)
    742                    {
    743                        eglHandle = value;
    744                    }
    745                    break;
    746 
    747                case EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE:
    748                case EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE:
    749                    luidSpecified = true;
    750                    break;
    751                case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_EAGL_ANGLE:
    752                    // The property does not have an effect if it's not active, so do not check
    753                    // for non-support.
    754                    switch (value)
    755                    {
    756                        case EGL_FALSE:
    757                        case EGL_TRUE:
    758                            break;
    759                        default:
    760                            val->setError(EGL_BAD_ATTRIBUTE,
    761                                          "Invalid value for "
    762                                          "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
    763                                          "EAGL_ANGLE attrib");
    764                            return false;
    765                    }
    766                    break;
    767                case EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_CGL_ANGLE:
    768                    // The property does not have an effect if it's not active, so do not check
    769                    // for non-support.
    770                    switch (value)
    771                    {
    772                        case EGL_FALSE:
    773                        case EGL_TRUE:
    774                            break;
    775                        default:
    776                            val->setError(EGL_BAD_ATTRIBUTE,
    777                                          "Invalid value for "
    778                                          "EGL_PLATFORM_ANGLE_DEVICE_CONTEXT_VOLATILE_"
    779                                          "CGL_ANGLE attrib");
    780                            return false;
    781                    }
    782                    break;
    783                case EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE:
    784                case EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE:
    785                    if (!clientExtensions.platformANGLEDeviceId)
    786                    {
    787                        val->setError(EGL_BAD_ATTRIBUTE,
    788                                      "EGL_ANGLE_platform_angle_device_id is not supported");
    789                        return false;
    790                    }
    791                    deviceIdSpecified = true;
    792                    break;
    793                default:
    794                    break;
    795            }
    796        }
    797 
    798        if (!majorVersion.valid() && minorVersion.valid())
    799        {
    800            val->setError(EGL_BAD_ATTRIBUTE,
    801                          "Must specify major version if you specify a minor version.");
    802            return false;
    803        }
    804 
    805        if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE &&
    806            platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    807        {
    808            val->setError(EGL_BAD_ATTRIBUTE,
    809                          "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a "
    810                          "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
    811            return false;
    812        }
    813 
    814        if (enableAutoTrimSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    815        {
    816            val->setError(EGL_BAD_ATTRIBUTE,
    817                          "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE "
    818                          "requires a device type of "
    819                          "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
    820            return false;
    821        }
    822 
    823        if (enableD3D11on12)
    824        {
    825            if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    826            {
    827                val->setError(EGL_BAD_ATTRIBUTE,
    828                              "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE "
    829                              "requires a platform type of "
    830                              "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
    831                return false;
    832            }
    833 
    834            if (deviceType.valid() && deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE &&
    835                deviceType != EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE)
    836            {
    837                val->setError(EGL_BAD_ATTRIBUTE,
    838                              "EGL_PLATFORM_ANGLE_D3D11ON12_ANGLE requires a device "
    839                              "type of EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE "
    840                              "or EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE");
    841                return false;
    842            }
    843        }
    844 
    845        if (presentPathSpecified && platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    846        {
    847            val->setError(EGL_BAD_ATTRIBUTE,
    848                          "EGL_EXPERIMENTAL_PRESENT_PATH_ANGLE requires a "
    849                          "device type of EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
    850            return false;
    851        }
    852 
    853        if (luidSpecified)
    854        {
    855            if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    856            {
    857                val->setError(EGL_BAD_ATTRIBUTE,
    858                              "EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE and "
    859                              "EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE "
    860                              "require a platform type of "
    861                              "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE.");
    862                return false;
    863            }
    864 
    865            if (attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE, 0) == 0 &&
    866                attribMap.get(EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE, 0) == 0)
    867            {
    868                val->setError(EGL_BAD_ATTRIBUTE,
    869                              "If either EGL_PLATFORM_ANGLE_D3D_LUID_HIGH_ANGLE "
    870                              "and/or EGL_PLATFORM_ANGLE_D3D_LUID_LOW_ANGLE are "
    871                              "specified, at least one must non-zero.");
    872                return false;
    873            }
    874        }
    875 
    876        if (deviceIdSpecified)
    877        {
    878            if (attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE, 0) == 0 &&
    879                attribMap.get(EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE, 0) == 0)
    880            {
    881                val->setError(EGL_BAD_ATTRIBUTE,
    882                              "If either EGL_PLATFORM_ANGLE_DEVICE_ID_HIGH_ANGLE "
    883                              "and/or EGL_PLATFORM_ANGLE_DEVICE_ID_LOW_ANGLE are "
    884                              "specified, at least one must non-zero.");
    885                return false;
    886            }
    887        }
    888 
    889        if (deviceType.valid())
    890        {
    891            switch (deviceType.value())
    892            {
    893                case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE:
    894                case EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE:
    895                    if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE &&
    896                        platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
    897                    {
    898                        val->setError(EGL_BAD_ATTRIBUTE,
    899                                      "This device type requires a "
    900                                      "platform type of EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE or "
    901                                      "EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE.");
    902                        return false;
    903                    }
    904                    break;
    905 
    906                case EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE:
    907                    if (platformType != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
    908                    {
    909                        val->setError(EGL_BAD_ATTRIBUTE,
    910                                      "This device type requires a "
    911                                      "platform type of EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE.");
    912                        return false;
    913                    }
    914                    break;
    915 
    916                default:
    917                    break;
    918            }
    919        }
    920 
    921        if (platformType == EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE)
    922        {
    923            if ((majorVersion.valid() && majorVersion.value() != 1) ||
    924                (minorVersion.valid() && minorVersion.value() != 0))
    925            {
    926                val->setError(EGL_BAD_ATTRIBUTE,
    927                              "EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE currently "
    928                              "only supports Vulkan 1.0.");
    929                return false;
    930            }
    931        }
    932 
    933        if (eglHandle.valid() && platformType != EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE &&
    934            platformType != EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
    935        {
    936            val->setError(EGL_BAD_ATTRIBUTE,
    937                          "EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE requires a "
    938                          "device type of EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE.");
    939            return false;
    940        }
    941    }
    942    else
    943    {
    944        const Device *eglDevice = static_cast<const Device *>(native_display);
    945        if (eglDevice == nullptr || !Device::IsValidDevice(eglDevice))
    946        {
    947            val->setError(EGL_BAD_ATTRIBUTE,
    948                          "native_display should be a valid EGL device if "
    949                          "platform equals EGL_PLATFORM_DEVICE_EXT");
    950            return false;
    951        }
    952    }
    953 
    954    if (attribMap.contains(EGL_POWER_PREFERENCE_ANGLE))
    955    {
    956        if (!clientExtensions.displayPowerPreferenceANGLE)
    957        {
    958            val->setError(EGL_BAD_ATTRIBUTE,
    959                          "Attribute EGL_POWER_PREFERENCE_ANGLE "
    960                          "requires EGL_ANGLE_display_power_preference.");
    961            return false;
    962        }
    963        EGLAttrib value = attribMap.get(EGL_POWER_PREFERENCE_ANGLE, 0);
    964        if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
    965        {
    966            val->setError(EGL_BAD_ATTRIBUTE,
    967                          "EGL_POWER_PREFERENCE_ANGLE must be "
    968                          "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
    969            return false;
    970        }
    971    }
    972 
    973    if (attribMap.contains(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE))
    974    {
    975        if (!clientExtensions.featureControlANGLE)
    976        {
    977            val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
    978            return false;
    979        }
    980        else if (attribMap.get(EGL_FEATURE_OVERRIDES_ENABLED_ANGLE, 0) == 0)
    981        {
    982            val->setError(EGL_BAD_ATTRIBUTE,
    983                          "EGL_FEATURE_OVERRIDES_ENABLED_ANGLE must be a valid pointer");
    984            return false;
    985        }
    986    }
    987    if (attribMap.contains(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE))
    988    {
    989        if (!clientExtensions.featureControlANGLE)
    990        {
    991            val->setError(EGL_BAD_ATTRIBUTE, "EGL_ANGLE_feature_control is not supported");
    992            return false;
    993        }
    994        else if (attribMap.get(EGL_FEATURE_OVERRIDES_DISABLED_ANGLE, 0) == 0)
    995        {
    996            val->setError(EGL_BAD_ATTRIBUTE,
    997                          "EGL_FEATURE_OVERRIDES_DISABLED_ANGLE must be a valid pointer");
    998            return false;
    999        }
   1000    }
   1001 
   1002    return true;
   1003 }
   1004 
   1005 bool ValidateStream(const ValidationContext *val, const Display *display, const Stream *stream)
   1006 {
   1007    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   1008 
   1009    const DisplayExtensions &displayExtensions = display->getExtensions();
   1010    if (!displayExtensions.stream)
   1011    {
   1012        val->setError(EGL_BAD_ACCESS, "Stream extension not active");
   1013        return false;
   1014    }
   1015 
   1016    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
   1017    {
   1018        val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
   1019        return false;
   1020    }
   1021 
   1022    return true;
   1023 }
   1024 
   1025 bool ValidateLabeledObject(const ValidationContext *val,
   1026                           const Display *display,
   1027                           ObjectType objectType,
   1028                           EGLObjectKHR object,
   1029                           LabeledObject **outLabeledObject)
   1030 {
   1031    switch (objectType)
   1032    {
   1033        case ObjectType::Context:
   1034        {
   1035            gl::Context *context = static_cast<gl::Context *>(object);
   1036            ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   1037            *outLabeledObject = context;
   1038            break;
   1039        }
   1040 
   1041        case ObjectType::Display:
   1042        {
   1043            ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   1044            if (display != object)
   1045            {
   1046                if (val)
   1047                {
   1048                    val->setError(EGL_BAD_PARAMETER,
   1049                                  "when object type is EGL_OBJECT_DISPLAY_KHR, the "
   1050                                  "object must be the same as the display.");
   1051                }
   1052                return false;
   1053            }
   1054 
   1055            *outLabeledObject = static_cast<Display *>(object);
   1056            break;
   1057        }
   1058 
   1059        case ObjectType::Image:
   1060        {
   1061            Image *image = static_cast<Image *>(object);
   1062            ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
   1063            *outLabeledObject = image;
   1064            break;
   1065        }
   1066 
   1067        case ObjectType::Stream:
   1068        {
   1069            Stream *stream = static_cast<Stream *>(object);
   1070            ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   1071            *outLabeledObject = stream;
   1072            break;
   1073        }
   1074 
   1075        case ObjectType::Surface:
   1076        {
   1077            Surface *surface = static_cast<Surface *>(object);
   1078            ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   1079            *outLabeledObject = surface;
   1080            break;
   1081        }
   1082 
   1083        case ObjectType::Sync:
   1084        {
   1085            Sync *sync = static_cast<Sync *>(object);
   1086            ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   1087            *outLabeledObject = sync;
   1088            break;
   1089        }
   1090 
   1091        case ObjectType::Thread:
   1092        {
   1093            ASSERT(val);
   1094            *outLabeledObject = val->eglThread;
   1095            break;
   1096        }
   1097 
   1098        default:
   1099            if (val)
   1100            {
   1101                val->setError(EGL_BAD_PARAMETER, "unknown object type.");
   1102            }
   1103            return false;
   1104    }
   1105 
   1106    return true;
   1107 }
   1108 
   1109 // This is a common sub-check of Display status that's shared by multiple functions
   1110 bool ValidateDisplayPointer(const ValidationContext *val, const Display *display)
   1111 {
   1112    if (display == EGL_NO_DISPLAY)
   1113    {
   1114        if (val)
   1115        {
   1116            val->setError(EGL_BAD_DISPLAY, "display is EGL_NO_DISPLAY.");
   1117        }
   1118        return false;
   1119    }
   1120 
   1121    if (!Display::isValidDisplay(display))
   1122    {
   1123        if (val)
   1124        {
   1125            val->setError(EGL_BAD_DISPLAY, "display is not a valid display: 0x%p", display);
   1126        }
   1127        return false;
   1128    }
   1129 
   1130    return true;
   1131 }
   1132 
   1133 bool ValidCompositorTimingName(CompositorTiming name)
   1134 {
   1135    switch (name)
   1136    {
   1137        case CompositorTiming::CompositeDeadline:
   1138        case CompositorTiming::CompositInterval:
   1139        case CompositorTiming::CompositToPresentLatency:
   1140            return true;
   1141 
   1142        default:
   1143            return false;
   1144    }
   1145 }
   1146 
   1147 bool ValidTimestampType(Timestamp timestamp)
   1148 {
   1149    switch (timestamp)
   1150    {
   1151        case Timestamp::RequestedPresentTime:
   1152        case Timestamp::RenderingCompleteTime:
   1153        case Timestamp::CompositionLatchTime:
   1154        case Timestamp::FirstCompositionStartTime:
   1155        case Timestamp::LastCompositionStartTime:
   1156        case Timestamp::FirstCompositionGPUFinishedTime:
   1157        case Timestamp::DisplayPresentTime:
   1158        case Timestamp::DequeueReadyTime:
   1159        case Timestamp::ReadsDoneTime:
   1160            return true;
   1161 
   1162        default:
   1163            return false;
   1164    }
   1165 }
   1166 
   1167 bool ValidateCompatibleSurface(const ValidationContext *val,
   1168                               const Display *display,
   1169                               const gl::Context *context,
   1170                               const Surface *surface)
   1171 {
   1172    const Config *contextConfig = context->getConfig();
   1173    const Config *surfaceConfig = surface->getConfig();
   1174 
   1175    if (context->getClientType() != EGL_OPENGL_API)
   1176    {
   1177        // Surface compatible with client API - only OPENGL_ES supported
   1178        switch (context->getClientMajorVersion())
   1179        {
   1180            case 1:
   1181                if (!(surfaceConfig->renderableType & EGL_OPENGL_ES_BIT))
   1182                {
   1183                    val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 1.x.");
   1184                    return false;
   1185                }
   1186                break;
   1187            case 2:
   1188                if (!(surfaceConfig->renderableType & EGL_OPENGL_ES2_BIT))
   1189                {
   1190                    val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 2.x.");
   1191                    return false;
   1192                }
   1193                break;
   1194            case 3:
   1195                if (!(surfaceConfig->renderableType & (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT)))
   1196                {
   1197                    val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL ES 3.x.");
   1198                    return false;
   1199                }
   1200                break;
   1201            default:
   1202                val->setError(EGL_BAD_MATCH, "Surface not compatible with Context API.");
   1203                return false;
   1204        }
   1205    }
   1206    else
   1207    {
   1208        if (!(surfaceConfig->renderableType & EGL_OPENGL_BIT))
   1209        {
   1210            val->setError(EGL_BAD_MATCH, "Surface not compatible with OpenGL Desktop.");
   1211            return false;
   1212        }
   1213    }
   1214 
   1215    // EGL KHR no config context
   1216    if (context->getConfig() == EGL_NO_CONFIG_KHR)
   1217    {
   1218        const DisplayExtensions &displayExtensions = display->getExtensions();
   1219        if (displayExtensions.noConfigContext)
   1220        {
   1221            return true;
   1222        }
   1223        val->setError(EGL_BAD_MATCH, "Context with no config is not supported.");
   1224        return false;
   1225    }
   1226 
   1227    // Config compatibility is defined in section 2.2 of the EGL 1.5 spec
   1228 
   1229    bool colorBufferCompat = surfaceConfig->colorBufferType == contextConfig->colorBufferType;
   1230    if (!colorBufferCompat)
   1231    {
   1232        val->setError(EGL_BAD_MATCH, "Color buffer types are not compatible.");
   1233        return false;
   1234    }
   1235 
   1236    bool colorCompat = surfaceConfig->redSize == contextConfig->redSize &&
   1237                       surfaceConfig->greenSize == contextConfig->greenSize &&
   1238                       surfaceConfig->blueSize == contextConfig->blueSize &&
   1239                       surfaceConfig->alphaSize == contextConfig->alphaSize &&
   1240                       surfaceConfig->luminanceSize == contextConfig->luminanceSize;
   1241    if (!colorCompat)
   1242    {
   1243        val->setError(EGL_BAD_MATCH, "Color buffer sizes are not compatible.");
   1244        return false;
   1245    }
   1246 
   1247    bool componentTypeCompat =
   1248        surfaceConfig->colorComponentType == contextConfig->colorComponentType;
   1249    if (!componentTypeCompat)
   1250    {
   1251        val->setError(EGL_BAD_MATCH, "Color buffer component types are not compatible.");
   1252        return false;
   1253    }
   1254 
   1255    bool dsCompat = surfaceConfig->depthSize == contextConfig->depthSize &&
   1256                    surfaceConfig->stencilSize == contextConfig->stencilSize;
   1257    if (!dsCompat)
   1258    {
   1259        val->setError(EGL_BAD_MATCH, "Depth-stencil buffer types are not compatible.");
   1260        return false;
   1261    }
   1262 
   1263    bool surfaceTypeCompat = (surfaceConfig->surfaceType & contextConfig->surfaceType) != 0;
   1264    if (!surfaceTypeCompat)
   1265    {
   1266        val->setError(EGL_BAD_MATCH, "Surface type is not compatible.");
   1267        return false;
   1268    }
   1269 
   1270    return true;
   1271 }
   1272 
   1273 bool ValidateCreateSyncBase(const ValidationContext *val,
   1274                            const Display *display,
   1275                            EGLenum type,
   1276                            const AttributeMap &attribs,
   1277                            bool isExt)
   1278 {
   1279    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   1280 
   1281    attribs.initializeWithoutValidation();
   1282 
   1283    gl::Context *currentContext  = val->eglThread->getContext();
   1284    egl::Display *currentDisplay = currentContext ? currentContext->getDisplay() : nullptr;
   1285 
   1286    switch (type)
   1287    {
   1288        case EGL_SYNC_FENCE_KHR:
   1289            if (!attribs.isEmpty())
   1290            {
   1291                val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   1292                return false;
   1293            }
   1294 
   1295            if (!display->getExtensions().fenceSync)
   1296            {
   1297                val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
   1298                return false;
   1299            }
   1300 
   1301            if (display != currentDisplay)
   1302            {
   1303                val->setError(EGL_BAD_MATCH,
   1304                              "CreateSync can only be called on the current display");
   1305                return false;
   1306            }
   1307 
   1308            ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
   1309 
   1310            if (!currentContext->getExtensions().EGLSyncOES)
   1311            {
   1312                val->setError(EGL_BAD_MATCH,
   1313                              "EGL_SYNC_FENCE_KHR cannot be used without "
   1314                              "GL_OES_EGL_sync support.");
   1315                return false;
   1316            }
   1317            break;
   1318 
   1319        case EGL_SYNC_NATIVE_FENCE_ANDROID:
   1320            if (!display->getExtensions().fenceSync)
   1321            {
   1322                val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
   1323                return false;
   1324            }
   1325 
   1326            if (!display->getExtensions().nativeFenceSyncANDROID)
   1327            {
   1328                val->setError(EGL_BAD_DISPLAY,
   1329                              "EGL_ANDROID_native_fence_sync extension is not available.");
   1330                return false;
   1331            }
   1332 
   1333            if (display != currentDisplay)
   1334            {
   1335                val->setError(EGL_BAD_MATCH,
   1336                              "CreateSync can only be called on the current display");
   1337                return false;
   1338            }
   1339 
   1340            ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
   1341 
   1342            if (!currentContext->getExtensions().EGLSyncOES)
   1343            {
   1344                val->setError(EGL_BAD_MATCH,
   1345                              "EGL_SYNC_FENCE_KHR cannot be used without "
   1346                              "GL_OES_EGL_sync support.");
   1347                return false;
   1348            }
   1349 
   1350            for (const auto &attributeIter : attribs)
   1351            {
   1352                EGLAttrib attribute = attributeIter.first;
   1353 
   1354                switch (attribute)
   1355                {
   1356                    case EGL_SYNC_NATIVE_FENCE_FD_ANDROID:
   1357                        break;
   1358 
   1359                    default:
   1360                        val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   1361                        return false;
   1362                }
   1363            }
   1364            break;
   1365 
   1366        case EGL_SYNC_REUSABLE_KHR:
   1367            if (!attribs.isEmpty())
   1368            {
   1369                val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   1370                return false;
   1371            }
   1372 
   1373            if (!display->getExtensions().reusableSyncKHR)
   1374            {
   1375                val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
   1376                return false;
   1377            }
   1378            break;
   1379 
   1380        case EGL_SYNC_METAL_SHARED_EVENT_ANGLE:
   1381            if (!display->getExtensions().fenceSync)
   1382            {
   1383                val->setError(EGL_BAD_MATCH, "EGL_KHR_fence_sync extension is not available");
   1384                return false;
   1385            }
   1386 
   1387            if (!display->getExtensions().mtlSyncSharedEventANGLE)
   1388            {
   1389                val->setError(EGL_BAD_DISPLAY,
   1390                              "EGL_ANGLE_metal_shared_event_sync is not available");
   1391                return false;
   1392            }
   1393 
   1394            if (display != currentDisplay)
   1395            {
   1396                val->setError(EGL_BAD_MATCH,
   1397                              "CreateSync can only be called on the current display");
   1398                return false;
   1399            }
   1400 
   1401            ANGLE_VALIDATION_TRY(ValidateContext(val, currentDisplay, currentContext));
   1402 
   1403            // This should be implied by exposing EGL_KHR_fence_sync
   1404            ASSERT(currentContext->getExtensions().EGLSyncOES);
   1405 
   1406            for (const auto &attributeIter : attribs)
   1407            {
   1408                EGLAttrib attribute = attributeIter.first;
   1409                EGLAttrib value     = attributeIter.second;
   1410 
   1411                switch (attribute)
   1412                {
   1413                    case EGL_SYNC_METAL_SHARED_EVENT_OBJECT_ANGLE:
   1414                        if (!value)
   1415                        {
   1416                            val->setError(EGL_BAD_ATTRIBUTE,
   1417                                          "EGL_SYNC_METAL_SHARED_EVENT_ANGLE can't be NULL");
   1418                            return false;
   1419                        }
   1420                        break;
   1421 
   1422                    case EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_LO_ANGLE:
   1423                    case EGL_SYNC_METAL_SHARED_EVENT_SIGNAL_VALUE_HI_ANGLE:
   1424                        break;
   1425 
   1426                    default:
   1427                        val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   1428                        return false;
   1429                }
   1430            }
   1431            break;
   1432 
   1433        default:
   1434            if (isExt)
   1435            {
   1436                val->setError(EGL_BAD_ATTRIBUTE, "Invalid type parameter");
   1437                return false;
   1438            }
   1439            else
   1440            {
   1441                val->setError(EGL_BAD_PARAMETER, "Invalid type parameter");
   1442                return false;
   1443            }
   1444    }
   1445 
   1446    return true;
   1447 }
   1448 
   1449 bool ValidateGetSyncAttribBase(const ValidationContext *val,
   1450                               const Display *display,
   1451                               const Sync *sync,
   1452                               EGLint attribute)
   1453 {
   1454    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   1455 
   1456    switch (attribute)
   1457    {
   1458        case EGL_SYNC_CONDITION_KHR:
   1459            switch (sync->getType())
   1460            {
   1461                case EGL_SYNC_FENCE_KHR:
   1462                case EGL_SYNC_NATIVE_FENCE_ANDROID:
   1463                case EGL_SYNC_METAL_SHARED_EVENT_ANGLE:
   1464                    break;
   1465 
   1466                default:
   1467                    val->setError(EGL_BAD_ATTRIBUTE,
   1468                                  "EGL_SYNC_CONDITION_KHR is not valid for this sync type.");
   1469                    return false;
   1470            }
   1471            break;
   1472 
   1473        // The following attributes are accepted by all types
   1474        case EGL_SYNC_TYPE_KHR:
   1475        case EGL_SYNC_STATUS_KHR:
   1476            break;
   1477 
   1478        default:
   1479            val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   1480            return false;
   1481    }
   1482 
   1483    return true;
   1484 }
   1485 
   1486 bool ValidateQueryDisplayAttribBase(const ValidationContext *val,
   1487                                    const Display *display,
   1488                                    const EGLint attribute)
   1489 {
   1490    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   1491 
   1492    switch (attribute)
   1493    {
   1494        case EGL_DEVICE_EXT:
   1495            if (!Display::GetClientExtensions().deviceQueryEXT)
   1496            {
   1497                val->setError(EGL_BAD_DISPLAY, "EGL_EXT_device_query extension is not available.");
   1498                return false;
   1499            }
   1500            break;
   1501 
   1502        case EGL_FEATURE_COUNT_ANGLE:
   1503            if (!Display::GetClientExtensions().featureControlANGLE)
   1504            {
   1505                val->setError(EGL_BAD_DISPLAY,
   1506                              "EGL_ANGLE_feature_control extension is not available.");
   1507                return false;
   1508            }
   1509            break;
   1510 
   1511        default:
   1512            val->setError(EGL_BAD_ATTRIBUTE, "attribute is not valid.");
   1513            return false;
   1514    }
   1515 
   1516    return true;
   1517 }
   1518 
   1519 bool ValidateCreateContextAttribute(const ValidationContext *val,
   1520                                    const Display *display,
   1521                                    EGLAttrib attribute)
   1522 {
   1523    switch (attribute)
   1524    {
   1525        case EGL_CONTEXT_CLIENT_VERSION:
   1526        case EGL_CONTEXT_MINOR_VERSION:
   1527        case EGL_CONTEXT_FLAGS_KHR:
   1528        case EGL_CONTEXT_OPENGL_DEBUG:
   1529            break;
   1530 
   1531        case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
   1532            if (val->eglThread->getAPI() != EGL_OPENGL_API)
   1533            {
   1534                // Only valid for OpenGL (non-ES) contexts
   1535                val->setError(EGL_BAD_ATTRIBUTE, "OpenGL profile mask requires an OpenGL context.");
   1536                return false;
   1537            }
   1538            break;
   1539 
   1540        case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
   1541            if (!display->getExtensions().createContextRobustness)
   1542            {
   1543                val->setError(EGL_BAD_ATTRIBUTE);
   1544                return false;
   1545            }
   1546            break;
   1547 
   1548        case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
   1549            if (!display->getExtensions().createContextRobustness)
   1550            {
   1551                val->setError(EGL_BAD_ATTRIBUTE);
   1552                return false;
   1553            }
   1554            break;
   1555 
   1556        case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY:
   1557        {
   1558            // We either need to have -
   1559            // 1. EGL 1.5 which added support for this as part of core spec
   1560            // 2. EGL_KHR_create_context extension which requires EGL 1.4
   1561            constexpr EGLint kRequiredMajorVersion = 1;
   1562            constexpr EGLint kRequiredMinorVersion = 5;
   1563            if ((kEglMajorVersion < kRequiredMajorVersion ||
   1564                 kEglMinorVersion < kRequiredMinorVersion) &&
   1565                !display->getExtensions().createContext)
   1566            {
   1567                val->setError(EGL_BAD_ATTRIBUTE);
   1568                return false;
   1569            }
   1570            break;
   1571        }
   1572 
   1573        case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
   1574            if (!display->getExtensions().createContextNoError)
   1575            {
   1576                val->setError(EGL_BAD_ATTRIBUTE, "Invalid Context attribute.");
   1577                return false;
   1578            }
   1579            break;
   1580 
   1581        case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
   1582            if (!display->getExtensions().createContextWebGLCompatibility)
   1583            {
   1584                val->setError(EGL_BAD_ATTRIBUTE,
   1585                              "Attribute "
   1586                              "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE requires "
   1587                              "EGL_ANGLE_create_context_webgl_compatibility.");
   1588                return false;
   1589            }
   1590            break;
   1591 
   1592        case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
   1593            if (!display->getExtensions().createContextBindGeneratesResource)
   1594            {
   1595                val->setError(EGL_BAD_ATTRIBUTE,
   1596                              "Attribute EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM requires "
   1597                              "EGL_CHROMIUM_create_context_bind_generates_resource.");
   1598                return false;
   1599            }
   1600            break;
   1601 
   1602        case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
   1603            if (!display->getExtensions().displayTextureShareGroup)
   1604            {
   1605                val->setError(EGL_BAD_ATTRIBUTE,
   1606                              "Attribute "
   1607                              "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE requires "
   1608                              "EGL_ANGLE_display_texture_share_group.");
   1609                return false;
   1610            }
   1611            break;
   1612 
   1613        case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
   1614            if (!display->getExtensions().displayTextureShareGroup)
   1615            {
   1616                val->setError(EGL_BAD_ATTRIBUTE,
   1617                              "Attribute "
   1618                              "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE requires "
   1619                              "EGL_ANGLE_display_semaphore_share_group.");
   1620                return false;
   1621            }
   1622            break;
   1623 
   1624        case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
   1625            if (!display->getExtensions().createContextClientArrays)
   1626            {
   1627                val->setError(EGL_BAD_ATTRIBUTE,
   1628                              "Attribute EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE requires "
   1629                              "EGL_ANGLE_create_context_client_arrays.");
   1630                return false;
   1631            }
   1632            break;
   1633 
   1634        case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
   1635            if (!display->getExtensions().programCacheControlANGLE)
   1636            {
   1637                val->setError(EGL_BAD_ATTRIBUTE,
   1638                              "Attribute EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE "
   1639                              "requires EGL_ANGLE_program_cache_control.");
   1640                return false;
   1641            }
   1642            break;
   1643 
   1644        case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   1645            if (!display->getExtensions().robustResourceInitializationANGLE)
   1646            {
   1647                val->setError(EGL_BAD_ATTRIBUTE,
   1648                              "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
   1649                              "requires EGL_ANGLE_robust_resource_initialization.");
   1650                return false;
   1651            }
   1652            break;
   1653 
   1654        case EGL_EXTENSIONS_ENABLED_ANGLE:
   1655            if (!display->getExtensions().createContextExtensionsEnabled)
   1656            {
   1657                val->setError(EGL_BAD_ATTRIBUTE,
   1658                              "Attribute EGL_EXTENSIONS_ENABLED_ANGLE "
   1659                              "requires EGL_ANGLE_create_context_extensions_enabled.");
   1660                return false;
   1661            }
   1662            break;
   1663 
   1664        case EGL_POWER_PREFERENCE_ANGLE:
   1665            if (!display->getExtensions().powerPreference)
   1666            {
   1667                val->setError(EGL_BAD_ATTRIBUTE,
   1668                              "Attribute EGL_POWER_PREFERENCE_ANGLE "
   1669                              "requires EGL_ANGLE_power_preference.");
   1670                return false;
   1671            }
   1672            break;
   1673 
   1674        case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
   1675            if (!display->getExtensions().createContextBackwardsCompatible)
   1676            {
   1677                val->setError(EGL_BAD_ATTRIBUTE,
   1678                              "Attribute EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE "
   1679                              "requires EGL_ANGLE_create_context_backwards_compatible.");
   1680                return false;
   1681            }
   1682            break;
   1683 
   1684        case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
   1685            if (!display->getExtensions().contextPriority)
   1686            {
   1687                val->setError(EGL_BAD_ATTRIBUTE,
   1688                              "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
   1689                              "extension EGL_IMG_context_priority.");
   1690                return false;
   1691            }
   1692            break;
   1693 
   1694        case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
   1695            if (!display->getExtensions().robustnessVideoMemoryPurgeNV)
   1696            {
   1697                val->setError(EGL_BAD_ATTRIBUTE,
   1698                              "Attribute EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV requires "
   1699                              "extension EGL_NV_robustness_video_memory_purge.");
   1700                return false;
   1701            }
   1702            break;
   1703 
   1704        case EGL_EXTERNAL_CONTEXT_ANGLE:
   1705            if (!display->getExtensions().externalContextAndSurface)
   1706            {
   1707                val->setError(EGL_BAD_ATTRIBUTE,
   1708                              "Attribute "
   1709                              "EGL_EXTERNAL_CONTEXT_ANGLE requires "
   1710                              "EGL_ANGLE_external_context_and_surface.");
   1711                return false;
   1712            }
   1713            break;
   1714        case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
   1715            if (!display->getExtensions().externalContextAndSurface)
   1716            {
   1717                val->setError(EGL_BAD_ATTRIBUTE,
   1718                              "Attribute "
   1719                              "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE requires "
   1720                              "EGL_ANGLE_external_context_and_surface.");
   1721                return false;
   1722            }
   1723            break;
   1724 
   1725        case EGL_PROTECTED_CONTENT_EXT:
   1726            if (!display->getExtensions().protectedContentEXT)
   1727            {
   1728                val->setError(EGL_BAD_ATTRIBUTE,
   1729                              "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
   1730                              "extension EGL_EXT_protected_content.");
   1731                return false;
   1732            }
   1733            break;
   1734 
   1735        case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
   1736            if (!display->getExtensions().contextVirtualizationANGLE)
   1737            {
   1738                val->setError(EGL_BAD_ATTRIBUTE,
   1739                              "Attribute EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE requires "
   1740                              "extension EGL_ANGLE_context_virtualization.");
   1741                return false;
   1742            }
   1743            break;
   1744 
   1745        case EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE:
   1746            if (!display->getExtensions().metalCreateContextOwnershipIdentityANGLE)
   1747            {
   1748                val->setError(EGL_BAD_ATTRIBUTE,
   1749                              "Attribute EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE requires "
   1750                              "EGL_ANGLE_metal_create_context_ownership_identity.");
   1751            }
   1752            break;
   1753 
   1754        default:
   1755            val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR "X", attribute);
   1756            return false;
   1757    }
   1758 
   1759    return true;
   1760 }
   1761 
   1762 bool ValidateCreateContextAttributeValue(const ValidationContext *val,
   1763                                         const Display *display,
   1764                                         const gl::Context *shareContext,
   1765                                         EGLAttrib attribute,
   1766                                         EGLAttrib value)
   1767 {
   1768    switch (attribute)
   1769    {
   1770        case EGL_CONTEXT_CLIENT_VERSION:
   1771        case EGL_CONTEXT_MINOR_VERSION:
   1772        case EGL_CONTEXT_OPENGL_DEBUG:
   1773        case EGL_CONTEXT_VIRTUALIZATION_GROUP_ANGLE:
   1774            break;
   1775 
   1776        case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
   1777        {
   1778            constexpr EGLint kValidProfileMaskFlags =
   1779                (EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT |
   1780                 EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT);
   1781            if ((value & ~kValidProfileMaskFlags) != 0)
   1782            {
   1783                val->setError(EGL_BAD_ATTRIBUTE, "Invalid OpenGL profile mask.");
   1784                return false;
   1785            }
   1786            break;
   1787        }
   1788 
   1789        case EGL_CONTEXT_FLAGS_KHR:
   1790        {
   1791            // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
   1792            constexpr EGLint kValidContextFlags =
   1793                (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
   1794            if ((value & ~kValidContextFlags) != 0)
   1795            {
   1796                val->setError(EGL_BAD_ATTRIBUTE);
   1797                return false;
   1798            }
   1799            break;
   1800        }
   1801 
   1802        case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
   1803            if (value != EGL_TRUE && value != EGL_FALSE)
   1804            {
   1805                val->setError(EGL_BAD_ATTRIBUTE);
   1806                return false;
   1807            }
   1808            break;
   1809 
   1810        case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
   1811        case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY:
   1812            if (value != EGL_LOSE_CONTEXT_ON_RESET_EXT && value != EGL_NO_RESET_NOTIFICATION_EXT)
   1813            {
   1814                val->setError(EGL_BAD_ATTRIBUTE);
   1815                return false;
   1816            }
   1817 
   1818            if (shareContext && shareContext->isResetNotificationEnabled() !=
   1819                                    (value == EGL_LOSE_CONTEXT_ON_RESET_EXT))
   1820            {
   1821                val->setError(EGL_BAD_MATCH);
   1822                return false;
   1823            }
   1824            break;
   1825 
   1826        case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
   1827            if (value != EGL_TRUE && value != EGL_FALSE)
   1828            {
   1829                val->setError(EGL_BAD_ATTRIBUTE, "Attribute must be EGL_TRUE or EGL_FALSE.");
   1830                return false;
   1831            }
   1832            break;
   1833 
   1834        case EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE:
   1835            if (value != EGL_TRUE && value != EGL_FALSE)
   1836            {
   1837                val->setError(EGL_BAD_ATTRIBUTE,
   1838                              "EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE must be "
   1839                              "EGL_TRUE or EGL_FALSE.");
   1840                return false;
   1841            }
   1842            break;
   1843 
   1844        case EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM:
   1845            if (value != EGL_TRUE && value != EGL_FALSE)
   1846            {
   1847                val->setError(EGL_BAD_ATTRIBUTE,
   1848                              "EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM "
   1849                              "must be EGL_TRUE or EGL_FALSE.");
   1850                return false;
   1851            }
   1852            break;
   1853 
   1854        case EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE:
   1855            if (value != EGL_TRUE && value != EGL_FALSE)
   1856            {
   1857                val->setError(EGL_BAD_ATTRIBUTE,
   1858                              "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE must be "
   1859                              "EGL_TRUE or EGL_FALSE.");
   1860                return false;
   1861            }
   1862            if (shareContext &&
   1863                shareContext->usingDisplayTextureShareGroup() != (value == EGL_TRUE))
   1864            {
   1865                val->setError(EGL_BAD_ATTRIBUTE,
   1866                              "All contexts within a share group must be "
   1867                              "created with the same value of "
   1868                              "EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE.");
   1869                return false;
   1870            }
   1871            break;
   1872 
   1873        case EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE:
   1874            if (value != EGL_TRUE && value != EGL_FALSE)
   1875            {
   1876                val->setError(EGL_BAD_ATTRIBUTE,
   1877                              "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE must be "
   1878                              "EGL_TRUE or EGL_FALSE.");
   1879                return false;
   1880            }
   1881            if (shareContext &&
   1882                shareContext->usingDisplaySemaphoreShareGroup() != (value == EGL_TRUE))
   1883            {
   1884                val->setError(EGL_BAD_ATTRIBUTE,
   1885                              "All contexts within a share group must be "
   1886                              "created with the same value of "
   1887                              "EGL_DISPLAY_SEMAPHORE_SHARE_GROUP_ANGLE.");
   1888                return false;
   1889            }
   1890            break;
   1891 
   1892        case EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE:
   1893            if (value != EGL_TRUE && value != EGL_FALSE)
   1894            {
   1895                val->setError(EGL_BAD_ATTRIBUTE,
   1896                              "EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE must "
   1897                              "be EGL_TRUE or EGL_FALSE.");
   1898                return false;
   1899            }
   1900            break;
   1901 
   1902        case EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE:
   1903            if (value != EGL_TRUE && value != EGL_FALSE)
   1904            {
   1905                val->setError(EGL_BAD_ATTRIBUTE,
   1906                              "EGL_CONTEXT_PROGRAM_BINARY_CACHE_ENABLED_ANGLE must "
   1907                              "be EGL_TRUE or EGL_FALSE.");
   1908                return false;
   1909            }
   1910            break;
   1911 
   1912        case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   1913            if (value != EGL_TRUE && value != EGL_FALSE)
   1914            {
   1915                val->setError(EGL_BAD_ATTRIBUTE,
   1916                              "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
   1917                              "either EGL_TRUE or EGL_FALSE.");
   1918                return false;
   1919            }
   1920            break;
   1921 
   1922        case EGL_EXTENSIONS_ENABLED_ANGLE:
   1923            if (value != EGL_TRUE && value != EGL_FALSE)
   1924            {
   1925                val->setError(EGL_BAD_ATTRIBUTE,
   1926                              "EGL_EXTENSIONS_ENABLED_ANGLE must be "
   1927                              "either EGL_TRUE or EGL_FALSE.");
   1928                return false;
   1929            }
   1930            break;
   1931 
   1932        case EGL_POWER_PREFERENCE_ANGLE:
   1933            if (value != EGL_LOW_POWER_ANGLE && value != EGL_HIGH_POWER_ANGLE)
   1934            {
   1935                val->setError(EGL_BAD_ATTRIBUTE,
   1936                              "EGL_POWER_PREFERENCE_ANGLE must be "
   1937                              "either EGL_LOW_POWER_ANGLE or EGL_HIGH_POWER_ANGLE.");
   1938                return false;
   1939            }
   1940            break;
   1941 
   1942        case EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE:
   1943            if (value != EGL_TRUE && value != EGL_FALSE)
   1944            {
   1945                val->setError(EGL_BAD_ATTRIBUTE,
   1946                              "EGL_CONTEXT_OPENGL_BACKWARDS_COMPATIBLE_ANGLE must be "
   1947                              "either EGL_TRUE or EGL_FALSE.");
   1948                return false;
   1949            }
   1950            break;
   1951 
   1952        case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
   1953            switch (value)
   1954            {
   1955                case EGL_CONTEXT_PRIORITY_LOW_IMG:
   1956                case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
   1957                case EGL_CONTEXT_PRIORITY_HIGH_IMG:
   1958                    break;
   1959                default:
   1960                    val->setError(EGL_BAD_ATTRIBUTE,
   1961                                  "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG "
   1962                                  "must be one of: EGL_CONTEXT_PRIORITY_LOW_IMG, "
   1963                                  "EGL_CONTEXT_PRIORITY_MEDIUM_IMG, or "
   1964                                  "EGL_CONTEXT_PRIORITY_HIGH_IMG.");
   1965                    return false;
   1966            }
   1967            break;
   1968 
   1969        case EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV:
   1970            if (value != EGL_TRUE && value != EGL_FALSE)
   1971            {
   1972                val->setError(EGL_BAD_ATTRIBUTE,
   1973                              "EGL_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV must "
   1974                              "be either EGL_TRUE or EGL_FALSE.");
   1975                return false;
   1976            }
   1977            break;
   1978 
   1979        case EGL_EXTERNAL_CONTEXT_ANGLE:
   1980            if (value != EGL_TRUE && value != EGL_FALSE)
   1981            {
   1982                val->setError(EGL_BAD_ATTRIBUTE,
   1983                              "EGL_EXTERNAL_CONTEXT_ANGLE must "
   1984                              "be either EGL_TRUE or EGL_FALSE.");
   1985                return false;
   1986            }
   1987            if (shareContext && (value == EGL_TRUE))
   1988            {
   1989                val->setError(
   1990                    EGL_BAD_ATTRIBUTE,
   1991                    "EGL_EXTERNAL_CONTEXT_ANGLE doesn't allow creating with sharedContext.");
   1992                return false;
   1993            }
   1994            break;
   1995        case EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE:
   1996            if (value != EGL_TRUE && value != EGL_FALSE)
   1997            {
   1998                val->setError(EGL_BAD_ATTRIBUTE,
   1999                              "EGL_EXTERNAL_CONTEXT_SAVE_STATE_ANGLE must "
   2000                              "be either EGL_TRUE or EGL_FALSE.");
   2001                return false;
   2002            }
   2003            break;
   2004 
   2005        case EGL_PROTECTED_CONTENT_EXT:
   2006            if (value != EGL_TRUE && value != EGL_FALSE)
   2007            {
   2008                val->setError(EGL_BAD_ATTRIBUTE,
   2009                              "EGL_PROTECTED_CONTENT_EXT must "
   2010                              "be either EGL_TRUE or EGL_FALSE.");
   2011                return false;
   2012            }
   2013            break;
   2014 
   2015        case EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE:
   2016            if (value == 0)
   2017            {
   2018                val->setError(EGL_BAD_ATTRIBUTE,
   2019                              "EGL_CONTEXT_METAL_OWNERSHIP_IDENTITY_ANGLE must"
   2020                              "be non-zero.");
   2021                return false;
   2022            }
   2023            break;
   2024 
   2025        default:
   2026            UNREACHABLE();
   2027            return false;
   2028    }
   2029 
   2030    return true;
   2031 }
   2032 
   2033 bool ValidateCreatePbufferSurfaceAttribute(const ValidationContext *val,
   2034                                           const Display *display,
   2035                                           EGLAttrib attribute)
   2036 {
   2037    const DisplayExtensions &displayExtensions = display->getExtensions();
   2038 
   2039    switch (attribute)
   2040    {
   2041        case EGL_WIDTH:
   2042        case EGL_HEIGHT:
   2043        case EGL_LARGEST_PBUFFER:
   2044        case EGL_TEXTURE_FORMAT:
   2045        case EGL_TEXTURE_TARGET:
   2046        case EGL_MIPMAP_TEXTURE:
   2047        case EGL_VG_COLORSPACE:
   2048        case EGL_GL_COLORSPACE:
   2049        case EGL_VG_ALPHA_FORMAT:
   2050            break;
   2051 
   2052        case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   2053            if (!displayExtensions.robustResourceInitializationANGLE)
   2054            {
   2055                val->setError(EGL_BAD_ATTRIBUTE,
   2056                              "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
   2057                              "requires EGL_ANGLE_robust_resource_initialization.");
   2058                return false;
   2059            }
   2060            break;
   2061 
   2062        case EGL_PROTECTED_CONTENT_EXT:
   2063            if (!displayExtensions.protectedContentEXT)
   2064            {
   2065                val->setError(EGL_BAD_ATTRIBUTE,
   2066                              "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
   2067                              "extension EGL_EXT_protected_content.");
   2068                return false;
   2069            }
   2070            break;
   2071 
   2072        default:
   2073            val->setError(EGL_BAD_ATTRIBUTE);
   2074            return false;
   2075    }
   2076 
   2077    return true;
   2078 }
   2079 
   2080 bool ValidateCreatePbufferSurfaceAttributeValue(const ValidationContext *val,
   2081                                                const Display *display,
   2082                                                EGLAttrib attribute,
   2083                                                EGLAttrib value)
   2084 {
   2085    const DisplayExtensions &displayExtensions = display->getExtensions();
   2086 
   2087    switch (attribute)
   2088    {
   2089        case EGL_WIDTH:
   2090        case EGL_HEIGHT:
   2091            if (value < 0)
   2092            {
   2093                val->setError(EGL_BAD_PARAMETER);
   2094                return false;
   2095            }
   2096            break;
   2097 
   2098        case EGL_LARGEST_PBUFFER:
   2099            break;
   2100 
   2101        case EGL_TEXTURE_FORMAT:
   2102            switch (value)
   2103            {
   2104                case EGL_NO_TEXTURE:
   2105                case EGL_TEXTURE_RGB:
   2106                case EGL_TEXTURE_RGBA:
   2107                    break;
   2108                default:
   2109                    val->setError(EGL_BAD_ATTRIBUTE);
   2110                    return false;
   2111            }
   2112            break;
   2113 
   2114        case EGL_TEXTURE_TARGET:
   2115            switch (value)
   2116            {
   2117                case EGL_NO_TEXTURE:
   2118                case EGL_TEXTURE_2D:
   2119                    break;
   2120                default:
   2121                    val->setError(EGL_BAD_ATTRIBUTE);
   2122                    return false;
   2123            }
   2124            break;
   2125 
   2126        case EGL_MIPMAP_TEXTURE:
   2127            break;
   2128 
   2129        case EGL_VG_COLORSPACE:
   2130            break;
   2131 
   2132        case EGL_GL_COLORSPACE:
   2133            ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
   2134            break;
   2135 
   2136        case EGL_VG_ALPHA_FORMAT:
   2137            break;
   2138 
   2139        case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   2140            ASSERT(displayExtensions.robustResourceInitializationANGLE);
   2141            if (value != EGL_TRUE && value != EGL_FALSE)
   2142            {
   2143                val->setError(EGL_BAD_ATTRIBUTE,
   2144                              "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
   2145                              "either EGL_TRUE or EGL_FALSE.");
   2146                return false;
   2147            }
   2148            break;
   2149 
   2150        case EGL_PROTECTED_CONTENT_EXT:
   2151            ASSERT(displayExtensions.protectedContentEXT);
   2152            if (value != EGL_TRUE && value != EGL_FALSE)
   2153            {
   2154                val->setError(EGL_BAD_ATTRIBUTE,
   2155                              "EGL_PROTECTED_CONTENT_EXT must "
   2156                              "be either EGL_TRUE or EGL_FALSE.");
   2157                return false;
   2158            }
   2159            break;
   2160 
   2161        default:
   2162            UNREACHABLE();
   2163            return false;
   2164    }
   2165 
   2166    return true;
   2167 }
   2168 }  // anonymous namespace
   2169 
   2170 void ValidationContext::setError(EGLint error) const
   2171 {
   2172    eglThread->setError(error, entryPoint, labeledObject, nullptr);
   2173 }
   2174 
   2175 void ValidationContext::setError(EGLint error, const char *message...) const
   2176 {
   2177    ASSERT(message);
   2178 
   2179    constexpr uint32_t kBufferSize = 1000;
   2180    char buffer[kBufferSize];
   2181 
   2182    va_list args;
   2183    va_start(args, message);
   2184    vsnprintf(buffer, kBufferSize, message, args);
   2185 
   2186    eglThread->setError(error, entryPoint, labeledObject, buffer);
   2187 }
   2188 
   2189 bool ValidateDisplay(const ValidationContext *val, const Display *display)
   2190 {
   2191    ANGLE_VALIDATION_TRY(ValidateDisplayPointer(val, display));
   2192 
   2193    if (!display->isInitialized())
   2194    {
   2195        if (val)
   2196        {
   2197            val->setError(EGL_NOT_INITIALIZED, "display is not initialized.");
   2198        }
   2199        return false;
   2200    }
   2201 
   2202    if (display->isDeviceLost())
   2203    {
   2204        if (val)
   2205        {
   2206            val->setError(EGL_CONTEXT_LOST, "display had a context loss");
   2207        }
   2208        return false;
   2209    }
   2210 
   2211    return true;
   2212 }
   2213 
   2214 bool ValidateSurface(const ValidationContext *val, const Display *display, const Surface *surface)
   2215 {
   2216    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   2217 
   2218    if (!display->isValidSurface(surface))
   2219    {
   2220        if (val)
   2221        {
   2222            val->setError(EGL_BAD_SURFACE);
   2223        }
   2224        return false;
   2225    }
   2226 
   2227    return true;
   2228 }
   2229 
   2230 bool ValidateConfig(const ValidationContext *val, const Display *display, const Config *config)
   2231 {
   2232    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   2233 
   2234    if (!display->isValidConfig(config))
   2235    {
   2236        if (val)
   2237        {
   2238            val->setError(EGL_BAD_CONFIG);
   2239        }
   2240        return false;
   2241    }
   2242 
   2243    return true;
   2244 }
   2245 
   2246 bool ValidateContext(const ValidationContext *val,
   2247                     const Display *display,
   2248                     const gl::Context *context)
   2249 {
   2250    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   2251 
   2252    if (!display->isValidContext(context))
   2253    {
   2254        if (val)
   2255        {
   2256            val->setError(EGL_BAD_CONTEXT);
   2257        }
   2258        return false;
   2259    }
   2260 
   2261    return true;
   2262 }
   2263 
   2264 bool ValidateImage(const ValidationContext *val, const Display *display, const Image *image)
   2265 {
   2266    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   2267 
   2268    if (!display->isValidImage(image))
   2269    {
   2270        if (val)
   2271        {
   2272            val->setError(EGL_BAD_PARAMETER, "image is not valid.");
   2273        }
   2274        return false;
   2275    }
   2276 
   2277    return true;
   2278 }
   2279 
   2280 bool ValidateDevice(const ValidationContext *val, const Device *device)
   2281 {
   2282    if (device == EGL_NO_DEVICE_EXT)
   2283    {
   2284        if (val)
   2285        {
   2286            val->setError(EGL_BAD_ACCESS, "device is EGL_NO_DEVICE.");
   2287        }
   2288        return false;
   2289    }
   2290 
   2291    if (!Device::IsValidDevice(device))
   2292    {
   2293        if (val)
   2294        {
   2295            val->setError(EGL_BAD_ACCESS, "device is not valid.");
   2296        }
   2297        return false;
   2298    }
   2299 
   2300    return true;
   2301 }
   2302 
   2303 bool ValidateSync(const ValidationContext *val, const Display *display, const Sync *sync)
   2304 {
   2305    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   2306 
   2307    if (!display->isValidSync(sync))
   2308    {
   2309        if (val)
   2310        {
   2311            val->setError(EGL_BAD_PARAMETER, "sync object is not valid.");
   2312        }
   2313        return false;
   2314    }
   2315 
   2316    return true;
   2317 }
   2318 
   2319 const Thread *GetThreadIfValid(const Thread *thread)
   2320 {
   2321    // Threads should always be valid
   2322    return thread;
   2323 }
   2324 
   2325 const Display *GetDisplayIfValid(const Display *display)
   2326 {
   2327    return ValidateDisplay(nullptr, display) ? display : nullptr;
   2328 }
   2329 
   2330 const Surface *GetSurfaceIfValid(const Display *display, const Surface *surface)
   2331 {
   2332    return ValidateSurface(nullptr, display, surface) ? surface : nullptr;
   2333 }
   2334 
   2335 const Image *GetImageIfValid(const Display *display, const Image *image)
   2336 {
   2337    return ValidateImage(nullptr, display, image) ? image : nullptr;
   2338 }
   2339 
   2340 const Stream *GetStreamIfValid(const Display *display, const Stream *stream)
   2341 {
   2342    return ValidateStream(nullptr, display, stream) ? stream : nullptr;
   2343 }
   2344 
   2345 const gl::Context *GetContextIfValid(const Display *display, const gl::Context *context)
   2346 {
   2347    return ValidateContext(nullptr, display, context) ? context : nullptr;
   2348 }
   2349 
   2350 const Device *GetDeviceIfValid(const Device *device)
   2351 {
   2352    return ValidateDevice(nullptr, device) ? device : nullptr;
   2353 }
   2354 
   2355 const Sync *GetSyncIfValid(const Display *display, const Sync *sync)
   2356 {
   2357    return ValidateSync(nullptr, display, sync) ? sync : nullptr;
   2358 }
   2359 
   2360 LabeledObject *GetLabeledObjectIfValid(Thread *thread,
   2361                                       const Display *display,
   2362                                       ObjectType objectType,
   2363                                       EGLObjectKHR object)
   2364 {
   2365    if (objectType == ObjectType::Thread)
   2366    {
   2367        return thread;
   2368    }
   2369 
   2370    LabeledObject *labeledObject = nullptr;
   2371    if (ValidateLabeledObject(nullptr, display, objectType, object, &labeledObject))
   2372    {
   2373        return labeledObject;
   2374    }
   2375 
   2376    return nullptr;
   2377 }
   2378 
   2379 bool ValidateInitialize(const ValidationContext *val,
   2380                        const Display *display,
   2381                        const EGLint *major,
   2382                        const EGLint *minor)
   2383 {
   2384    return ValidateDisplayPointer(val, display);
   2385 }
   2386 
   2387 bool ValidateTerminate(const ValidationContext *val, const Display *display)
   2388 {
   2389    return ValidateDisplayPointer(val, display);
   2390 }
   2391 
   2392 bool ValidateCreateContext(const ValidationContext *val,
   2393                           const Display *display,
   2394                           const Config *configuration,
   2395                           const gl::Context *shareContext,
   2396                           const AttributeMap &attributes)
   2397 {
   2398    if (configuration)
   2399    {
   2400        ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
   2401    }
   2402    else
   2403    {
   2404        ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   2405        const DisplayExtensions &displayExtensions = display->getExtensions();
   2406        if (!displayExtensions.noConfigContext)
   2407        {
   2408            val->setError(EGL_BAD_CONFIG);
   2409            return false;
   2410        }
   2411    }
   2412 
   2413    ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreateContextAttribute));
   2414 
   2415    for (const auto &attributePair : attributes)
   2416    {
   2417        EGLAttrib attribute = attributePair.first;
   2418        EGLAttrib value     = attributePair.second;
   2419        ANGLE_VALIDATION_TRY(
   2420            ValidateCreateContextAttributeValue(val, display, shareContext, attribute, value));
   2421    }
   2422 
   2423    // Get the requested client version (default is 1) and check it is 2 or 3.
   2424    EGLAttrib clientMajorVersion = attributes.get(EGL_CONTEXT_CLIENT_VERSION, 1);
   2425    EGLAttrib clientMinorVersion = attributes.get(EGL_CONTEXT_MINOR_VERSION, 0);
   2426    EGLenum api                  = val->eglThread->getAPI();
   2427 
   2428    switch (api)
   2429    {
   2430        case EGL_OPENGL_ES_API:
   2431            switch (clientMajorVersion)
   2432            {
   2433                case 1:
   2434                    if (clientMinorVersion != 0 && clientMinorVersion != 1)
   2435                    {
   2436                        val->setError(EGL_BAD_ATTRIBUTE);
   2437                        return false;
   2438                    }
   2439                    if (configuration == EGL_NO_CONFIG_KHR)
   2440                    {
   2441                        val->setError(EGL_BAD_MATCH);
   2442                        return false;
   2443                    }
   2444                    if ((configuration != EGL_NO_CONFIG_KHR) &&
   2445                        !(configuration->renderableType & EGL_OPENGL_ES_BIT))
   2446                    {
   2447                        val->setError(EGL_BAD_MATCH);
   2448                        return false;
   2449                    }
   2450                    break;
   2451 
   2452                case 2:
   2453                    if (clientMinorVersion != 0)
   2454                    {
   2455                        val->setError(EGL_BAD_ATTRIBUTE);
   2456                        return false;
   2457                    }
   2458                    if ((configuration != EGL_NO_CONFIG_KHR) &&
   2459                        !(configuration->renderableType & EGL_OPENGL_ES2_BIT))
   2460                    {
   2461                        val->setError(EGL_BAD_MATCH);
   2462                        return false;
   2463                    }
   2464                    break;
   2465                case 3:
   2466                    if (clientMinorVersion < 0 || clientMinorVersion > 2)
   2467                    {
   2468                        val->setError(EGL_BAD_ATTRIBUTE);
   2469                        return false;
   2470                    }
   2471                    if ((configuration != EGL_NO_CONFIG_KHR) &&
   2472                        !(configuration->renderableType & EGL_OPENGL_ES3_BIT))
   2473                    {
   2474                        val->setError(EGL_BAD_MATCH);
   2475                        return false;
   2476                    }
   2477                    if (display->getMaxSupportedESVersion() <
   2478                        gl::Version(static_cast<GLuint>(clientMajorVersion),
   2479                                    static_cast<GLuint>(clientMinorVersion)))
   2480                    {
   2481                        gl::Version max = display->getMaxSupportedESVersion();
   2482                        val->setError(EGL_BAD_ATTRIBUTE,
   2483                                      "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
   2484                                      ") is greater than "
   2485                                      "max supported (%d, %d).",
   2486                                      clientMajorVersion, clientMinorVersion, max.major, max.minor);
   2487                        return false;
   2488                    }
   2489                    if ((attributes.get(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE, EGL_FALSE) ==
   2490                         EGL_TRUE) &&
   2491                        (clientMinorVersion > 1))
   2492                    {
   2493                        val->setError(EGL_BAD_ATTRIBUTE,
   2494                                      "Requested GLES version (%" PRIxPTR ".%" PRIxPTR
   2495                                      ") is greater than "
   2496                                      "max supported 3.1 for WebGL.",
   2497                                      clientMajorVersion, clientMinorVersion);
   2498                        return false;
   2499                    }
   2500                    break;
   2501                default:
   2502                    val->setError(EGL_BAD_ATTRIBUTE);
   2503                    return false;
   2504            }
   2505            break;
   2506 
   2507        case EGL_OPENGL_API:
   2508            // The requested configuration must use EGL_OPENGL_BIT if EGL_OPENGL_BIT is the
   2509            // currently bound API.
   2510            if ((configuration != EGL_NO_CONFIG_KHR) &&
   2511                !(configuration->renderableType & EGL_OPENGL_BIT))
   2512            {
   2513                val->setError(EGL_BAD_CONFIG);
   2514                return false;
   2515            }
   2516            // TODO(http://anglebug.com/7533): validate desktop OpenGL versions and profile mask
   2517            break;
   2518 
   2519        default:
   2520            val->setError(EGL_BAD_MATCH, "Unsupported API.");
   2521            return false;
   2522    }
   2523 
   2524    if (shareContext)
   2525    {
   2526        // Shared context is invalid or is owned by another display
   2527        if (!display->isValidContext(shareContext))
   2528        {
   2529            val->setError(EGL_BAD_MATCH);
   2530            return false;
   2531        }
   2532    }
   2533 
   2534    return true;
   2535 }
   2536 
   2537 bool ValidateCreateWindowSurface(const ValidationContext *val,
   2538                                 const Display *display,
   2539                                 const Config *config,
   2540                                 EGLNativeWindowType window,
   2541                                 const AttributeMap &attributes)
   2542 {
   2543    ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
   2544 
   2545    if (!display->isValidNativeWindow(window))
   2546    {
   2547        val->setError(EGL_BAD_NATIVE_WINDOW);
   2548        return false;
   2549    }
   2550 
   2551    const DisplayExtensions &displayExtensions = display->getExtensions();
   2552 
   2553    attributes.initializeWithoutValidation();
   2554 
   2555    for (const auto &attributeIter : attributes)
   2556    {
   2557        EGLAttrib attribute = attributeIter.first;
   2558        EGLAttrib value     = attributeIter.second;
   2559 
   2560        switch (attribute)
   2561        {
   2562            case EGL_RENDER_BUFFER:
   2563                switch (value)
   2564                {
   2565                    case EGL_BACK_BUFFER:
   2566                        break;
   2567                    case EGL_SINGLE_BUFFER:
   2568                        break;
   2569                    default:
   2570                        val->setError(EGL_BAD_ATTRIBUTE);
   2571                        return false;
   2572                }
   2573                break;
   2574 
   2575            case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
   2576                if (!displayExtensions.postSubBuffer)
   2577                {
   2578                    val->setError(EGL_BAD_ATTRIBUTE);
   2579                    return false;
   2580                }
   2581                break;
   2582 
   2583            case EGL_WIDTH:
   2584            case EGL_HEIGHT:
   2585                if (!displayExtensions.windowFixedSize)
   2586                {
   2587                    val->setError(EGL_BAD_ATTRIBUTE);
   2588                    return false;
   2589                }
   2590                if (value < 0)
   2591                {
   2592                    val->setError(EGL_BAD_PARAMETER);
   2593                    return false;
   2594                }
   2595                break;
   2596 
   2597            case EGL_FIXED_SIZE_ANGLE:
   2598                if (!displayExtensions.windowFixedSize)
   2599                {
   2600                    val->setError(EGL_BAD_ATTRIBUTE);
   2601                    return false;
   2602                }
   2603                break;
   2604 
   2605            case EGL_SURFACE_ORIENTATION_ANGLE:
   2606                if (!displayExtensions.surfaceOrientation)
   2607                {
   2608                    val->setError(EGL_BAD_ATTRIBUTE,
   2609                                  "EGL_ANGLE_surface_orientation is not enabled.");
   2610                    return false;
   2611                }
   2612                break;
   2613 
   2614            case EGL_VG_COLORSPACE:
   2615                if (value != EGL_VG_COLORSPACE_sRGB)
   2616                {
   2617                    val->setError(EGL_BAD_MATCH);
   2618                    return false;
   2619                }
   2620                break;
   2621 
   2622            case EGL_GL_COLORSPACE:
   2623                ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
   2624                break;
   2625 
   2626            case EGL_VG_ALPHA_FORMAT:
   2627                val->setError(EGL_BAD_MATCH);
   2628                return false;
   2629 
   2630            case EGL_DIRECT_COMPOSITION_ANGLE:
   2631                if (!displayExtensions.directComposition)
   2632                {
   2633                    val->setError(EGL_BAD_ATTRIBUTE);
   2634                    return false;
   2635                }
   2636                break;
   2637 
   2638            case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   2639                if (!display->getExtensions().robustResourceInitializationANGLE)
   2640                {
   2641                    val->setError(EGL_BAD_ATTRIBUTE,
   2642                                  "Attribute EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE "
   2643                                  "requires EGL_ANGLE_robust_resource_initialization.");
   2644                    return false;
   2645                }
   2646                if (value != EGL_TRUE && value != EGL_FALSE)
   2647                {
   2648                    val->setError(EGL_BAD_ATTRIBUTE,
   2649                                  "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE must be "
   2650                                  "either EGL_TRUE or EGL_FALSE.");
   2651                    return false;
   2652                }
   2653                break;
   2654 
   2655            case EGL_GGP_STREAM_DESCRIPTOR_ANGLE:
   2656                if (!display->getExtensions().ggpStreamDescriptor)
   2657                {
   2658                    val->setError(EGL_BAD_ATTRIBUTE,
   2659                                  "EGL_GGP_STREAM_DESCRIPTOR_ANGLE requires "
   2660                                  "EGL_ANGLE_ggp_stream_descriptor.");
   2661                    return false;
   2662                }
   2663                break;
   2664 
   2665            case EGL_PROTECTED_CONTENT_EXT:
   2666                if (!displayExtensions.protectedContentEXT)
   2667                {
   2668                    val->setError(EGL_BAD_ATTRIBUTE,
   2669                                  "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
   2670                                  "extension EGL_EXT_protected_content.");
   2671                    return false;
   2672                }
   2673                if (value != EGL_TRUE && value != EGL_FALSE)
   2674                {
   2675                    val->setError(EGL_BAD_ATTRIBUTE,
   2676                                  "EGL_PROTECTED_CONTENT_EXT must "
   2677                                  "be either EGL_TRUE or EGL_FALSE.");
   2678                    return false;
   2679                }
   2680                break;
   2681 
   2682            case EGL_SWAP_INTERVAL_ANGLE:
   2683                if (!displayExtensions.createSurfaceSwapIntervalANGLE)
   2684                {
   2685                    val->setError(EGL_BAD_ATTRIBUTE,
   2686                                  "Attribute EGL_SWAP_INTERVAL_ANGLE requires "
   2687                                  "extension EGL_ANGLE_create_surface_swap_interval.");
   2688                    return false;
   2689                }
   2690                if (value < config->minSwapInterval || value > config->maxSwapInterval)
   2691                {
   2692                    val->setError(EGL_BAD_ATTRIBUTE,
   2693                                  "EGL_SWAP_INTERVAL_ANGLE must "
   2694                                  "be within the EGLConfig min and max swap intervals.");
   2695                    return false;
   2696                }
   2697                break;
   2698 
   2699            default:
   2700                val->setError(EGL_BAD_ATTRIBUTE);
   2701                return false;
   2702        }
   2703    }
   2704 
   2705    if (Display::hasExistingWindowSurface(window))
   2706    {
   2707        val->setError(EGL_BAD_ALLOC);
   2708        return false;
   2709    }
   2710 
   2711    return true;
   2712 }
   2713 
   2714 bool ValidateCreatePbufferSurface(const ValidationContext *val,
   2715                                  const Display *display,
   2716                                  const Config *config,
   2717                                  const AttributeMap &attributes)
   2718 {
   2719    ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
   2720    ANGLE_VALIDATION_TRY(attributes.validate(val, display, ValidateCreatePbufferSurfaceAttribute));
   2721 
   2722    for (const auto &attributeIter : attributes)
   2723    {
   2724        EGLAttrib attribute = attributeIter.first;
   2725        EGLAttrib value     = attributeIter.second;
   2726 
   2727        ANGLE_VALIDATION_TRY(
   2728            ValidateCreatePbufferSurfaceAttributeValue(val, display, attribute, value));
   2729    }
   2730 
   2731    if ((config->surfaceType & EGL_PBUFFER_BIT) == 0)
   2732    {
   2733        val->setError(EGL_BAD_MATCH);
   2734        return false;
   2735    }
   2736 
   2737    const Caps &caps = display->getCaps();
   2738 
   2739    EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
   2740    EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
   2741 
   2742    if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
   2743        (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
   2744    {
   2745        val->setError(EGL_BAD_MATCH);
   2746        return false;
   2747    }
   2748 
   2749    if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
   2750        (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
   2751    {
   2752        val->setError(EGL_BAD_ATTRIBUTE);
   2753        return false;
   2754    }
   2755 
   2756    EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
   2757    EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
   2758    if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
   2759        (!gl::isPow2(width) || !gl::isPow2(height)))
   2760    {
   2761        val->setError(EGL_BAD_MATCH);
   2762        return false;
   2763    }
   2764 
   2765    return true;
   2766 }
   2767 
   2768 bool ValidateCreatePbufferFromClientBuffer(const ValidationContext *val,
   2769                                           const Display *display,
   2770                                           EGLenum buftype,
   2771                                           EGLClientBuffer buffer,
   2772                                           const Config *config,
   2773                                           const AttributeMap &attributes)
   2774 {
   2775    ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
   2776 
   2777    const DisplayExtensions &displayExtensions = display->getExtensions();
   2778 
   2779    attributes.initializeWithoutValidation();
   2780 
   2781    switch (buftype)
   2782    {
   2783        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
   2784            if (!displayExtensions.d3dShareHandleClientBuffer)
   2785            {
   2786                val->setError(EGL_BAD_PARAMETER);
   2787                return false;
   2788            }
   2789            if (buffer == nullptr)
   2790            {
   2791                val->setError(EGL_BAD_PARAMETER);
   2792                return false;
   2793            }
   2794            break;
   2795 
   2796        case EGL_D3D_TEXTURE_ANGLE:
   2797            if (!displayExtensions.d3dTextureClientBuffer)
   2798            {
   2799                val->setError(EGL_BAD_PARAMETER);
   2800                return false;
   2801            }
   2802            if (buffer == nullptr)
   2803            {
   2804                val->setError(EGL_BAD_PARAMETER);
   2805                return false;
   2806            }
   2807            break;
   2808 
   2809        case EGL_IOSURFACE_ANGLE:
   2810            if (!displayExtensions.iosurfaceClientBuffer)
   2811            {
   2812                val->setError(EGL_BAD_PARAMETER,
   2813                              "<buftype> EGL_IOSURFACE_ANGLE requires the "
   2814                              "EGL_ANGLE_iosurface_client_buffer extension.");
   2815                return false;
   2816            }
   2817            if (buffer == nullptr)
   2818            {
   2819                val->setError(EGL_BAD_PARAMETER, "<buffer> must be non null");
   2820                return false;
   2821            }
   2822            break;
   2823        case EGL_EXTERNAL_SURFACE_ANGLE:
   2824            if (!display->getExtensions().externalContextAndSurface)
   2825            {
   2826                val->setError(EGL_BAD_ATTRIBUTE,
   2827                              "Attribute "
   2828                              "EGL_EXTERNAL_SURFACE_ANGLE requires "
   2829                              "EGL_ANGLE_external_context_and_surface.");
   2830                return false;
   2831            }
   2832            if (buffer != nullptr)
   2833            {
   2834                val->setError(EGL_BAD_PARAMETER, "<buffer> must be null");
   2835                return false;
   2836            }
   2837            break;
   2838 
   2839        default:
   2840            val->setError(EGL_BAD_PARAMETER);
   2841            return false;
   2842    }
   2843 
   2844    for (AttributeMap::const_iterator attributeIter = attributes.begin();
   2845         attributeIter != attributes.end(); attributeIter++)
   2846    {
   2847        EGLAttrib attribute = attributeIter->first;
   2848        EGLAttrib value     = attributeIter->second;
   2849 
   2850        switch (attribute)
   2851        {
   2852            case EGL_WIDTH:
   2853            case EGL_HEIGHT:
   2854                if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE &&
   2855                    buftype != EGL_D3D_TEXTURE_ANGLE && buftype != EGL_IOSURFACE_ANGLE &&
   2856                    buftype != EGL_EXTERNAL_SURFACE_ANGLE)
   2857                {
   2858                    val->setError(EGL_BAD_PARAMETER,
   2859                                  "Width and Height are not supported for this <buftype>");
   2860                    return false;
   2861                }
   2862                if (value < 0)
   2863                {
   2864                    val->setError(EGL_BAD_PARAMETER, "Width and Height must be positive");
   2865                    return false;
   2866                }
   2867                break;
   2868 
   2869            case EGL_TEXTURE_FORMAT:
   2870                switch (value)
   2871                {
   2872                    case EGL_NO_TEXTURE:
   2873                    case EGL_TEXTURE_RGB:
   2874                    case EGL_TEXTURE_RGBA:
   2875                        break;
   2876                    default:
   2877                        val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_FORMAT");
   2878                        return false;
   2879                }
   2880                break;
   2881 
   2882            case EGL_TEXTURE_TARGET:
   2883                switch (value)
   2884                {
   2885                    case EGL_NO_TEXTURE:
   2886                    case EGL_TEXTURE_2D:
   2887                        break;
   2888                    case EGL_TEXTURE_RECTANGLE_ANGLE:
   2889                        if (buftype != EGL_IOSURFACE_ANGLE)
   2890                        {
   2891                            val->setError(EGL_BAD_PARAMETER,
   2892                                          "<buftype> doesn't support rectangle texture targets");
   2893                            return false;
   2894                        }
   2895                        break;
   2896 
   2897                    default:
   2898                        val->setError(EGL_BAD_ATTRIBUTE, "Invalid value for EGL_TEXTURE_TARGET");
   2899                        return false;
   2900                }
   2901                break;
   2902 
   2903            case EGL_MIPMAP_TEXTURE:
   2904                break;
   2905 
   2906            case EGL_IOSURFACE_PLANE_ANGLE:
   2907                if (buftype != EGL_IOSURFACE_ANGLE)
   2908                {
   2909                    val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support iosurface plane");
   2910                    return false;
   2911                }
   2912                break;
   2913 
   2914            case EGL_TEXTURE_TYPE_ANGLE:
   2915                if (buftype != EGL_IOSURFACE_ANGLE)
   2916                {
   2917                    val->setError(EGL_BAD_ATTRIBUTE, "<buftype> doesn't support texture type");
   2918                    return false;
   2919                }
   2920                break;
   2921 
   2922            case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
   2923                if (buftype != EGL_IOSURFACE_ANGLE && buftype != EGL_D3D_TEXTURE_ANGLE)
   2924                {
   2925                    val->setError(EGL_BAD_ATTRIBUTE,
   2926                                  "<buftype> doesn't support texture internal format");
   2927                    return false;
   2928                }
   2929                break;
   2930 
   2931            case EGL_GL_COLORSPACE:
   2932                if (buftype != EGL_D3D_TEXTURE_ANGLE)
   2933                {
   2934                    val->setError(EGL_BAD_ATTRIBUTE,
   2935                                  "<buftype> doesn't support setting GL colorspace");
   2936                    return false;
   2937                }
   2938                break;
   2939 
   2940            case EGL_IOSURFACE_USAGE_HINT_ANGLE:
   2941                if (value & ~(EGL_IOSURFACE_READ_HINT_ANGLE | EGL_IOSURFACE_WRITE_HINT_ANGLE))
   2942                {
   2943                    val->setError(EGL_BAD_ATTRIBUTE,
   2944                                  "IOSurface usage hint must only contain READ or WRITE");
   2945                    return false;
   2946                }
   2947                break;
   2948 
   2949            case EGL_TEXTURE_OFFSET_X_ANGLE:
   2950            case EGL_TEXTURE_OFFSET_Y_ANGLE:
   2951                if (buftype != EGL_D3D_TEXTURE_ANGLE)
   2952                {
   2953                    val->setError(EGL_BAD_ATTRIBUTE,
   2954                                  "<buftype> doesn't support setting texture offset");
   2955                    return false;
   2956                }
   2957                break;
   2958 
   2959            case EGL_PROTECTED_CONTENT_EXT:
   2960                if (!displayExtensions.protectedContentEXT)
   2961                {
   2962                    val->setError(EGL_BAD_ATTRIBUTE,
   2963                                  "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
   2964                                  "extension EGL_EXT_protected_content.");
   2965                    return false;
   2966                }
   2967                if (value != EGL_TRUE && value != EGL_FALSE)
   2968                {
   2969                    val->setError(EGL_BAD_ATTRIBUTE,
   2970                                  "EGL_PROTECTED_CONTENT_EXT must "
   2971                                  "be either EGL_TRUE or EGL_FALSE.");
   2972                    return false;
   2973                }
   2974                break;
   2975 
   2976            default:
   2977                val->setError(EGL_BAD_ATTRIBUTE);
   2978                return false;
   2979        }
   2980    }
   2981 
   2982    EGLAttrib colorspace = attributes.get(EGL_GL_COLORSPACE, EGL_GL_COLORSPACE_LINEAR);
   2983    if (colorspace != EGL_GL_COLORSPACE_LINEAR && colorspace != EGL_GL_COLORSPACE_SRGB)
   2984    {
   2985        val->setError(EGL_BAD_ATTRIBUTE, "invalid GL colorspace");
   2986        return false;
   2987    }
   2988 
   2989    if (!(config->surfaceType & EGL_PBUFFER_BIT))
   2990    {
   2991        val->setError(EGL_BAD_MATCH);
   2992        return false;
   2993    }
   2994 
   2995    EGLAttrib textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
   2996    EGLAttrib textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
   2997    if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
   2998        (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
   2999    {
   3000        val->setError(EGL_BAD_MATCH);
   3001        return false;
   3002    }
   3003    if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
   3004        (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
   3005    {
   3006        // TODO(cwallez@chromium.org): For IOSurface pbuffers we require that EGL_TEXTURE_RGBA is
   3007        // set so that eglBindTexImage works. Normally this is only allowed if the config exposes
   3008        // the bindToTextureRGB/RGBA flag. This issue is that enabling this flags means that
   3009        // eglBindTexImage should also work for regular pbuffers which isn't implemented on macOS.
   3010        // Instead of adding the flag we special case the check here to be ignored for IOSurfaces.
   3011        // The TODO is to find a proper solution for this, maybe by implementing eglBindTexImage on
   3012        // OSX?
   3013        if (buftype != EGL_IOSURFACE_ANGLE)
   3014        {
   3015            val->setError(EGL_BAD_ATTRIBUTE);
   3016            return false;
   3017        }
   3018    }
   3019 
   3020    if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
   3021    {
   3022        EGLint width  = static_cast<EGLint>(attributes.get(EGL_WIDTH, 0));
   3023        EGLint height = static_cast<EGLint>(attributes.get(EGL_HEIGHT, 0));
   3024 
   3025        if (width == 0 || height == 0)
   3026        {
   3027            val->setError(EGL_BAD_ATTRIBUTE);
   3028            return false;
   3029        }
   3030 
   3031        const Caps &caps = display->getCaps();
   3032        if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT &&
   3033            (!gl::isPow2(width) || !gl::isPow2(height)))
   3034        {
   3035            val->setError(EGL_BAD_MATCH);
   3036            return false;
   3037        }
   3038    }
   3039 
   3040    if (buftype == EGL_IOSURFACE_ANGLE)
   3041    {
   3042        if (static_cast<EGLenum>(textureTarget) != config->bindToTextureTarget)
   3043        {
   3044            val->setError(EGL_BAD_ATTRIBUTE,
   3045                          "EGL_IOSURFACE requires the texture target to match the config");
   3046            return false;
   3047        }
   3048        if (textureFormat != EGL_TEXTURE_RGBA)
   3049        {
   3050            val->setError(EGL_BAD_ATTRIBUTE, "EGL_IOSURFACE requires the EGL_TEXTURE_RGBA format");
   3051            return false;
   3052        }
   3053 
   3054        if (!attributes.contains(EGL_WIDTH) || !attributes.contains(EGL_HEIGHT) ||
   3055            !attributes.contains(EGL_TEXTURE_FORMAT) ||
   3056            !attributes.contains(EGL_TEXTURE_TYPE_ANGLE) ||
   3057            !attributes.contains(EGL_TEXTURE_INTERNAL_FORMAT_ANGLE) ||
   3058            !attributes.contains(EGL_IOSURFACE_PLANE_ANGLE))
   3059        {
   3060            val->setError(EGL_BAD_PARAMETER, "Missing required attribute for EGL_IOSURFACE");
   3061            return false;
   3062        }
   3063    }
   3064 
   3065    ANGLE_EGL_TRY_RETURN(val->eglThread,
   3066                         display->validateClientBuffer(config, buftype, buffer, attributes),
   3067                         val->entryPoint, val->labeledObject, false);
   3068 
   3069    return true;
   3070 }
   3071 
   3072 bool ValidateCreatePixmapSurface(const ValidationContext *val,
   3073                                 const Display *display,
   3074                                 const Config *config,
   3075                                 EGLNativePixmapType pixmap,
   3076                                 const AttributeMap &attributes)
   3077 {
   3078    ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
   3079 
   3080    const DisplayExtensions &displayExtensions = display->getExtensions();
   3081 
   3082    attributes.initializeWithoutValidation();
   3083 
   3084    for (const auto &attributePair : attributes)
   3085    {
   3086        EGLAttrib attribute = attributePair.first;
   3087        EGLAttrib value     = attributePair.second;
   3088 
   3089        switch (attribute)
   3090        {
   3091            case EGL_GL_COLORSPACE:
   3092                ANGLE_VALIDATION_TRY(ValidateColorspaceAttribute(val, displayExtensions, value));
   3093                break;
   3094 
   3095            case EGL_VG_COLORSPACE:
   3096                break;
   3097            case EGL_VG_ALPHA_FORMAT:
   3098                break;
   3099 
   3100            case EGL_TEXTURE_FORMAT:
   3101                if (!displayExtensions.textureFromPixmapNOK)
   3102                {
   3103                    val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
   3104                    return false;
   3105                }
   3106                switch (value)
   3107                {
   3108                    case EGL_NO_TEXTURE:
   3109                    case EGL_TEXTURE_RGB:
   3110                    case EGL_TEXTURE_RGBA:
   3111                        break;
   3112                    default:
   3113                        val->setError(EGL_BAD_ATTRIBUTE);
   3114                        return false;
   3115                }
   3116                break;
   3117 
   3118            case EGL_TEXTURE_TARGET:
   3119                if (!displayExtensions.textureFromPixmapNOK)
   3120                {
   3121                    val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
   3122                    return false;
   3123                }
   3124                switch (value)
   3125                {
   3126                    case EGL_NO_TEXTURE:
   3127                    case EGL_TEXTURE_2D:
   3128                        break;
   3129                    default:
   3130                        val->setError(EGL_BAD_ATTRIBUTE);
   3131                        return false;
   3132                }
   3133                break;
   3134 
   3135            case EGL_MIPMAP_TEXTURE:
   3136                if (!displayExtensions.textureFromPixmapNOK)
   3137                {
   3138                    val->setError(EGL_BAD_ATTRIBUTE, "EGL_NOK_texture_from_pixmap is not enabled.");
   3139                    return false;
   3140                }
   3141                break;
   3142 
   3143            case EGL_PROTECTED_CONTENT_EXT:
   3144                if (!displayExtensions.protectedContentEXT)
   3145                {
   3146                    val->setError(EGL_BAD_ATTRIBUTE,
   3147                                  "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
   3148                                  "extension EGL_EXT_protected_content.");
   3149                    return false;
   3150                }
   3151                if (value != EGL_TRUE && value != EGL_FALSE)
   3152                {
   3153                    val->setError(EGL_BAD_ATTRIBUTE,
   3154                                  "EGL_PROTECTED_CONTENT_EXT must "
   3155                                  "be either EGL_TRUE or EGL_FALSE.");
   3156                    return false;
   3157                }
   3158                break;
   3159 
   3160            default:
   3161                val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04" PRIxPTR, attribute);
   3162                return false;
   3163        }
   3164    }
   3165 
   3166    if (!(config->surfaceType & EGL_PIXMAP_BIT))
   3167    {
   3168        val->setError(EGL_BAD_MATCH, "Congfig does not suport pixmaps.");
   3169        return false;
   3170    }
   3171 
   3172    ANGLE_EGL_TRY_RETURN(val->eglThread, display->valdiatePixmap(config, pixmap, attributes),
   3173                         val->entryPoint, val->labeledObject, false);
   3174 
   3175    return true;
   3176 }
   3177 
   3178 bool ValidateMakeCurrent(const ValidationContext *val,
   3179                         const Display *display,
   3180                         const Surface *draw,
   3181                         const Surface *read,
   3182                         const gl::Context *context)
   3183 {
   3184    if (context == EGL_NO_CONTEXT && (draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
   3185    {
   3186        val->setError(EGL_BAD_MATCH, "If ctx is EGL_NO_CONTEXT, surfaces must be EGL_NO_SURFACE");
   3187        return false;
   3188    }
   3189 
   3190    // If ctx is EGL_NO_CONTEXT and either draw or read are not EGL_NO_SURFACE, an EGL_BAD_MATCH
   3191    // error is generated. EGL_KHR_surfaceless_context allows both surfaces to be EGL_NO_SURFACE.
   3192    if (context != EGL_NO_CONTEXT && (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE))
   3193    {
   3194        if (display->getExtensions().surfacelessContext)
   3195        {
   3196            if ((draw == EGL_NO_SURFACE) != (read == EGL_NO_SURFACE))
   3197            {
   3198                val->setError(EGL_BAD_MATCH,
   3199                              "If ctx is not EGL_NOT_CONTEXT, draw or read must "
   3200                              "both be EGL_NO_SURFACE, or both not");
   3201                return false;
   3202            }
   3203        }
   3204        else
   3205        {
   3206            val->setError(EGL_BAD_MATCH,
   3207                          "If ctx is not EGL_NO_CONTEXT, surfaces must not be EGL_NO_SURFACE");
   3208            return false;
   3209        }
   3210    }
   3211 
   3212    // If either of draw or read is a valid surface and the other is EGL_NO_SURFACE, an
   3213    // EGL_BAD_MATCH error is generated.
   3214    if ((read == EGL_NO_SURFACE) != (draw == EGL_NO_SURFACE))
   3215    {
   3216        val->setError(EGL_BAD_MATCH,
   3217                      "read and draw must both be valid surfaces, or both be EGL_NO_SURFACE");
   3218        return false;
   3219    }
   3220 
   3221    if (display == EGL_NO_DISPLAY || !Display::isValidDisplay(display))
   3222    {
   3223        val->setError(EGL_BAD_DISPLAY, "'dpy' not a valid EGLDisplay handle");
   3224        return false;
   3225    }
   3226 
   3227    // EGL 1.5 spec: dpy can be uninitialized if all other parameters are null
   3228    if (!display->isInitialized() &&
   3229        (context != EGL_NO_CONTEXT || draw != EGL_NO_SURFACE || read != EGL_NO_SURFACE))
   3230    {
   3231        val->setError(EGL_NOT_INITIALIZED, "'dpy' not initialized");
   3232        return false;
   3233    }
   3234 
   3235    if (context != EGL_NO_CONTEXT)
   3236    {
   3237        ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   3238    }
   3239 
   3240    if (display->isInitialized() && display->isDeviceLost())
   3241    {
   3242        val->setError(EGL_CONTEXT_LOST);
   3243        return false;
   3244    }
   3245 
   3246    if (draw != EGL_NO_SURFACE)
   3247    {
   3248        ANGLE_VALIDATION_TRY(ValidateSurface(val, display, draw));
   3249    }
   3250 
   3251    if (read != EGL_NO_SURFACE)
   3252    {
   3253        ANGLE_VALIDATION_TRY(ValidateSurface(val, display, read));
   3254        ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
   3255    }
   3256 
   3257    if (draw != read)
   3258    {
   3259        if (draw)
   3260        {
   3261            ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, draw));
   3262        }
   3263        if (read)
   3264        {
   3265            ANGLE_VALIDATION_TRY(ValidateCompatibleSurface(val, display, context, read));
   3266        }
   3267    }
   3268    return true;
   3269 }
   3270 
   3271 bool ValidateCreateImage(const ValidationContext *val,
   3272                         const Display *display,
   3273                         const gl::Context *context,
   3274                         EGLenum target,
   3275                         EGLClientBuffer buffer,
   3276                         const AttributeMap &attributes)
   3277 {
   3278 
   3279    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   3280 
   3281    attributes.initializeWithoutValidation();
   3282 
   3283    const DisplayExtensions &displayExtensions = display->getExtensions();
   3284 
   3285    // TODO(geofflang): Complete validation from EGL_KHR_image_base:
   3286    // If the resource specified by <dpy>, <ctx>, <target>, <buffer> and <attrib_list> is itself an
   3287    // EGLImage sibling, the error EGL_BAD_ACCESS is generated.
   3288 
   3289    for (AttributeMap::const_iterator attributeIter = attributes.begin();
   3290         attributeIter != attributes.end(); attributeIter++)
   3291    {
   3292        EGLAttrib attribute = attributeIter->first;
   3293        EGLAttrib value     = attributeIter->second;
   3294 
   3295        switch (attribute)
   3296        {
   3297            case EGL_IMAGE_PRESERVED:
   3298                switch (value)
   3299                {
   3300                    case EGL_TRUE:
   3301                    case EGL_FALSE:
   3302                        break;
   3303 
   3304                    default:
   3305                        val->setError(EGL_BAD_PARAMETER,
   3306                                      "EGL_IMAGE_PRESERVED must be EGL_TRUE or EGL_FALSE.");
   3307                        return false;
   3308                }
   3309                break;
   3310 
   3311            case EGL_GL_TEXTURE_LEVEL:
   3312                if (!displayExtensions.glTexture2DImage &&
   3313                    !displayExtensions.glTextureCubemapImage && !displayExtensions.glTexture3DImage)
   3314                {
   3315                    val->setError(EGL_BAD_PARAMETER,
   3316                                  "EGL_GL_TEXTURE_LEVEL cannot be used "
   3317                                  "without KHR_gl_texture_*_image support.");
   3318                    return false;
   3319                }
   3320 
   3321                if (value < 0)
   3322                {
   3323                    val->setError(EGL_BAD_PARAMETER, "EGL_GL_TEXTURE_LEVEL cannot be negative.");
   3324                    return false;
   3325                }
   3326                break;
   3327 
   3328            case EGL_GL_TEXTURE_ZOFFSET:
   3329                if (!displayExtensions.glTexture3DImage)
   3330                {
   3331                    val->setError(EGL_BAD_PARAMETER,
   3332                                  "EGL_GL_TEXTURE_ZOFFSET cannot be used "
   3333                                  "without KHR_gl_texture_3D_image support.");
   3334                    return false;
   3335                }
   3336                break;
   3337 
   3338            case EGL_GL_COLORSPACE:
   3339                if (!displayExtensions.glColorspace)
   3340                {
   3341                    val->setError(EGL_BAD_PARAMETER,
   3342                                  "EGL_GL_COLORSPACE cannot be used "
   3343                                  "without EGL_KHR_gl_colorspace support.");
   3344                    return false;
   3345                }
   3346                switch (value)
   3347                {
   3348                    case EGL_GL_COLORSPACE_DEFAULT_EXT:
   3349                        break;
   3350                    default:
   3351                        ANGLE_VALIDATION_TRY(
   3352                            ValidateColorspaceAttribute(val, displayExtensions, value));
   3353                        break;
   3354                }
   3355                break;
   3356 
   3357            case EGL_TEXTURE_INTERNAL_FORMAT_ANGLE:
   3358                if (!displayExtensions.imageD3D11Texture && !displayExtensions.vulkanImageANGLE)
   3359                {
   3360                    val->setError(
   3361                        EGL_BAD_PARAMETER,
   3362                        "EGL_TEXTURE_INTERNAL_FORMAT_ANGLE cannot be used without "
   3363                        "EGL_ANGLE_image_d3d11_texture or EGL_ANGLE_vulkan_image support.");
   3364                    return false;
   3365                }
   3366                break;
   3367 
   3368            case EGL_D3D11_TEXTURE_PLANE_ANGLE:
   3369                if (!displayExtensions.imageD3D11Texture)
   3370                {
   3371                    val->setError(EGL_BAD_ATTRIBUTE,
   3372                                  "EGL_D3D11_TEXTURE_PLANE_ANGLE cannot be used without "
   3373                                  "EGL_ANGLE_image_d3d11_texture support.");
   3374                    return false;
   3375                }
   3376                break;
   3377 
   3378            case EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE:
   3379                if (!displayExtensions.imageD3D11Texture)
   3380                {
   3381                    val->setError(EGL_BAD_ATTRIBUTE,
   3382                                  "EGL_D3D11_TEXTURE_ARRAY_SLICE_ANGLE cannot be used without "
   3383                                  "EGL_ANGLE_image_d3d11_texture support.");
   3384                    return false;
   3385                }
   3386                break;
   3387 
   3388            case EGL_WIDTH:
   3389            case EGL_HEIGHT:
   3390                if (target != EGL_LINUX_DMA_BUF_EXT)
   3391                {
   3392                    val->setError(
   3393                        EGL_BAD_PARAMETER,
   3394                        "Parameter cannot be used if target is not EGL_LINUX_DMA_BUF_EXT");
   3395                    return false;
   3396                }
   3397                break;
   3398 
   3399            case EGL_LINUX_DRM_FOURCC_EXT:
   3400            case EGL_DMA_BUF_PLANE0_FD_EXT:
   3401            case EGL_DMA_BUF_PLANE0_OFFSET_EXT:
   3402            case EGL_DMA_BUF_PLANE0_PITCH_EXT:
   3403            case EGL_DMA_BUF_PLANE1_FD_EXT:
   3404            case EGL_DMA_BUF_PLANE1_OFFSET_EXT:
   3405            case EGL_DMA_BUF_PLANE1_PITCH_EXT:
   3406            case EGL_DMA_BUF_PLANE2_FD_EXT:
   3407            case EGL_DMA_BUF_PLANE2_OFFSET_EXT:
   3408            case EGL_DMA_BUF_PLANE2_PITCH_EXT:
   3409                if (!displayExtensions.imageDmaBufImportEXT)
   3410                {
   3411                    val->setError(EGL_BAD_PARAMETER,
   3412                                  "Parameter cannot be used without "
   3413                                  "EGL_EXT_image_dma_buf_import support.");
   3414                    return false;
   3415                }
   3416                break;
   3417 
   3418            case EGL_YUV_COLOR_SPACE_HINT_EXT:
   3419                if (!displayExtensions.imageDmaBufImportEXT)
   3420                {
   3421                    val->setError(EGL_BAD_PARAMETER,
   3422                                  "Parameter cannot be used without "
   3423                                  "EGL_EXT_image_dma_buf_import support.");
   3424                    return false;
   3425                }
   3426 
   3427                switch (value)
   3428                {
   3429                    case EGL_ITU_REC601_EXT:
   3430                    case EGL_ITU_REC709_EXT:
   3431                    case EGL_ITU_REC2020_EXT:
   3432                        break;
   3433 
   3434                    default:
   3435                        val->setError(EGL_BAD_PARAMETER,
   3436                                      "Invalid value for EGL_YUV_COLOR_SPACE_HINT_EXT.");
   3437                        return false;
   3438                }
   3439                break;
   3440 
   3441            case EGL_SAMPLE_RANGE_HINT_EXT:
   3442                if (!displayExtensions.imageDmaBufImportEXT)
   3443                {
   3444                    val->setError(EGL_BAD_PARAMETER,
   3445                                  "Parameter cannot be used without "
   3446                                  "EGL_EXT_image_dma_buf_import support.");
   3447                    return false;
   3448                }
   3449 
   3450                switch (value)
   3451                {
   3452                    case EGL_YUV_FULL_RANGE_EXT:
   3453                    case EGL_YUV_NARROW_RANGE_EXT:
   3454                        break;
   3455 
   3456                    default:
   3457                        val->setError(EGL_BAD_PARAMETER,
   3458                                      "Invalid value for EGL_SAMPLE_RANGE_HINT_EXT.");
   3459                        return false;
   3460                }
   3461                break;
   3462 
   3463            case EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT:
   3464            case EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT:
   3465                if (!displayExtensions.imageDmaBufImportEXT)
   3466                {
   3467                    val->setError(EGL_BAD_PARAMETER,
   3468                                  "Parameter cannot be used without "
   3469                                  "EGL_EXT_image_dma_buf_import support.");
   3470                    return false;
   3471                }
   3472 
   3473                switch (value)
   3474                {
   3475                    case EGL_YUV_CHROMA_SITING_0_EXT:
   3476                    case EGL_YUV_CHROMA_SITING_0_5_EXT:
   3477                        break;
   3478 
   3479                    default:
   3480                        val->setError(
   3481                            EGL_BAD_PARAMETER,
   3482                            "Invalid value for EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT or "
   3483                            "EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT.");
   3484                        return false;
   3485                }
   3486                break;
   3487 
   3488            case EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT:
   3489            case EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT:
   3490            case EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT:
   3491            case EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT:
   3492            case EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT:
   3493            case EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT:
   3494            case EGL_DMA_BUF_PLANE3_FD_EXT:
   3495            case EGL_DMA_BUF_PLANE3_OFFSET_EXT:
   3496            case EGL_DMA_BUF_PLANE3_PITCH_EXT:
   3497            case EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT:
   3498            case EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT:
   3499                if (!displayExtensions.imageDmaBufImportModifiersEXT)
   3500                {
   3501                    val->setError(EGL_BAD_PARAMETER,
   3502                                  "Parameter cannot be used without "
   3503                                  "EGL_EXT_image_dma_buf_import_modifiers support.");
   3504                    return false;
   3505                }
   3506                break;
   3507 
   3508            case EGL_PROTECTED_CONTENT_EXT:
   3509                if (!displayExtensions.protectedContentEXT)
   3510                {
   3511                    val->setError(EGL_BAD_ATTRIBUTE,
   3512                                  "Attribute EGL_PROTECTED_CONTEXT_EXT requires "
   3513                                  "extension EGL_EXT_protected_content.");
   3514                    return false;
   3515                }
   3516                if (value != EGL_TRUE && value != EGL_FALSE)
   3517                {
   3518                    val->setError(EGL_BAD_ATTRIBUTE,
   3519                                  "EGL_PROTECTED_CONTENT_EXT must "
   3520                                  "be either EGL_TRUE or EGL_FALSE.");
   3521                    return false;
   3522                }
   3523                break;
   3524 
   3525            case EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE:
   3526            case EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE:
   3527                if (!displayExtensions.vulkanImageANGLE)
   3528                {
   3529                    val->setError(EGL_BAD_ATTRIBUTE,
   3530                                  "Attribute EGL_VULKAN_IMAGE_CREATE_INFO_{HI,LO}_ANGLE require "
   3531                                  "extension EGL_ANGLE_vulkan_image.");
   3532                    return false;
   3533                }
   3534                break;
   3535 
   3536            default:
   3537                val->setError(EGL_BAD_PARAMETER, "invalid attribute: 0x%04" PRIxPTR "X", attribute);
   3538                return false;
   3539        }
   3540    }
   3541 
   3542    switch (target)
   3543    {
   3544        case EGL_GL_TEXTURE_2D:
   3545        {
   3546            if (!displayExtensions.glTexture2DImage)
   3547            {
   3548                val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_2D_image not supported.");
   3549                return false;
   3550            }
   3551 
   3552            if (buffer == 0)
   3553            {
   3554                val->setError(EGL_BAD_PARAMETER,
   3555                              "buffer cannot reference a 2D texture with the name 0.");
   3556                return false;
   3557            }
   3558 
   3559            ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   3560            const gl::Texture *texture =
   3561                context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
   3562            if (texture == nullptr || texture->getType() != gl::TextureType::_2D)
   3563            {
   3564                val->setError(EGL_BAD_PARAMETER, "target is not a 2D texture.");
   3565                return false;
   3566            }
   3567 
   3568            if (texture->getBoundSurface() != nullptr)
   3569            {
   3570                val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
   3571                return false;
   3572            }
   3573 
   3574            EGLAttrib level = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
   3575            if (texture->getWidth(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0 ||
   3576                texture->getHeight(gl::TextureTarget::_2D, static_cast<size_t>(level)) == 0)
   3577            {
   3578                val->setError(EGL_BAD_PARAMETER,
   3579                              "target 2D texture does not have a valid size at specified level.");
   3580                return false;
   3581            }
   3582 
   3583            bool protectedContentAttrib =
   3584                (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
   3585            if (protectedContentAttrib != texture->hasProtectedContent())
   3586            {
   3587                val->setError(EGL_BAD_PARAMETER,
   3588                              "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
   3589                              "of target.");
   3590                return false;
   3591            }
   3592 
   3593            ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
   3594        }
   3595        break;
   3596 
   3597        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X:
   3598        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
   3599        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
   3600        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
   3601        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
   3602        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
   3603        {
   3604            if (!displayExtensions.glTextureCubemapImage)
   3605            {
   3606                val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_cubemap_image not supported.");
   3607                return false;
   3608            }
   3609 
   3610            if (buffer == 0)
   3611            {
   3612                val->setError(EGL_BAD_PARAMETER,
   3613                              "buffer cannot reference a cubemap texture with the name 0.");
   3614                return false;
   3615            }
   3616 
   3617            ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   3618            const gl::Texture *texture =
   3619                context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
   3620            if (texture == nullptr || texture->getType() != gl::TextureType::CubeMap)
   3621            {
   3622                val->setError(EGL_BAD_PARAMETER, "target is not a cubemap texture.");
   3623                return false;
   3624            }
   3625 
   3626            if (texture->getBoundSurface() != nullptr)
   3627            {
   3628                val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
   3629                return false;
   3630            }
   3631 
   3632            EGLAttrib level               = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
   3633            gl::TextureTarget cubeMapFace = egl_gl::EGLCubeMapTargetToCubeMapTarget(target);
   3634            if (texture->getWidth(cubeMapFace, static_cast<size_t>(level)) == 0 ||
   3635                texture->getHeight(cubeMapFace, static_cast<size_t>(level)) == 0)
   3636            {
   3637                val->setError(EGL_BAD_PARAMETER,
   3638                              "target cubemap texture does not have a valid "
   3639                              "size at specified level and face.");
   3640                return false;
   3641            }
   3642 
   3643            ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
   3644 
   3645            if (level == 0 && !texture->isMipmapComplete() &&
   3646                CubeTextureHasUnspecifiedLevel0Face(texture))
   3647            {
   3648                val->setError(EGL_BAD_PARAMETER,
   3649                              "if level is zero and the texture is incomplete, "
   3650                              "it must have all of its faces specified at level "
   3651                              "zero.");
   3652                return false;
   3653            }
   3654 
   3655            bool protectedContentAttrib =
   3656                (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
   3657            if (protectedContentAttrib != texture->hasProtectedContent())
   3658            {
   3659                val->setError(EGL_BAD_PARAMETER,
   3660                              "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
   3661                              "of target.");
   3662                return false;
   3663            }
   3664        }
   3665        break;
   3666 
   3667        case EGL_GL_TEXTURE_3D:
   3668        {
   3669            if (!displayExtensions.glTexture3DImage)
   3670            {
   3671                val->setError(EGL_BAD_PARAMETER, "KHR_gl_texture_3D_image not supported.");
   3672                return false;
   3673            }
   3674 
   3675            if (buffer == 0)
   3676            {
   3677                val->setError(EGL_BAD_PARAMETER,
   3678                              "buffer cannot reference a 3D texture with the name 0.");
   3679                return false;
   3680            }
   3681 
   3682            ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   3683            const gl::Texture *texture =
   3684                context->getTexture({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
   3685            if (texture == nullptr || texture->getType() != gl::TextureType::_3D)
   3686            {
   3687                val->setError(EGL_BAD_PARAMETER, "target is not a 3D texture.");
   3688                return false;
   3689            }
   3690 
   3691            if (texture->getBoundSurface() != nullptr)
   3692            {
   3693                val->setError(EGL_BAD_ACCESS, "texture has a surface bound to it.");
   3694                return false;
   3695            }
   3696 
   3697            EGLAttrib level   = attributes.get(EGL_GL_TEXTURE_LEVEL, 0);
   3698            EGLAttrib zOffset = attributes.get(EGL_GL_TEXTURE_ZOFFSET, 0);
   3699            if (texture->getWidth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
   3700                texture->getHeight(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0 ||
   3701                texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)) == 0)
   3702            {
   3703                val->setError(EGL_BAD_PARAMETER,
   3704                              "target 3D texture does not have a valid size at specified level.");
   3705                return false;
   3706            }
   3707 
   3708            if (static_cast<size_t>(zOffset) >=
   3709                texture->getDepth(gl::TextureTarget::_3D, static_cast<size_t>(level)))
   3710            {
   3711                val->setError(EGL_BAD_PARAMETER,
   3712                              "target 3D texture does not have enough layers "
   3713                              "for the specified Z offset at the specified "
   3714                              "level.");
   3715                return false;
   3716            }
   3717 
   3718            bool protectedContentAttrib =
   3719                (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
   3720            if (protectedContentAttrib != texture->hasProtectedContent())
   3721            {
   3722                val->setError(EGL_BAD_PARAMETER,
   3723                              "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
   3724                              "of target.");
   3725                return false;
   3726            }
   3727 
   3728            ANGLE_VALIDATION_TRY(ValidateCreateImageMipLevelCommon(val, context, texture, level));
   3729        }
   3730        break;
   3731 
   3732        case EGL_GL_RENDERBUFFER:
   3733        {
   3734            if (!displayExtensions.glRenderbufferImage)
   3735            {
   3736                val->setError(EGL_BAD_PARAMETER, "KHR_gl_renderbuffer_image not supported.");
   3737                return false;
   3738            }
   3739 
   3740            if (attributes.contains(EGL_GL_TEXTURE_LEVEL))
   3741            {
   3742                val->setError(EGL_BAD_PARAMETER,
   3743                              "EGL_GL_TEXTURE_LEVEL cannot be used in "
   3744                              "conjunction with a renderbuffer target.");
   3745                return false;
   3746            }
   3747 
   3748            if (buffer == 0)
   3749            {
   3750                val->setError(EGL_BAD_PARAMETER,
   3751                              "buffer cannot reference a renderbuffer with the name 0.");
   3752                return false;
   3753            }
   3754 
   3755            ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   3756            const gl::Renderbuffer *renderbuffer =
   3757                context->getRenderbuffer({egl_gl::EGLClientBufferToGLObjectHandle(buffer)});
   3758            if (renderbuffer == nullptr)
   3759            {
   3760                val->setError(EGL_BAD_PARAMETER, "target is not a renderbuffer.");
   3761                return false;
   3762            }
   3763 
   3764            if (renderbuffer->getSamples() > 0)
   3765            {
   3766                val->setError(EGL_BAD_PARAMETER, "target renderbuffer cannot be multisampled.");
   3767                return false;
   3768            }
   3769 
   3770            bool protectedContentAttrib =
   3771                (attributes.getAsInt(EGL_PROTECTED_CONTENT_EXT, EGL_FALSE) != EGL_FALSE);
   3772            if (protectedContentAttrib != renderbuffer->hasProtectedContent())
   3773            {
   3774                val->setError(EGL_BAD_ACCESS,
   3775                              "EGL_PROTECTED_CONTENT_EXT attribute does not match protected state "
   3776                              "of target.");
   3777                return false;
   3778            }
   3779        }
   3780        break;
   3781 
   3782        case EGL_NATIVE_BUFFER_ANDROID:
   3783        {
   3784            if (!displayExtensions.imageNativeBuffer)
   3785            {
   3786                val->setError(EGL_BAD_PARAMETER, "EGL_ANDROID_image_native_buffer not supported.");
   3787                return false;
   3788            }
   3789 
   3790            if (context != nullptr)
   3791            {
   3792                val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
   3793                return false;
   3794            }
   3795 
   3796            ANGLE_EGL_TRY_RETURN(
   3797                val->eglThread,
   3798                display->validateImageClientBuffer(context, target, buffer, attributes),
   3799                val->entryPoint, val->labeledObject, false);
   3800        }
   3801        break;
   3802 
   3803        case EGL_D3D11_TEXTURE_ANGLE:
   3804            if (!displayExtensions.imageD3D11Texture)
   3805            {
   3806                val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_image_d3d11_texture not supported.");
   3807                return false;
   3808            }
   3809 
   3810            if (context != nullptr)
   3811            {
   3812                val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
   3813                return false;
   3814            }
   3815 
   3816            ANGLE_EGL_TRY_RETURN(
   3817                val->eglThread,
   3818                display->validateImageClientBuffer(context, target, buffer, attributes),
   3819                val->entryPoint, val->labeledObject, false);
   3820            break;
   3821 
   3822        case EGL_LINUX_DMA_BUF_EXT:
   3823            if (!displayExtensions.imageDmaBufImportEXT)
   3824            {
   3825                val->setError(EGL_BAD_PARAMETER, "EGL_EXT_image_dma_buf_import not supported.");
   3826                return false;
   3827            }
   3828 
   3829            if (context != nullptr)
   3830            {
   3831                val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
   3832                return false;
   3833            }
   3834 
   3835            if (buffer != nullptr)
   3836            {
   3837                val->setError(EGL_BAD_PARAMETER, "buffer must be NULL.");
   3838                return false;
   3839            }
   3840 
   3841            {
   3842                EGLenum kRequiredParameters[] = {EGL_WIDTH,
   3843                                                 EGL_HEIGHT,
   3844                                                 EGL_LINUX_DRM_FOURCC_EXT,
   3845                                                 EGL_DMA_BUF_PLANE0_FD_EXT,
   3846                                                 EGL_DMA_BUF_PLANE0_OFFSET_EXT,
   3847                                                 EGL_DMA_BUF_PLANE0_PITCH_EXT};
   3848                for (EGLenum requiredParameter : kRequiredParameters)
   3849                {
   3850                    if (!attributes.contains(requiredParameter))
   3851                    {
   3852                        val->setError(EGL_BAD_PARAMETER,
   3853                                      "Missing required parameter 0x%X for image target "
   3854                                      "EGL_LINUX_DMA_BUF_EXT.",
   3855                                      requiredParameter);
   3856                        return false;
   3857                    }
   3858                }
   3859 
   3860                bool containPlane0ModifierLo =
   3861                    attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT);
   3862                bool containPlane0ModifierHi =
   3863                    attributes.contains(EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT);
   3864                bool containPlane1ModifierLo =
   3865                    attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_LO_EXT);
   3866                bool containPlane1ModifierHi =
   3867                    attributes.contains(EGL_DMA_BUF_PLANE1_MODIFIER_HI_EXT);
   3868                bool containPlane2ModifierLo =
   3869                    attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_LO_EXT);
   3870                bool containPlane2ModifierHi =
   3871                    attributes.contains(EGL_DMA_BUF_PLANE2_MODIFIER_HI_EXT);
   3872                bool containPlane3ModifierLo =
   3873                    attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_LO_EXT);
   3874                bool containPlane3ModifierHi =
   3875                    attributes.contains(EGL_DMA_BUF_PLANE3_MODIFIER_HI_EXT);
   3876                if ((containPlane0ModifierLo ^ containPlane0ModifierHi) ||
   3877                    (containPlane1ModifierLo ^ containPlane1ModifierHi) ||
   3878                    (containPlane2ModifierLo ^ containPlane2ModifierHi) ||
   3879                    (containPlane3ModifierLo ^ containPlane3ModifierHi))
   3880                {
   3881                    val->setError(
   3882                        EGL_BAD_PARAMETER,
   3883                        "the list of attributes contains EGL_DMA_BUF_PLANE*_MODIFIER_LO_EXT "
   3884                        "but not EGL_DMA_BUF_PLANE*_MODIFIER_HI_EXT or vice versa.");
   3885                    return false;
   3886                }
   3887            }
   3888            break;
   3889 
   3890        case EGL_METAL_TEXTURE_ANGLE:
   3891            if (!displayExtensions.mtlTextureClientBuffer)
   3892            {
   3893                val->setError(EGL_BAD_PARAMETER,
   3894                              "EGL_ANGLE_metal_texture_client_buffer not supported.");
   3895                return false;
   3896            }
   3897 
   3898            if (context != nullptr)
   3899            {
   3900                val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
   3901                return false;
   3902            }
   3903 
   3904            ANGLE_EGL_TRY_RETURN(
   3905                val->eglThread,
   3906                display->validateImageClientBuffer(context, target, buffer, attributes),
   3907                val->entryPoint, val->labeledObject, false);
   3908            break;
   3909        case EGL_VULKAN_IMAGE_ANGLE:
   3910            if (!displayExtensions.vulkanImageANGLE)
   3911            {
   3912                val->setError(EGL_BAD_PARAMETER, "EGL_ANGLE_vulkan_image not supported.");
   3913                return false;
   3914            }
   3915 
   3916            if (context != nullptr)
   3917            {
   3918                val->setError(EGL_BAD_CONTEXT, "ctx must be EGL_NO_CONTEXT.");
   3919                return false;
   3920            }
   3921 
   3922            {
   3923                const EGLenum kRequiredParameters[] = {
   3924                    EGL_VULKAN_IMAGE_CREATE_INFO_HI_ANGLE,
   3925                    EGL_VULKAN_IMAGE_CREATE_INFO_LO_ANGLE,
   3926                };
   3927                for (EGLenum requiredParameter : kRequiredParameters)
   3928                {
   3929                    if (!attributes.contains(requiredParameter))
   3930                    {
   3931                        val->setError(EGL_BAD_PARAMETER,
   3932                                      "Missing required parameter 0x%X for image target "
   3933                                      "EGL_VULKAN_IMAGE_ANGLE.",
   3934                                      requiredParameter);
   3935                        return false;
   3936                    }
   3937                }
   3938            }
   3939 
   3940            ANGLE_EGL_TRY_RETURN(
   3941                val->eglThread,
   3942                display->validateImageClientBuffer(context, target, buffer, attributes),
   3943                val->entryPoint, val->labeledObject, false);
   3944            break;
   3945        default:
   3946            val->setError(EGL_BAD_PARAMETER, "invalid target: 0x%X", target);
   3947            return false;
   3948    }
   3949 
   3950    if (attributes.contains(EGL_GL_TEXTURE_ZOFFSET) && target != EGL_GL_TEXTURE_3D)
   3951    {
   3952        val->setError(EGL_BAD_PARAMETER,
   3953                      "EGL_GL_TEXTURE_ZOFFSET must be used with a 3D texture target.");
   3954        return false;
   3955    }
   3956 
   3957    return true;
   3958 }
   3959 
   3960 bool ValidateDestroyImage(const ValidationContext *val, const Display *display, const Image *image)
   3961 {
   3962    ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
   3963 
   3964    return true;
   3965 }
   3966 
   3967 bool ValidateCreateImageKHR(const ValidationContext *val,
   3968                            const Display *display,
   3969                            const gl::Context *context,
   3970                            EGLenum target,
   3971                            EGLClientBuffer buffer,
   3972                            const AttributeMap &attributes)
   3973 {
   3974    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   3975 
   3976    if (!display->getExtensions().imageBase && !display->getExtensions().image)
   3977    {
   3978        // It is out of spec what happens when calling an extension function when the extension is
   3979        // not available.
   3980        // EGL_BAD_DISPLAY seems like a reasonable error.
   3981        val->setError(EGL_BAD_DISPLAY, "EGL_KHR_image not supported.");
   3982        return false;
   3983    }
   3984 
   3985    return ValidateCreateImage(val, display, context, target, buffer, attributes);
   3986 }
   3987 
   3988 bool ValidateDestroyImageKHR(const ValidationContext *val,
   3989                             const Display *display,
   3990                             const Image *image)
   3991 {
   3992    ANGLE_VALIDATION_TRY(ValidateImage(val, display, image));
   3993 
   3994    if (!display->getExtensions().imageBase && !display->getExtensions().image)
   3995    {
   3996        // It is out of spec what happens when calling an extension function when the extension is
   3997        // not available.
   3998        // EGL_BAD_DISPLAY seems like a reasonable error.
   3999        val->setError(EGL_BAD_DISPLAY);
   4000        return false;
   4001    }
   4002 
   4003    return true;
   4004 }
   4005 
   4006 bool ValidateCreateDeviceANGLE(const ValidationContext *val,
   4007                               EGLint device_type,
   4008                               const void *native_device,
   4009                               const EGLAttrib *attrib_list)
   4010 {
   4011    const ClientExtensions &clientExtensions = Display::GetClientExtensions();
   4012    if (!clientExtensions.deviceCreation)
   4013    {
   4014        val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
   4015        return false;
   4016    }
   4017 
   4018    if (attrib_list != nullptr && attrib_list[0] != EGL_NONE)
   4019    {
   4020        val->setError(EGL_BAD_ATTRIBUTE, "Invalid attrib_list parameter");
   4021        return false;
   4022    }
   4023 
   4024    switch (device_type)
   4025    {
   4026        case EGL_D3D11_DEVICE_ANGLE:
   4027            if (!clientExtensions.deviceCreationD3D11)
   4028            {
   4029                val->setError(EGL_BAD_ATTRIBUTE, "D3D11 device creation extension not active");
   4030                return false;
   4031            }
   4032            break;
   4033        default:
   4034            val->setError(EGL_BAD_ATTRIBUTE, "Invalid device_type parameter");
   4035            return false;
   4036    }
   4037 
   4038    return true;
   4039 }
   4040 
   4041 bool ValidateReleaseDeviceANGLE(const ValidationContext *val, const Device *device)
   4042 {
   4043    const ClientExtensions &clientExtensions = Display::GetClientExtensions();
   4044    if (!clientExtensions.deviceCreation)
   4045    {
   4046        val->setError(EGL_BAD_ACCESS, "Device creation extension not active");
   4047        return false;
   4048    }
   4049 
   4050    if (device == EGL_NO_DEVICE_EXT || !Device::IsValidDevice(device))
   4051    {
   4052        val->setError(EGL_BAD_DEVICE_EXT, "Invalid device parameter");
   4053        return false;
   4054    }
   4055 
   4056    Display *owningDisplay = device->getOwningDisplay();
   4057    if (owningDisplay != nullptr)
   4058    {
   4059        val->setError(EGL_BAD_DEVICE_EXT, "Device must have been created using eglCreateDevice");
   4060        return false;
   4061    }
   4062 
   4063    return true;
   4064 }
   4065 
   4066 bool ValidateCreateSync(const ValidationContext *val,
   4067                        const Display *display,
   4068                        EGLenum type,
   4069                        const AttributeMap &attribs)
   4070 {
   4071    return ValidateCreateSyncBase(val, display, type, attribs, false);
   4072 }
   4073 
   4074 bool ValidateCreateSyncKHR(const ValidationContext *val,
   4075                           const Display *display,
   4076                           EGLenum type,
   4077                           const AttributeMap &attribs)
   4078 {
   4079    return ValidateCreateSyncBase(val, display, type, attribs, true);
   4080 }
   4081 
   4082 bool ValidateDestroySync(const ValidationContext *val, const Display *display, const Sync *sync)
   4083 {
   4084    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   4085    return true;
   4086 }
   4087 
   4088 bool ValidateDestroySyncKHR(const ValidationContext *val,
   4089                            const Display *dpyPacked,
   4090                            const Sync *syncPacked)
   4091 {
   4092    return ValidateDestroySync(val, dpyPacked, syncPacked);
   4093 }
   4094 
   4095 bool ValidateClientWaitSync(const ValidationContext *val,
   4096                            const Display *display,
   4097                            const Sync *sync,
   4098                            EGLint flags,
   4099                            EGLTime timeout)
   4100 {
   4101    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   4102    return true;
   4103 }
   4104 
   4105 bool ValidateClientWaitSyncKHR(const ValidationContext *val,
   4106                               const Display *dpyPacked,
   4107                               const Sync *syncPacked,
   4108                               EGLint flags,
   4109                               EGLTimeKHR timeout)
   4110 {
   4111    return ValidateClientWaitSync(val, dpyPacked, syncPacked, flags, timeout);
   4112 }
   4113 
   4114 bool ValidateWaitSync(const ValidationContext *val,
   4115                      const Display *display,
   4116                      const Sync *sync,
   4117                      EGLint flags)
   4118 {
   4119    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4120 
   4121    const DisplayExtensions &extensions = display->getExtensions();
   4122    if (!extensions.waitSync)
   4123    {
   4124        val->setError(EGL_BAD_ACCESS, "EGL_KHR_wait_sync extension is not available");
   4125        return false;
   4126    }
   4127 
   4128    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   4129 
   4130    gl::Context *context = val->eglThread->getContext();
   4131    if (context == nullptr)
   4132    {
   4133        val->setError(EGL_BAD_MATCH, "No context is current.");
   4134        return false;
   4135    }
   4136 
   4137    if (!context->getExtensions().EGLSyncOES)
   4138    {
   4139        val->setError(EGL_BAD_MATCH,
   4140                      "Server-side waits cannot be performed without "
   4141                      "GL_OES_EGL_sync support.");
   4142        return false;
   4143    }
   4144 
   4145    if (flags != 0)
   4146    {
   4147        val->setError(EGL_BAD_PARAMETER, "flags must be zero");
   4148        return false;
   4149    }
   4150 
   4151    return true;
   4152 }
   4153 
   4154 bool ValidateWaitSyncKHR(const ValidationContext *val,
   4155                         const Display *dpyPacked,
   4156                         const Sync *syncPacked,
   4157                         EGLint flags)
   4158 {
   4159    return ValidateWaitSync(val, dpyPacked, syncPacked, flags);
   4160 }
   4161 
   4162 bool ValidateGetSyncAttrib(const ValidationContext *val,
   4163                           const Display *display,
   4164                           const Sync *sync,
   4165                           EGLint attribute,
   4166                           const EGLAttrib *value)
   4167 {
   4168    if (value == nullptr)
   4169    {
   4170        val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
   4171        return false;
   4172    }
   4173    return ValidateGetSyncAttribBase(val, display, sync, attribute);
   4174 }
   4175 
   4176 bool ValidateGetSyncAttribKHR(const ValidationContext *val,
   4177                              const Display *display,
   4178                              const Sync *sync,
   4179                              EGLint attribute,
   4180                              const EGLint *value)
   4181 {
   4182    if (value == nullptr)
   4183    {
   4184        val->setError(EGL_BAD_PARAMETER, "Invalid value parameter");
   4185        return false;
   4186    }
   4187    return ValidateGetSyncAttribBase(val, display, sync, attribute);
   4188 }
   4189 
   4190 bool ValidateCreateStreamKHR(const ValidationContext *val,
   4191                             const Display *display,
   4192                             const AttributeMap &attributes)
   4193 {
   4194    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4195 
   4196    const DisplayExtensions &displayExtensions = display->getExtensions();
   4197    if (!displayExtensions.stream)
   4198    {
   4199        val->setError(EGL_BAD_ALLOC, "Stream extension not active");
   4200        return false;
   4201    }
   4202 
   4203    attributes.initializeWithoutValidation();
   4204 
   4205    for (const auto &attributeIter : attributes)
   4206    {
   4207        EGLAttrib attribute = attributeIter.first;
   4208        EGLAttrib value     = attributeIter.second;
   4209 
   4210        ANGLE_VALIDATION_TRY(ValidateStreamAttribute(val, attribute, value, displayExtensions));
   4211    }
   4212 
   4213    return true;
   4214 }
   4215 
   4216 bool ValidateDestroyStreamKHR(const ValidationContext *val,
   4217                              const Display *display,
   4218                              const Stream *stream)
   4219 {
   4220    ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   4221    return true;
   4222 }
   4223 
   4224 bool ValidateStreamAttribKHR(const ValidationContext *val,
   4225                             const Display *display,
   4226                             const Stream *stream,
   4227                             EGLenum attribute,
   4228                             EGLint value)
   4229 {
   4230    ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   4231 
   4232    if (stream->getState() == EGL_STREAM_STATE_DISCONNECTED_KHR)
   4233    {
   4234        val->setError(EGL_BAD_STATE_KHR, "Bad stream state");
   4235        return false;
   4236    }
   4237 
   4238    return ValidateStreamAttribute(val, attribute, value, display->getExtensions());
   4239 }
   4240 
   4241 bool ValidateQueryStreamKHR(const ValidationContext *val,
   4242                            const Display *display,
   4243                            const Stream *stream,
   4244                            EGLenum attribute,
   4245                            const EGLint *value)
   4246 {
   4247    ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   4248 
   4249    switch (attribute)
   4250    {
   4251        case EGL_STREAM_STATE_KHR:
   4252        case EGL_CONSUMER_LATENCY_USEC_KHR:
   4253            break;
   4254        case EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR:
   4255            if (!display->getExtensions().streamConsumerGLTexture)
   4256            {
   4257                val->setError(EGL_BAD_ATTRIBUTE, "Consumer GLTexture extension not active");
   4258                return false;
   4259            }
   4260            break;
   4261        default:
   4262            val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   4263            return false;
   4264    }
   4265 
   4266    return true;
   4267 }
   4268 
   4269 bool ValidateQueryStreamu64KHR(const ValidationContext *val,
   4270                               const Display *display,
   4271                               const Stream *stream,
   4272                               EGLenum attribute,
   4273                               const EGLuint64KHR *value)
   4274 {
   4275    ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   4276 
   4277    switch (attribute)
   4278    {
   4279        case EGL_CONSUMER_FRAME_KHR:
   4280        case EGL_PRODUCER_FRAME_KHR:
   4281            break;
   4282        default:
   4283            val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   4284            return false;
   4285    }
   4286 
   4287    return true;
   4288 }
   4289 
   4290 bool ValidateStreamConsumerGLTextureExternalKHR(const ValidationContext *val,
   4291                                                const Display *display,
   4292                                                const Stream *stream)
   4293 {
   4294    gl::Context *context = val->eglThread->getContext();
   4295    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   4296 
   4297    const DisplayExtensions &displayExtensions = display->getExtensions();
   4298    if (!displayExtensions.streamConsumerGLTexture)
   4299    {
   4300        val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
   4301        return false;
   4302    }
   4303 
   4304    if (!context->getExtensions().EGLStreamConsumerExternalNV)
   4305    {
   4306        val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
   4307        return false;
   4308    }
   4309 
   4310    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
   4311    {
   4312        val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
   4313        return false;
   4314    }
   4315 
   4316    if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
   4317    {
   4318        val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
   4319        return false;
   4320    }
   4321 
   4322    // Lookup the texture and ensure it is correct
   4323    gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
   4324    if (texture == nullptr || texture->id().value == 0)
   4325    {
   4326        val->setError(EGL_BAD_ACCESS, "No external texture bound");
   4327        return false;
   4328    }
   4329 
   4330    return true;
   4331 }
   4332 
   4333 bool ValidateStreamConsumerAcquireKHR(const ValidationContext *val,
   4334                                      const Display *display,
   4335                                      const Stream *stream)
   4336 {
   4337    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4338 
   4339    const DisplayExtensions &displayExtensions = display->getExtensions();
   4340    if (!displayExtensions.streamConsumerGLTexture)
   4341    {
   4342        val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
   4343        return false;
   4344    }
   4345 
   4346    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
   4347    {
   4348        val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
   4349        return false;
   4350    }
   4351 
   4352    gl::Context *context = val->eglThread->getContext();
   4353    if (!context)
   4354    {
   4355        val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
   4356        return false;
   4357    }
   4358 
   4359    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   4360 
   4361    if (!stream->isConsumerBoundToContext(context))
   4362    {
   4363        val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
   4364        return false;
   4365    }
   4366 
   4367    if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
   4368        stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
   4369    {
   4370        val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
   4371        return false;
   4372    }
   4373 
   4374    // Note: technically EGL_STREAM_STATE_EMPTY_KHR is a valid state when the timeout is non-zero.
   4375    // However, the timeout is effectively ignored since it has no useful functionality with the
   4376    // current producers that are implemented, so we don't allow that state
   4377    if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
   4378        stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
   4379    {
   4380        val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
   4381        return false;
   4382    }
   4383 
   4384    return true;
   4385 }
   4386 
   4387 bool ValidateStreamConsumerReleaseKHR(const ValidationContext *val,
   4388                                      const Display *display,
   4389                                      const Stream *stream)
   4390 {
   4391    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4392 
   4393    const DisplayExtensions &displayExtensions = display->getExtensions();
   4394    if (!displayExtensions.streamConsumerGLTexture)
   4395    {
   4396        val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
   4397        return false;
   4398    }
   4399 
   4400    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
   4401    {
   4402        val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
   4403        return false;
   4404    }
   4405 
   4406    gl::Context *context = val->eglThread->getContext();
   4407    if (!context)
   4408    {
   4409        val->setError(EGL_BAD_ACCESS, "No GL context current to calling thread.");
   4410        return false;
   4411    }
   4412 
   4413    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   4414 
   4415    if (!stream->isConsumerBoundToContext(context))
   4416    {
   4417        val->setError(EGL_BAD_ACCESS, "Current GL context not associated with stream consumer");
   4418        return false;
   4419    }
   4420 
   4421    if (stream->getConsumerType() != Stream::ConsumerType::GLTextureRGB &&
   4422        stream->getConsumerType() != Stream::ConsumerType::GLTextureYUV)
   4423    {
   4424        val->setError(EGL_BAD_ACCESS, "Invalid stream consumer type");
   4425        return false;
   4426    }
   4427 
   4428    if (stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
   4429        stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
   4430    {
   4431        val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
   4432        return false;
   4433    }
   4434 
   4435    return true;
   4436 }
   4437 
   4438 bool ValidateStreamConsumerGLTextureExternalAttribsNV(const ValidationContext *val,
   4439                                                      const Display *display,
   4440                                                      const Stream *stream,
   4441                                                      const AttributeMap &attribs)
   4442 {
   4443    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4444 
   4445    const DisplayExtensions &displayExtensions = display->getExtensions();
   4446    if (!displayExtensions.streamConsumerGLTexture)
   4447    {
   4448        val->setError(EGL_BAD_ACCESS, "Stream consumer extension not active");
   4449        return false;
   4450    }
   4451 
   4452    gl::Context *context = val->eglThread->getContext();
   4453    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   4454 
   4455    // Although technically not a requirement in spec, the context needs to be checked for support
   4456    // for external textures or future logic will cause assertations. This extension is also
   4457    // effectively useless without external textures.
   4458    if (!context->getExtensions().EGLStreamConsumerExternalNV)
   4459    {
   4460        val->setError(EGL_BAD_ACCESS, "EGL stream consumer external GL extension not enabled");
   4461        return false;
   4462    }
   4463 
   4464    if (stream == EGL_NO_STREAM_KHR || !display->isValidStream(stream))
   4465    {
   4466        val->setError(EGL_BAD_STREAM_KHR, "Invalid stream");
   4467        return false;
   4468    }
   4469 
   4470    if (stream->getState() != EGL_STREAM_STATE_CREATED_KHR)
   4471    {
   4472        val->setError(EGL_BAD_STATE_KHR, "Invalid stream state");
   4473        return false;
   4474    }
   4475 
   4476    const gl::Caps &glCaps = context->getCaps();
   4477 
   4478    EGLAttrib colorBufferType = EGL_RGB_BUFFER;
   4479    EGLAttrib planeCount      = -1;
   4480    EGLAttrib plane[3];
   4481    for (int i = 0; i < 3; i++)
   4482    {
   4483        plane[i] = -1;
   4484    }
   4485 
   4486    attribs.initializeWithoutValidation();
   4487 
   4488    for (const auto &attributeIter : attribs)
   4489    {
   4490        EGLAttrib attribute = attributeIter.first;
   4491        EGLAttrib value     = attributeIter.second;
   4492 
   4493        switch (attribute)
   4494        {
   4495            case EGL_COLOR_BUFFER_TYPE:
   4496                if (value != EGL_RGB_BUFFER && value != EGL_YUV_BUFFER_EXT)
   4497                {
   4498                    val->setError(EGL_BAD_PARAMETER, "Invalid color buffer type");
   4499                    return false;
   4500                }
   4501                colorBufferType = value;
   4502                break;
   4503            case EGL_YUV_NUMBER_OF_PLANES_EXT:
   4504                // planeCount = -1 is a tag for the default plane count so the value must be checked
   4505                // to be positive here to ensure future logic doesn't break on invalid negative
   4506                // inputs
   4507                if (value < 0)
   4508                {
   4509                    val->setError(EGL_BAD_MATCH, "Invalid plane count");
   4510                    return false;
   4511                }
   4512                planeCount = value;
   4513                break;
   4514            default:
   4515                if (attribute >= EGL_YUV_PLANE0_TEXTURE_UNIT_NV &&
   4516                    attribute <= EGL_YUV_PLANE2_TEXTURE_UNIT_NV)
   4517                {
   4518                    if ((value < 0 ||
   4519                         value >= static_cast<EGLAttrib>(glCaps.maxCombinedTextureImageUnits)) &&
   4520                        value != EGL_NONE)
   4521                    {
   4522                        val->setError(EGL_BAD_ACCESS, "Invalid texture unit");
   4523                        return false;
   4524                    }
   4525                    plane[attribute - EGL_YUV_PLANE0_TEXTURE_UNIT_NV] = value;
   4526                }
   4527                else
   4528                {
   4529                    val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   4530                    return false;
   4531                }
   4532        }
   4533    }
   4534 
   4535    if (colorBufferType == EGL_RGB_BUFFER)
   4536    {
   4537        if (planeCount > 0)
   4538        {
   4539            val->setError(EGL_BAD_MATCH, "Plane count must be 0 for RGB buffer");
   4540            return false;
   4541        }
   4542        for (int i = 0; i < 3; i++)
   4543        {
   4544            if (plane[i] != -1)
   4545            {
   4546                val->setError(EGL_BAD_MATCH, "Planes cannot be specified");
   4547                return false;
   4548            }
   4549        }
   4550 
   4551        // Lookup the texture and ensure it is correct
   4552        gl::Texture *texture = context->getState().getTargetTexture(gl::TextureType::External);
   4553        if (texture == nullptr || texture->id().value == 0)
   4554        {
   4555            val->setError(EGL_BAD_ACCESS, "No external texture bound");
   4556            return false;
   4557        }
   4558    }
   4559    else
   4560    {
   4561        if (planeCount == -1)
   4562        {
   4563            planeCount = 2;
   4564        }
   4565        if (planeCount < 1 || planeCount > 3)
   4566        {
   4567            val->setError(EGL_BAD_MATCH, "Invalid YUV plane count");
   4568            return false;
   4569        }
   4570        for (EGLAttrib i = planeCount; i < 3; i++)
   4571        {
   4572            if (plane[i] != -1)
   4573            {
   4574                val->setError(EGL_BAD_MATCH, "Invalid plane specified");
   4575                return false;
   4576            }
   4577        }
   4578 
   4579        // Set to ensure no texture is referenced more than once
   4580        std::set<gl::Texture *> textureSet;
   4581        for (EGLAttrib i = 0; i < planeCount; i++)
   4582        {
   4583            if (plane[i] == -1)
   4584            {
   4585                val->setError(EGL_BAD_MATCH, "Not all planes specified");
   4586                return false;
   4587            }
   4588            if (plane[i] != EGL_NONE)
   4589            {
   4590                gl::Texture *texture = context->getState().getSamplerTexture(
   4591                    static_cast<unsigned int>(plane[i]), gl::TextureType::External);
   4592                if (texture == nullptr || texture->id().value == 0)
   4593                {
   4594                    val->setError(
   4595                        EGL_BAD_ACCESS,
   4596                        "No external texture bound at one or more specified texture units");
   4597                    return false;
   4598                }
   4599                if (textureSet.find(texture) != textureSet.end())
   4600                {
   4601                    val->setError(EGL_BAD_ACCESS, "Multiple planes bound to same texture object");
   4602                    return false;
   4603                }
   4604                textureSet.insert(texture);
   4605            }
   4606        }
   4607    }
   4608 
   4609    return true;
   4610 }
   4611 
   4612 bool ValidateCreateStreamProducerD3DTextureANGLE(const ValidationContext *val,
   4613                                                 const Display *display,
   4614                                                 const Stream *stream,
   4615                                                 const AttributeMap &attribs)
   4616 {
   4617    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4618 
   4619    const DisplayExtensions &displayExtensions = display->getExtensions();
   4620    if (!displayExtensions.streamProducerD3DTexture)
   4621    {
   4622        val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
   4623        return false;
   4624    }
   4625 
   4626    ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   4627 
   4628    attribs.initializeWithoutValidation();
   4629 
   4630    if (!attribs.isEmpty())
   4631    {
   4632        val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   4633        return false;
   4634    }
   4635 
   4636    if (stream->getState() != EGL_STREAM_STATE_CONNECTING_KHR)
   4637    {
   4638        val->setError(EGL_BAD_STATE_KHR, "Stream not in connecting state");
   4639        return false;
   4640    }
   4641 
   4642    switch (stream->getConsumerType())
   4643    {
   4644        case Stream::ConsumerType::GLTextureYUV:
   4645            if (stream->getPlaneCount() != 2)
   4646            {
   4647                val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
   4648                return false;
   4649            }
   4650            break;
   4651 
   4652        case Stream::ConsumerType::GLTextureRGB:
   4653            if (stream->getPlaneCount() != 1)
   4654            {
   4655                val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
   4656                return false;
   4657            }
   4658            break;
   4659 
   4660        default:
   4661            val->setError(EGL_BAD_MATCH, "Incompatible stream consumer type");
   4662            return false;
   4663    }
   4664 
   4665    return true;
   4666 }
   4667 
   4668 bool ValidateStreamPostD3DTextureANGLE(const ValidationContext *val,
   4669                                       const Display *display,
   4670                                       const Stream *stream,
   4671                                       const void *texture,
   4672                                       const AttributeMap &attribs)
   4673 {
   4674    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4675 
   4676    const DisplayExtensions &displayExtensions = display->getExtensions();
   4677    if (!displayExtensions.streamProducerD3DTexture)
   4678    {
   4679        val->setError(EGL_BAD_ACCESS, "Stream producer extension not active");
   4680        return false;
   4681    }
   4682 
   4683    ANGLE_VALIDATION_TRY(ValidateStream(val, display, stream));
   4684 
   4685    attribs.initializeWithoutValidation();
   4686 
   4687    for (auto &attributeIter : attribs)
   4688    {
   4689        EGLAttrib attribute = attributeIter.first;
   4690        EGLAttrib value     = attributeIter.second;
   4691 
   4692        switch (attribute)
   4693        {
   4694            case EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE:
   4695                if (value < 0)
   4696                {
   4697                    val->setError(EGL_BAD_PARAMETER, "Invalid subresource index");
   4698                    return false;
   4699                }
   4700                break;
   4701            case EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG:
   4702                if (value < 0)
   4703                {
   4704                    val->setError(EGL_BAD_PARAMETER, "Invalid plane offset");
   4705                    return false;
   4706                }
   4707                break;
   4708            default:
   4709                val->setError(EGL_BAD_ATTRIBUTE, "Invalid attribute");
   4710                return false;
   4711        }
   4712    }
   4713 
   4714    if (stream->getState() != EGL_STREAM_STATE_EMPTY_KHR &&
   4715        stream->getState() != EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR &&
   4716        stream->getState() != EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR)
   4717    {
   4718        val->setError(EGL_BAD_STATE_KHR, "Stream not fully configured");
   4719        return false;
   4720    }
   4721 
   4722    if (stream->getProducerType() != Stream::ProducerType::D3D11Texture)
   4723    {
   4724        val->setError(EGL_BAD_MATCH, "Incompatible stream producer");
   4725        return false;
   4726    }
   4727 
   4728    if (texture == nullptr)
   4729    {
   4730        val->setError(EGL_BAD_PARAMETER, "Texture is null");
   4731        return false;
   4732    }
   4733 
   4734    ANGLE_EGL_TRY_RETURN(val->eglThread, stream->validateD3D11Texture(texture, attribs),
   4735                         val->entryPoint, val->labeledObject, false);
   4736 
   4737    return true;
   4738 }
   4739 
   4740 bool ValidateSyncControlCHROMIUM(const ValidationContext *val,
   4741                                 const Display *display,
   4742                                 const Surface *eglSurface)
   4743 {
   4744    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4745    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
   4746 
   4747    const DisplayExtensions &displayExtensions = display->getExtensions();
   4748    if (!displayExtensions.syncControlCHROMIUM)
   4749    {
   4750        val->setError(EGL_BAD_ACCESS, "syncControlCHROMIUM extension not active");
   4751        return false;
   4752    }
   4753 
   4754    return true;
   4755 }
   4756 
   4757 bool ValidateSyncControlRateANGLE(const ValidationContext *val,
   4758                                  const Display *display,
   4759                                  const Surface *eglSurface)
   4760 {
   4761    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   4762    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
   4763 
   4764    const DisplayExtensions &displayExtensions = display->getExtensions();
   4765    if (!displayExtensions.syncControlRateANGLE)
   4766    {
   4767        val->setError(EGL_BAD_ACCESS, "syncControlRateANGLE extension not active");
   4768        return false;
   4769    }
   4770 
   4771    return true;
   4772 }
   4773 
   4774 bool ValidateGetMscRateANGLE(const ValidationContext *val,
   4775                             const Display *display,
   4776                             const Surface *eglSurface,
   4777                             const EGLint *numerator,
   4778                             const EGLint *denominator)
   4779 {
   4780    ANGLE_VALIDATION_TRY(ValidateSyncControlRateANGLE(val, display, eglSurface));
   4781 
   4782    if (numerator == nullptr)
   4783    {
   4784        val->setError(EGL_BAD_PARAMETER, "numerator is null");
   4785        return false;
   4786    }
   4787    if (denominator == nullptr)
   4788    {
   4789        val->setError(EGL_BAD_PARAMETER, "denominator is null");
   4790        return false;
   4791    }
   4792 
   4793    return true;
   4794 }
   4795 
   4796 bool ValidateGetSyncValuesCHROMIUM(const ValidationContext *val,
   4797                                   const Display *display,
   4798                                   const Surface *eglSurface,
   4799                                   const EGLuint64KHR *ust,
   4800                                   const EGLuint64KHR *msc,
   4801                                   const EGLuint64KHR *sbc)
   4802 {
   4803    ANGLE_VALIDATION_TRY(ValidateSyncControlCHROMIUM(val, display, eglSurface));
   4804 
   4805    if (ust == nullptr)
   4806    {
   4807        val->setError(EGL_BAD_PARAMETER, "ust is null");
   4808        return false;
   4809    }
   4810    if (msc == nullptr)
   4811    {
   4812        val->setError(EGL_BAD_PARAMETER, "msc is null");
   4813        return false;
   4814    }
   4815    if (sbc == nullptr)
   4816    {
   4817        val->setError(EGL_BAD_PARAMETER, "sbc is null");
   4818        return false;
   4819    }
   4820 
   4821    return true;
   4822 }
   4823 
   4824 bool ValidateDestroySurface(const ValidationContext *val,
   4825                            const Display *display,
   4826                            const Surface *surface)
   4827 {
   4828    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   4829    return true;
   4830 }
   4831 
   4832 bool ValidateDestroyContext(const ValidationContext *val,
   4833                            const Display *display,
   4834                            const gl::Context *glCtx)
   4835 {
   4836    ANGLE_VALIDATION_TRY(ValidateContext(val, display, glCtx));
   4837    return true;
   4838 }
   4839 
   4840 bool ValidateSwapBuffers(const ValidationContext *val,
   4841                         const Display *display,
   4842                         const Surface *eglSurface)
   4843 {
   4844    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
   4845 
   4846    if (display->isDeviceLost())
   4847    {
   4848        val->setError(EGL_CONTEXT_LOST);
   4849        return false;
   4850    }
   4851 
   4852    if (eglSurface->isLocked())
   4853    {
   4854        val->setError(EGL_BAD_ACCESS);
   4855        return false;
   4856    }
   4857 
   4858    if (eglSurface == EGL_NO_SURFACE || !val->eglThread->getContext() ||
   4859        val->eglThread->getCurrentDrawSurface() != eglSurface)
   4860    {
   4861        val->setError(EGL_BAD_SURFACE);
   4862        return false;
   4863    }
   4864 
   4865    return true;
   4866 }
   4867 
   4868 bool ValidateSwapBuffersWithDamageKHR(const ValidationContext *val,
   4869                                      const Display *display,
   4870                                      const Surface *surface,
   4871                                      const EGLint *rects,
   4872                                      EGLint n_rects)
   4873 {
   4874    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   4875 
   4876    if (!display->getExtensions().swapBuffersWithDamage)
   4877    {
   4878        // It is out of spec what happens when calling an extension function when the extension is
   4879        // not available. EGL_BAD_DISPLAY seems like a reasonable error.
   4880        val->setError(EGL_BAD_DISPLAY, "EGL_KHR_swap_buffers_with_damage is not available.");
   4881        return false;
   4882    }
   4883 
   4884    if (surface == EGL_NO_SURFACE)
   4885    {
   4886        val->setError(EGL_BAD_SURFACE, "Swap surface cannot be EGL_NO_SURFACE.");
   4887        return false;
   4888    }
   4889 
   4890    if (n_rects < 0)
   4891    {
   4892        val->setError(EGL_BAD_PARAMETER, "n_rects cannot be negative.");
   4893        return false;
   4894    }
   4895 
   4896    if (n_rects > 0 && rects == nullptr)
   4897    {
   4898        val->setError(EGL_BAD_PARAMETER, "n_rects cannot be greater than zero when rects is NULL.");
   4899        return false;
   4900    }
   4901 
   4902    if (surface->isLocked())
   4903    {
   4904        val->setError(EGL_BAD_ACCESS);
   4905        return false;
   4906    }
   4907 
   4908    // TODO(jmadill): Validate Surface is bound to the thread.
   4909 
   4910    return true;
   4911 }
   4912 
   4913 bool ValidateWaitNative(const ValidationContext *val, const EGLint engine)
   4914 {
   4915    if (val->eglThread->getDisplay() == nullptr)
   4916    {
   4917        // EGL spec says this about eglWaitNative -
   4918        //    eglWaitNative is ignored if there is no current EGL rendering context.
   4919        return true;
   4920    }
   4921 
   4922    ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
   4923 
   4924    if (engine != EGL_CORE_NATIVE_ENGINE)
   4925    {
   4926        val->setError(EGL_BAD_PARAMETER, "the 'engine' parameter has an unrecognized value");
   4927        return false;
   4928    }
   4929 
   4930    return true;
   4931 }
   4932 
   4933 bool ValidateCopyBuffers(const ValidationContext *val,
   4934                         const Display *display,
   4935                         const Surface *surface,
   4936                         EGLNativePixmapType target)
   4937 {
   4938    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   4939 
   4940    if (display->isDeviceLost())
   4941    {
   4942        val->setError(EGL_CONTEXT_LOST);
   4943        return false;
   4944    }
   4945 
   4946    return true;
   4947 }
   4948 
   4949 bool ValidateBindTexImage(const ValidationContext *val,
   4950                          const Display *display,
   4951                          const Surface *surface,
   4952                          const EGLint buffer)
   4953 {
   4954    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   4955 
   4956    if (buffer != EGL_BACK_BUFFER)
   4957    {
   4958        val->setError(EGL_BAD_PARAMETER);
   4959        return false;
   4960    }
   4961 
   4962    if (surface->getType() == EGL_WINDOW_BIT)
   4963    {
   4964        val->setError(EGL_BAD_SURFACE);
   4965        return false;
   4966    }
   4967 
   4968    if (surface->getBoundTexture())
   4969    {
   4970        val->setError(EGL_BAD_ACCESS);
   4971        return false;
   4972    }
   4973 
   4974    if (surface->getTextureFormat() == TextureFormat::NoTexture)
   4975    {
   4976        val->setError(EGL_BAD_MATCH);
   4977        return false;
   4978    }
   4979 
   4980    if (surface->isLocked())
   4981    {
   4982        val->setError(EGL_BAD_ACCESS);
   4983        return false;
   4984    }
   4985 
   4986    gl::Context *context = val->eglThread->getContext();
   4987    if (context && !context->isContextLost())
   4988    {
   4989        gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
   4990        gl::Texture *textureObject = context->getTextureByType(type);
   4991        ASSERT(textureObject != nullptr);
   4992 
   4993        if (textureObject->getImmutableFormat())
   4994        {
   4995            val->setError(EGL_BAD_MATCH);
   4996            return false;
   4997        }
   4998    }
   4999 
   5000    return true;
   5001 }
   5002 
   5003 bool ValidateReleaseTexImage(const ValidationContext *val,
   5004                             const Display *display,
   5005                             const Surface *surface,
   5006                             const EGLint buffer)
   5007 {
   5008    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5009 
   5010    if (buffer != EGL_BACK_BUFFER)
   5011    {
   5012        val->setError(EGL_BAD_PARAMETER);
   5013        return false;
   5014    }
   5015 
   5016    if (surface->getType() == EGL_WINDOW_BIT)
   5017    {
   5018        val->setError(EGL_BAD_SURFACE);
   5019        return false;
   5020    }
   5021 
   5022    if (surface->getTextureFormat() == TextureFormat::NoTexture)
   5023    {
   5024        val->setError(EGL_BAD_MATCH);
   5025        return false;
   5026    }
   5027 
   5028    return true;
   5029 }
   5030 
   5031 bool ValidateSwapInterval(const ValidationContext *val, const Display *display, EGLint interval)
   5032 {
   5033    const gl::Context *context = val->eglThread->getContext();
   5034    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   5035 
   5036    Surface *drawSurface = val->eglThread->getCurrentDrawSurface();
   5037    if (drawSurface == nullptr)
   5038    {
   5039        val->setError(EGL_BAD_SURFACE);
   5040        return false;
   5041    }
   5042 
   5043    return true;
   5044 }
   5045 
   5046 bool ValidateBindAPI(const ValidationContext *val, const EGLenum api)
   5047 {
   5048    switch (api)
   5049    {
   5050        case EGL_OPENGL_ES_API:
   5051        case EGL_OPENGL_API:
   5052            break;
   5053        case EGL_OPENVG_API:
   5054            val->setError(EGL_BAD_PARAMETER);
   5055            return false;  // Not supported by this implementation
   5056        default:
   5057            val->setError(EGL_BAD_PARAMETER);
   5058            return false;
   5059    }
   5060 
   5061    return true;
   5062 }
   5063 
   5064 bool ValidatePresentationTimeANDROID(const ValidationContext *val,
   5065                                     const Display *display,
   5066                                     const Surface *surface,
   5067                                     EGLnsecsANDROID time)
   5068 {
   5069    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5070 
   5071    if (!display->getExtensions().presentationTime)
   5072    {
   5073        // It is out of spec what happens when calling an extension function when the extension is
   5074        // not available. EGL_BAD_DISPLAY seems like a reasonable error.
   5075        val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_presentation_time is not available.");
   5076        return false;
   5077    }
   5078 
   5079    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5080 
   5081    return true;
   5082 }
   5083 
   5084 bool ValidateSetBlobCacheFuncsANDROID(const ValidationContext *val,
   5085                                      const Display *display,
   5086                                      EGLSetBlobFuncANDROID set,
   5087                                      EGLGetBlobFuncANDROID get)
   5088 {
   5089    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5090 
   5091    if (display->areBlobCacheFuncsSet())
   5092    {
   5093        val->setError(EGL_BAD_PARAMETER,
   5094                      "Blob cache functions can only be set once in the lifetime of a Display");
   5095        return false;
   5096    }
   5097 
   5098    if (set == nullptr || get == nullptr)
   5099    {
   5100        val->setError(EGL_BAD_PARAMETER, "Blob cache callbacks cannot be null.");
   5101        return false;
   5102    }
   5103 
   5104    return true;
   5105 }
   5106 
   5107 bool ValidateGetConfigAttrib(const ValidationContext *val,
   5108                             const Display *display,
   5109                             const Config *config,
   5110                             EGLint attribute,
   5111                             const EGLint *value)
   5112 {
   5113    ANGLE_VALIDATION_TRY(ValidateConfig(val, display, config));
   5114    ANGLE_TRY(ValidateConfigAttribute(val, display, static_cast<EGLAttrib>(attribute)));
   5115    return true;
   5116 }
   5117 
   5118 bool ValidateChooseConfig(const ValidationContext *val,
   5119                          const Display *display,
   5120                          const AttributeMap &attribs,
   5121                          const EGLConfig *configs,
   5122                          EGLint configSize,
   5123                          const EGLint *numConfig)
   5124 {
   5125    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5126    ANGLE_VALIDATION_TRY(ValidateConfigAttributes(val, display, attribs));
   5127 
   5128    if (numConfig == nullptr)
   5129    {
   5130        val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
   5131        return false;
   5132    }
   5133 
   5134    return true;
   5135 }
   5136 
   5137 bool ValidateGetConfigs(const ValidationContext *val,
   5138                        const Display *display,
   5139                        const EGLConfig *configs,
   5140                        EGLint configSize,
   5141                        const EGLint *numConfig)
   5142 {
   5143    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5144 
   5145    if (numConfig == nullptr)
   5146    {
   5147        val->setError(EGL_BAD_PARAMETER, "num_config cannot be null.");
   5148        return false;
   5149    }
   5150 
   5151    return true;
   5152 }
   5153 
   5154 bool ValidateGetPlatformDisplay(const ValidationContext *val,
   5155                                EGLenum platform,
   5156                                const void *native_display,
   5157                                const AttributeMap &attribMap)
   5158 {
   5159    return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
   5160 }
   5161 
   5162 bool ValidateGetPlatformDisplayEXT(const ValidationContext *val,
   5163                                   EGLenum platform,
   5164                                   const void *native_display,
   5165                                   const AttributeMap &attribMap)
   5166 {
   5167    return ValidateGetPlatformDisplayCommon(val, platform, native_display, attribMap);
   5168 }
   5169 
   5170 bool ValidateCreatePlatformWindowSurfaceEXT(const ValidationContext *val,
   5171                                            const Display *display,
   5172                                            const Config *configuration,
   5173                                            const void *nativeWindow,
   5174                                            const AttributeMap &attributes)
   5175 {
   5176    if (!Display::GetClientExtensions().platformBase)
   5177    {
   5178        val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
   5179        return false;
   5180    }
   5181 
   5182    const void *actualNativeWindow = display->getImplementation()->isX11()
   5183                                         ? *reinterpret_cast<const void *const *>(nativeWindow)
   5184                                         : nativeWindow;
   5185 
   5186    return ValidateCreatePlatformWindowSurface(val, display, configuration, actualNativeWindow,
   5187                                               attributes);
   5188 }
   5189 
   5190 bool ValidateCreatePlatformPixmapSurfaceEXT(const ValidationContext *val,
   5191                                            const Display *display,
   5192                                            const Config *configuration,
   5193                                            const void *nativePixmap,
   5194                                            const AttributeMap &attributes)
   5195 {
   5196    if (!Display::GetClientExtensions().platformBase)
   5197    {
   5198        val->setError(EGL_BAD_ACCESS, "EGL_EXT_platform_base not supported");
   5199        return false;
   5200    }
   5201 
   5202    ANGLE_VALIDATION_TRY(ValidateConfig(val, display, configuration));
   5203 
   5204    val->setError(EGL_BAD_DISPLAY, "ValidateCreatePlatformPixmapSurfaceEXT unimplemented.");
   5205    return false;
   5206 }
   5207 
   5208 bool ValidateProgramCacheGetAttribANGLE(const ValidationContext *val,
   5209                                        const Display *display,
   5210                                        EGLenum attrib)
   5211 {
   5212    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5213 
   5214    if (!display->getExtensions().programCacheControlANGLE)
   5215    {
   5216        val->setError(EGL_BAD_ACCESS, "Extension not supported");
   5217        return false;
   5218    }
   5219 
   5220    switch (attrib)
   5221    {
   5222        case EGL_PROGRAM_CACHE_KEY_LENGTH_ANGLE:
   5223        case EGL_PROGRAM_CACHE_SIZE_ANGLE:
   5224            break;
   5225 
   5226        default:
   5227            val->setError(EGL_BAD_PARAMETER, "Invalid program cache attribute.");
   5228            return false;
   5229    }
   5230 
   5231    return true;
   5232 }
   5233 
   5234 bool ValidateProgramCacheQueryANGLE(const ValidationContext *val,
   5235                                    const Display *display,
   5236                                    EGLint index,
   5237                                    const void *key,
   5238                                    const EGLint *keysize,
   5239                                    const void *binary,
   5240                                    const EGLint *binarysize)
   5241 {
   5242    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5243 
   5244    if (!display->getExtensions().programCacheControlANGLE)
   5245    {
   5246        val->setError(EGL_BAD_ACCESS, "Extension not supported");
   5247        return false;
   5248    }
   5249 
   5250    if (index < 0 || index >= display->programCacheGetAttrib(EGL_PROGRAM_CACHE_SIZE_ANGLE))
   5251    {
   5252        val->setError(EGL_BAD_PARAMETER, "Program index out of range.");
   5253        return false;
   5254    }
   5255 
   5256    if (keysize == nullptr || binarysize == nullptr)
   5257    {
   5258        val->setError(EGL_BAD_PARAMETER, "keysize and binarysize must always be valid pointers.");
   5259        return false;
   5260    }
   5261 
   5262    if (binary && *keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
   5263    {
   5264        val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
   5265        return false;
   5266    }
   5267 
   5268    if ((key == nullptr) != (binary == nullptr))
   5269    {
   5270        val->setError(EGL_BAD_PARAMETER, "key and binary must both be null or both non-null.");
   5271        return false;
   5272    }
   5273 
   5274    return true;
   5275 }
   5276 
   5277 bool ValidateProgramCachePopulateANGLE(const ValidationContext *val,
   5278                                       const Display *display,
   5279                                       const void *key,
   5280                                       EGLint keysize,
   5281                                       const void *binary,
   5282                                       EGLint binarysize)
   5283 {
   5284    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5285 
   5286    if (!display->getExtensions().programCacheControlANGLE)
   5287    {
   5288        val->setError(EGL_BAD_ACCESS, "Extension not supported");
   5289        return false;
   5290    }
   5291 
   5292    if (keysize != static_cast<EGLint>(egl::BlobCache::kKeyLength))
   5293    {
   5294        val->setError(EGL_BAD_PARAMETER, "Invalid program key size.");
   5295        return false;
   5296    }
   5297 
   5298    if (key == nullptr || binary == nullptr)
   5299    {
   5300        val->setError(EGL_BAD_PARAMETER, "null pointer in arguments.");
   5301        return false;
   5302    }
   5303 
   5304    // Upper bound for binarysize is arbitrary.
   5305    if (binarysize <= 0 || binarysize > egl::kProgramCacheSizeAbsoluteMax)
   5306    {
   5307        val->setError(EGL_BAD_PARAMETER, "binarysize out of valid range.");
   5308        return false;
   5309    }
   5310 
   5311    return true;
   5312 }
   5313 
   5314 bool ValidateProgramCacheResizeANGLE(const ValidationContext *val,
   5315                                     const Display *display,
   5316                                     EGLint limit,
   5317                                     EGLint mode)
   5318 {
   5319    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5320 
   5321    if (!display->getExtensions().programCacheControlANGLE)
   5322    {
   5323        val->setError(EGL_BAD_ACCESS, "Extension not supported");
   5324        return false;
   5325    }
   5326 
   5327    if (limit < 0)
   5328    {
   5329        val->setError(EGL_BAD_PARAMETER, "limit must be non-negative.");
   5330        return false;
   5331    }
   5332 
   5333    switch (mode)
   5334    {
   5335        case EGL_PROGRAM_CACHE_RESIZE_ANGLE:
   5336        case EGL_PROGRAM_CACHE_TRIM_ANGLE:
   5337            break;
   5338 
   5339        default:
   5340            val->setError(EGL_BAD_PARAMETER, "Invalid cache resize mode.");
   5341            return false;
   5342    }
   5343 
   5344    return true;
   5345 }
   5346 
   5347 bool ValidateSurfaceAttrib(const ValidationContext *val,
   5348                           const Display *display,
   5349                           const Surface *surface,
   5350                           EGLint attribute,
   5351                           EGLint value)
   5352 {
   5353    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5354    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5355 
   5356    if (surface == EGL_NO_SURFACE)
   5357    {
   5358        val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
   5359        return false;
   5360    }
   5361 
   5362    switch (attribute)
   5363    {
   5364        case EGL_MIPMAP_LEVEL:
   5365            break;
   5366 
   5367        case EGL_MULTISAMPLE_RESOLVE:
   5368            switch (value)
   5369            {
   5370                case EGL_MULTISAMPLE_RESOLVE_DEFAULT:
   5371                    break;
   5372 
   5373                case EGL_MULTISAMPLE_RESOLVE_BOX:
   5374                    if ((surface->getConfig()->surfaceType & EGL_MULTISAMPLE_RESOLVE_BOX_BIT) == 0)
   5375                    {
   5376                        val->setError(EGL_BAD_MATCH,
   5377                                      "Surface does not support EGL_MULTISAMPLE_RESOLVE_BOX.");
   5378                        return false;
   5379                    }
   5380                    break;
   5381 
   5382                default:
   5383                    val->setError(EGL_BAD_ATTRIBUTE, "Invalid multisample resolve type.");
   5384                    return false;
   5385            }
   5386            break;
   5387 
   5388        case EGL_SWAP_BEHAVIOR:
   5389            switch (value)
   5390            {
   5391                case EGL_BUFFER_PRESERVED:
   5392                    if ((surface->getConfig()->surfaceType & EGL_SWAP_BEHAVIOR_PRESERVED_BIT) == 0)
   5393                    {
   5394                        val->setError(EGL_BAD_MATCH,
   5395                                      "Surface does not support EGL_SWAP_BEHAVIOR_PRESERVED.");
   5396                        return false;
   5397                    }
   5398                    break;
   5399 
   5400                case EGL_BUFFER_DESTROYED:
   5401                    break;
   5402 
   5403                default:
   5404                    val->setError(EGL_BAD_ATTRIBUTE, "Invalid swap behaviour.");
   5405                    return false;
   5406            }
   5407            break;
   5408 
   5409        case EGL_WIDTH:
   5410        case EGL_HEIGHT:
   5411            if (!display->getExtensions().windowFixedSize)
   5412            {
   5413                val->setError(EGL_BAD_ATTRIBUTE,
   5414                              "EGL_WIDTH or EGL_HEIGHT cannot be set without "
   5415                              "EGL_ANGLE_window_fixed_size support.");
   5416                return false;
   5417            }
   5418            if (!surface->isFixedSize())
   5419            {
   5420                val->setError(EGL_BAD_MATCH,
   5421                              "EGL_WIDTH or EGL_HEIGHT cannot be set without "
   5422                              "EGL_FIXED_SIZE_ANGLE being enabled on the surface.");
   5423                return false;
   5424            }
   5425            break;
   5426 
   5427        case EGL_TIMESTAMPS_ANDROID:
   5428            if (!display->getExtensions().getFrameTimestamps &&
   5429                !display->getExtensions().timestampSurfaceAttributeANGLE)
   5430            {
   5431                val->setError(EGL_BAD_ATTRIBUTE,
   5432                              "EGL_TIMESTAMPS_ANDROID cannot be used without "
   5433                              "EGL_ANDROID_get_frame_timestamps support.");
   5434                return false;
   5435            }
   5436            switch (value)
   5437            {
   5438                case EGL_TRUE:
   5439                case EGL_FALSE:
   5440                    break;
   5441 
   5442                default:
   5443                    val->setError(EGL_BAD_ATTRIBUTE, "Invalid value.");
   5444                    return false;
   5445            }
   5446            break;
   5447 
   5448        case EGL_FRONT_BUFFER_AUTO_REFRESH_ANDROID:
   5449            ASSERT(value == EGL_TRUE || value == EGL_FALSE);
   5450            break;
   5451 
   5452        case EGL_RENDER_BUFFER:
   5453            if (value != EGL_BACK_BUFFER && value != EGL_SINGLE_BUFFER)
   5454            {
   5455                val->setError(EGL_BAD_ATTRIBUTE,
   5456                              "EGL_RENDER_BUFFER must be EGL_BACK_BUFFER or EGL_SINGLE_BUFFER.");
   5457                return false;
   5458            }
   5459 
   5460            if (value == EGL_SINGLE_BUFFER)
   5461            {
   5462                if (!display->getExtensions().mutableRenderBufferKHR)
   5463                {
   5464                    val->setError(
   5465                        EGL_BAD_ATTRIBUTE,
   5466                        "Attribute EGL_RENDER_BUFFER requires EGL_KHR_mutable_render_buffer.");
   5467                    return false;
   5468                }
   5469 
   5470                if ((surface->getConfig()->surfaceType & EGL_MUTABLE_RENDER_BUFFER_BIT_KHR) == 0)
   5471                {
   5472                    val->setError(EGL_BAD_MATCH,
   5473                                  "EGL_RENDER_BUFFER requires the surface type bit "
   5474                                  "EGL_MUTABLE_RENDER_BUFFER_BIT_KHR.");
   5475                    return false;
   5476                }
   5477            }
   5478            break;
   5479 
   5480        default:
   5481            val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
   5482            return false;
   5483    }
   5484 
   5485    return true;
   5486 }
   5487 
   5488 bool ValidateQuerySurface(const ValidationContext *val,
   5489                          const Display *display,
   5490                          const Surface *surface,
   5491                          EGLint attribute,
   5492                          const EGLint *value)
   5493 {
   5494    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5495    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5496 
   5497    if (surface == EGL_NO_SURFACE)
   5498    {
   5499        val->setError(EGL_BAD_SURFACE, "Surface cannot be EGL_NO_SURFACE.");
   5500        return false;
   5501    }
   5502 
   5503    switch (attribute)
   5504    {
   5505        case EGL_GL_COLORSPACE:
   5506        case EGL_VG_ALPHA_FORMAT:
   5507        case EGL_VG_COLORSPACE:
   5508        case EGL_CONFIG_ID:
   5509        case EGL_HEIGHT:
   5510        case EGL_HORIZONTAL_RESOLUTION:
   5511        case EGL_LARGEST_PBUFFER:
   5512        case EGL_MIPMAP_TEXTURE:
   5513        case EGL_MIPMAP_LEVEL:
   5514        case EGL_MULTISAMPLE_RESOLVE:
   5515        case EGL_PIXEL_ASPECT_RATIO:
   5516        case EGL_RENDER_BUFFER:
   5517        case EGL_SWAP_BEHAVIOR:
   5518        case EGL_TEXTURE_FORMAT:
   5519        case EGL_TEXTURE_TARGET:
   5520        case EGL_VERTICAL_RESOLUTION:
   5521        case EGL_WIDTH:
   5522            break;
   5523 
   5524        case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
   5525            if (!display->getExtensions().postSubBuffer)
   5526            {
   5527                val->setError(EGL_BAD_ATTRIBUTE,
   5528                              "EGL_POST_SUB_BUFFER_SUPPORTED_NV cannot be used "
   5529                              "without EGL_ANGLE_surface_orientation support.");
   5530                return false;
   5531            }
   5532            break;
   5533 
   5534        case EGL_FIXED_SIZE_ANGLE:
   5535            if (!display->getExtensions().windowFixedSize)
   5536            {
   5537                val->setError(EGL_BAD_ATTRIBUTE,
   5538                              "EGL_FIXED_SIZE_ANGLE cannot be used without "
   5539                              "EGL_ANGLE_window_fixed_size support.");
   5540                return false;
   5541            }
   5542            break;
   5543 
   5544        case EGL_SURFACE_ORIENTATION_ANGLE:
   5545            if (!display->getExtensions().surfaceOrientation)
   5546            {
   5547                val->setError(EGL_BAD_ATTRIBUTE,
   5548                              "EGL_SURFACE_ORIENTATION_ANGLE cannot be "
   5549                              "queried without "
   5550                              "EGL_ANGLE_surface_orientation support.");
   5551                return false;
   5552            }
   5553            break;
   5554 
   5555        case EGL_DIRECT_COMPOSITION_ANGLE:
   5556            if (!display->getExtensions().directComposition)
   5557            {
   5558                val->setError(EGL_BAD_ATTRIBUTE,
   5559                              "EGL_DIRECT_COMPOSITION_ANGLE cannot be "
   5560                              "used without "
   5561                              "EGL_ANGLE_direct_composition support.");
   5562                return false;
   5563            }
   5564            break;
   5565 
   5566        case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   5567            if (!display->getExtensions().robustResourceInitializationANGLE)
   5568            {
   5569                val->setError(EGL_BAD_ATTRIBUTE,
   5570                              "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
   5571                              "used without EGL_ANGLE_robust_resource_initialization "
   5572                              "support.");
   5573                return false;
   5574            }
   5575            break;
   5576 
   5577        case EGL_TIMESTAMPS_ANDROID:
   5578            if (!display->getExtensions().getFrameTimestamps &&
   5579                !display->getExtensions().timestampSurfaceAttributeANGLE)
   5580            {
   5581                val->setError(EGL_BAD_ATTRIBUTE,
   5582                              "EGL_TIMESTAMPS_ANDROID cannot be used without "
   5583                              "EGL_ANDROID_get_frame_timestamps support.");
   5584                return false;
   5585            }
   5586            break;
   5587 
   5588        case EGL_BUFFER_AGE_EXT:
   5589        {
   5590            if (!display->getExtensions().bufferAgeEXT)
   5591            {
   5592                val->setError(EGL_BAD_ATTRIBUTE,
   5593                              "EGL_BUFFER_AGE_EXT cannot be used without "
   5594                              "EGL_EXT_buffer_age support.");
   5595                return false;
   5596            }
   5597            gl::Context *context = val->eglThread->getContext();
   5598            if ((context == nullptr) || (context->getCurrentDrawSurface() != surface))
   5599            {
   5600                val->setError(EGL_BAD_SURFACE,
   5601                              "The surface must be current to the current context "
   5602                              "in order to query buffer age per extension "
   5603                              "EGL_EXT_buffer_age.");
   5604                return false;
   5605            }
   5606        }
   5607        break;
   5608 
   5609        case EGL_BITMAP_PITCH_KHR:
   5610        case EGL_BITMAP_ORIGIN_KHR:
   5611        case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
   5612        case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
   5613        case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
   5614        case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
   5615        case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
   5616        case EGL_BITMAP_PIXEL_SIZE_KHR:
   5617            if (!display->getExtensions().lockSurface3KHR)
   5618            {
   5619                val->setError(EGL_BAD_ATTRIBUTE, "EGL_KHR_lock_surface3 is not supported.");
   5620                return false;
   5621            }
   5622            break;
   5623 
   5624        case EGL_PROTECTED_CONTENT_EXT:
   5625            if (!display->getExtensions().protectedContentEXT)
   5626            {
   5627                val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_protected_content not supported");
   5628                return false;
   5629            }
   5630            break;
   5631 
   5632        default:
   5633            val->setError(EGL_BAD_ATTRIBUTE, "Invalid surface attribute: 0x%04X", attribute);
   5634            return false;
   5635    }
   5636 
   5637    return true;
   5638 }
   5639 
   5640 bool ValidateQueryContext(const ValidationContext *val,
   5641                          const Display *display,
   5642                          const gl::Context *context,
   5643                          EGLint attribute,
   5644                          const EGLint *value)
   5645 {
   5646    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   5647 
   5648    switch (attribute)
   5649    {
   5650        case EGL_CONFIG_ID:
   5651        case EGL_CONTEXT_CLIENT_TYPE:
   5652        case EGL_CONTEXT_CLIENT_VERSION:
   5653        case EGL_RENDER_BUFFER:
   5654            break;
   5655 
   5656        case EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE:
   5657            if (!display->getExtensions().robustResourceInitializationANGLE)
   5658            {
   5659                val->setError(EGL_BAD_ATTRIBUTE,
   5660                              "EGL_ROBUST_RESOURCE_INITIALIZATION_ANGLE cannot be "
   5661                              "used without EGL_ANGLE_robust_resource_initialization "
   5662                              "support.");
   5663                return false;
   5664            }
   5665            break;
   5666 
   5667        case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
   5668            if (!display->getExtensions().contextPriority)
   5669            {
   5670                val->setError(EGL_BAD_ATTRIBUTE,
   5671                              "Attribute EGL_CONTEXT_PRIORITY_LEVEL_IMG requires "
   5672                              "extension EGL_IMG_context_priority.");
   5673                return false;
   5674            }
   5675            break;
   5676 
   5677        case EGL_PROTECTED_CONTENT_EXT:
   5678            if (!display->getExtensions().protectedContentEXT)
   5679            {
   5680                val->setError(EGL_BAD_ATTRIBUTE, "EGL_EXT_protected_content not supported");
   5681                return false;
   5682            }
   5683            break;
   5684 
   5685        default:
   5686            val->setError(EGL_BAD_ATTRIBUTE, "Invalid context attribute: 0x%04X", attribute);
   5687            return false;
   5688    }
   5689 
   5690    return true;
   5691 }
   5692 
   5693 bool ValidateDebugMessageControlKHR(const ValidationContext *val,
   5694                                    EGLDEBUGPROCKHR callback,
   5695                                    const AttributeMap &attribs)
   5696 {
   5697    const ClientExtensions &clientExtensions = Display::GetClientExtensions();
   5698    if (!clientExtensions.debug)
   5699    {
   5700        val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
   5701        return false;
   5702    }
   5703 
   5704    attribs.initializeWithoutValidation();
   5705 
   5706    for (const auto &attrib : attribs)
   5707    {
   5708        switch (attrib.first)
   5709        {
   5710            case EGL_DEBUG_MSG_CRITICAL_KHR:
   5711            case EGL_DEBUG_MSG_ERROR_KHR:
   5712            case EGL_DEBUG_MSG_WARN_KHR:
   5713            case EGL_DEBUG_MSG_INFO_KHR:
   5714                if (attrib.second != EGL_TRUE && attrib.second != EGL_FALSE)
   5715                {
   5716                    val->setError(EGL_BAD_ATTRIBUTE,
   5717                                  "message controls must be EGL_TRUE or EGL_FALSE.");
   5718                    return false;
   5719                }
   5720                break;
   5721        }
   5722    }
   5723 
   5724    return true;
   5725 }
   5726 
   5727 bool ValidateQueryDebugKHR(const ValidationContext *val, EGLint attribute, const EGLAttrib *value)
   5728 {
   5729    const ClientExtensions &clientExtensions = Display::GetClientExtensions();
   5730    if (!clientExtensions.debug)
   5731    {
   5732        val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
   5733        return false;
   5734    }
   5735 
   5736    switch (attribute)
   5737    {
   5738        case EGL_DEBUG_MSG_CRITICAL_KHR:
   5739        case EGL_DEBUG_MSG_ERROR_KHR:
   5740        case EGL_DEBUG_MSG_WARN_KHR:
   5741        case EGL_DEBUG_MSG_INFO_KHR:
   5742        case EGL_DEBUG_CALLBACK_KHR:
   5743            break;
   5744 
   5745        default:
   5746            val->setError(EGL_BAD_ATTRIBUTE, "Unknown attribute: 0x%04X", attribute);
   5747            return false;
   5748    }
   5749 
   5750    return true;
   5751 }
   5752 
   5753 bool ValidateLabelObjectKHR(const ValidationContext *val,
   5754                            const Display *display,
   5755                            ObjectType objectType,
   5756                            EGLObjectKHR object,
   5757                            EGLLabelKHR label)
   5758 {
   5759    const ClientExtensions &clientExtensions = Display::GetClientExtensions();
   5760    if (!clientExtensions.debug)
   5761    {
   5762        val->setError(EGL_BAD_ACCESS, "EGL_KHR_debug extension is not available.");
   5763        return false;
   5764    }
   5765 
   5766    LabeledObject *labeledObject = nullptr;
   5767    ANGLE_VALIDATION_TRY(ValidateLabeledObject(val, display, objectType, object, &labeledObject));
   5768 
   5769    return true;
   5770 }
   5771 
   5772 bool ValidateGetCompositorTimingSupportedANDROID(const ValidationContext *val,
   5773                                                 const Display *display,
   5774                                                 const Surface *surface,
   5775                                                 CompositorTiming name)
   5776 {
   5777    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5778 
   5779    if (!display->getExtensions().getFrameTimestamps)
   5780    {
   5781        val->setError(EGL_BAD_DISPLAY,
   5782                      "EGL_ANDROID_get_frame_timestamps extension is not available.");
   5783        return false;
   5784    }
   5785 
   5786    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5787 
   5788    if (!ValidCompositorTimingName(name))
   5789    {
   5790        val->setError(EGL_BAD_PARAMETER, "invalid timing name.");
   5791        return false;
   5792    }
   5793 
   5794    return true;
   5795 }
   5796 
   5797 bool ValidateGetCompositorTimingANDROID(const ValidationContext *val,
   5798                                        const Display *display,
   5799                                        const Surface *surface,
   5800                                        EGLint numTimestamps,
   5801                                        const EGLint *names,
   5802                                        const EGLnsecsANDROID *values)
   5803 {
   5804    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5805 
   5806    if (!display->getExtensions().getFrameTimestamps)
   5807    {
   5808        val->setError(EGL_BAD_DISPLAY,
   5809                      "EGL_ANDROID_get_frame_timestamps extension is not available.");
   5810        return false;
   5811    }
   5812 
   5813    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5814 
   5815    if (names == nullptr && numTimestamps > 0)
   5816    {
   5817        val->setError(EGL_BAD_PARAMETER, "names is NULL.");
   5818        return false;
   5819    }
   5820 
   5821    if (values == nullptr && numTimestamps > 0)
   5822    {
   5823        val->setError(EGL_BAD_PARAMETER, "values is NULL.");
   5824        return false;
   5825    }
   5826 
   5827    if (numTimestamps < 0)
   5828    {
   5829        val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
   5830        return false;
   5831    }
   5832 
   5833    for (EGLint i = 0; i < numTimestamps; i++)
   5834    {
   5835        CompositorTiming name = FromEGLenum<CompositorTiming>(names[i]);
   5836 
   5837        if (!ValidCompositorTimingName(name))
   5838        {
   5839            val->setError(EGL_BAD_PARAMETER, "invalid compositor timing.");
   5840            return false;
   5841        }
   5842 
   5843        if (!surface->getSupportedCompositorTimings().test(name))
   5844        {
   5845            val->setError(EGL_BAD_PARAMETER, "compositor timing not supported by surface.");
   5846            return false;
   5847        }
   5848    }
   5849 
   5850    return true;
   5851 }
   5852 
   5853 bool ValidateGetNextFrameIdANDROID(const ValidationContext *val,
   5854                                   const Display *display,
   5855                                   const Surface *surface,
   5856                                   const EGLuint64KHR *frameId)
   5857 {
   5858    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5859 
   5860    if (!display->getExtensions().getFrameTimestamps)
   5861    {
   5862        val->setError(EGL_BAD_DISPLAY,
   5863                      "EGL_ANDROID_get_frame_timestamps extension is not available.");
   5864        return false;
   5865    }
   5866 
   5867    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5868 
   5869    if (frameId == nullptr)
   5870    {
   5871        val->setError(EGL_BAD_PARAMETER, "frameId is NULL.");
   5872        return false;
   5873    }
   5874 
   5875    return true;
   5876 }
   5877 
   5878 bool ValidateGetFrameTimestampSupportedANDROID(const ValidationContext *val,
   5879                                               const Display *display,
   5880                                               const Surface *surface,
   5881                                               Timestamp timestamp)
   5882 {
   5883    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5884 
   5885    if (!display->getExtensions().getFrameTimestamps)
   5886    {
   5887        val->setError(EGL_BAD_DISPLAY,
   5888                      "EGL_ANDROID_get_frame_timestamps extension is not available.");
   5889        return false;
   5890    }
   5891 
   5892    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5893 
   5894    if (!ValidTimestampType(timestamp))
   5895    {
   5896        val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
   5897        return false;
   5898    }
   5899 
   5900    return true;
   5901 }
   5902 
   5903 bool ValidateGetFrameTimestampsANDROID(const ValidationContext *val,
   5904                                       const Display *display,
   5905                                       const Surface *surface,
   5906                                       EGLuint64KHR frameId,
   5907                                       EGLint numTimestamps,
   5908                                       const EGLint *timestamps,
   5909                                       const EGLnsecsANDROID *values)
   5910 {
   5911    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5912 
   5913    if (!display->getExtensions().getFrameTimestamps)
   5914    {
   5915        val->setError(EGL_BAD_DISPLAY,
   5916                      "EGL_ANDROID_get_frame_timestamps extension is not available.");
   5917        return false;
   5918    }
   5919 
   5920    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   5921 
   5922    if (!surface->isTimestampsEnabled())
   5923    {
   5924        val->setError(EGL_BAD_SURFACE, "timestamp collection is not enabled for this surface.");
   5925        return false;
   5926    }
   5927 
   5928    if (timestamps == nullptr && numTimestamps > 0)
   5929    {
   5930        val->setError(EGL_BAD_PARAMETER, "timestamps is NULL.");
   5931        return false;
   5932    }
   5933 
   5934    if (values == nullptr && numTimestamps > 0)
   5935    {
   5936        val->setError(EGL_BAD_PARAMETER, "values is NULL.");
   5937        return false;
   5938    }
   5939 
   5940    if (numTimestamps < 0)
   5941    {
   5942        val->setError(EGL_BAD_PARAMETER, "numTimestamps must be at least 0.");
   5943        return false;
   5944    }
   5945 
   5946    for (EGLint i = 0; i < numTimestamps; i++)
   5947    {
   5948        Timestamp timestamp = FromEGLenum<Timestamp>(timestamps[i]);
   5949 
   5950        if (!ValidTimestampType(timestamp))
   5951        {
   5952            val->setError(EGL_BAD_PARAMETER, "invalid timestamp type.");
   5953            return false;
   5954        }
   5955 
   5956        if (!surface->getSupportedTimestamps().test(timestamp))
   5957        {
   5958            val->setError(EGL_BAD_PARAMETER, "timestamp not supported by surface.");
   5959            return false;
   5960        }
   5961    }
   5962 
   5963    return true;
   5964 }
   5965 
   5966 bool ValidateQueryStringiANGLE(const ValidationContext *val,
   5967                               const Display *display,
   5968                               EGLint name,
   5969                               EGLint index)
   5970 {
   5971    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   5972 
   5973    if (!Display::GetClientExtensions().featureControlANGLE)
   5974    {
   5975        val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_feature_control extension is not available.");
   5976        return false;
   5977    }
   5978 
   5979    if (index < 0)
   5980    {
   5981        val->setError(EGL_BAD_PARAMETER, "index is negative.");
   5982        return false;
   5983    }
   5984 
   5985    switch (name)
   5986    {
   5987        case EGL_FEATURE_NAME_ANGLE:
   5988        case EGL_FEATURE_CATEGORY_ANGLE:
   5989        case EGL_FEATURE_DESCRIPTION_ANGLE:
   5990        case EGL_FEATURE_BUG_ANGLE:
   5991        case EGL_FEATURE_STATUS_ANGLE:
   5992        case EGL_FEATURE_CONDITION_ANGLE:
   5993            break;
   5994        default:
   5995            val->setError(EGL_BAD_PARAMETER, "name is not valid.");
   5996            return false;
   5997    }
   5998 
   5999    if (static_cast<size_t>(index) >= display->getFeatures().size())
   6000    {
   6001        val->setError(EGL_BAD_PARAMETER, "index is too big.");
   6002        return false;
   6003    }
   6004 
   6005    return true;
   6006 }
   6007 
   6008 bool ValidateQueryDisplayAttribEXT(const ValidationContext *val,
   6009                                   const Display *display,
   6010                                   const EGLint attribute,
   6011                                   const EGLAttrib *value)
   6012 {
   6013    ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
   6014    return true;
   6015 }
   6016 
   6017 bool ValidateQueryDisplayAttribANGLE(const ValidationContext *val,
   6018                                     const Display *display,
   6019                                     const EGLint attribute,
   6020                                     const EGLAttrib *value)
   6021 {
   6022    ANGLE_VALIDATION_TRY(ValidateQueryDisplayAttribBase(val, display, attribute));
   6023    return true;
   6024 }
   6025 
   6026 bool ValidateGetNativeClientBufferANDROID(const ValidationContext *val,
   6027                                          const AHardwareBuffer *buffer)
   6028 {
   6029    // No extension check is done because no display is passed to eglGetNativeClientBufferANDROID
   6030    // despite it being a display extension.  No display is needed for the implementation though.
   6031    if (buffer == nullptr)
   6032    {
   6033        val->setError(EGL_BAD_PARAMETER, "NULL buffer.");
   6034        return false;
   6035    }
   6036 
   6037    return true;
   6038 }
   6039 
   6040 bool ValidateCreateNativeClientBufferANDROID(const ValidationContext *val,
   6041                                             const egl::AttributeMap &attribMap)
   6042 {
   6043    attribMap.initializeWithoutValidation();
   6044 
   6045    if (attribMap.isEmpty() || attribMap.begin()->second == EGL_NONE)
   6046    {
   6047        val->setError(EGL_BAD_PARAMETER, "invalid attribute list.");
   6048        return false;
   6049    }
   6050 
   6051    int width     = attribMap.getAsInt(EGL_WIDTH, 0);
   6052    int height    = attribMap.getAsInt(EGL_HEIGHT, 0);
   6053    int redSize   = attribMap.getAsInt(EGL_RED_SIZE, 0);
   6054    int greenSize = attribMap.getAsInt(EGL_GREEN_SIZE, 0);
   6055    int blueSize  = attribMap.getAsInt(EGL_BLUE_SIZE, 0);
   6056    int alphaSize = attribMap.getAsInt(EGL_ALPHA_SIZE, 0);
   6057    int usage     = attribMap.getAsInt(EGL_NATIVE_BUFFER_USAGE_ANDROID, 0);
   6058 
   6059    for (AttributeMap::const_iterator attributeIter = attribMap.begin();
   6060         attributeIter != attribMap.end(); attributeIter++)
   6061    {
   6062        EGLAttrib attribute = attributeIter->first;
   6063        switch (attribute)
   6064        {
   6065            case EGL_WIDTH:
   6066            case EGL_HEIGHT:
   6067                // Validation done after the switch statement
   6068                break;
   6069            case EGL_RED_SIZE:
   6070            case EGL_GREEN_SIZE:
   6071            case EGL_BLUE_SIZE:
   6072            case EGL_ALPHA_SIZE:
   6073                if (redSize < 0 || greenSize < 0 || blueSize < 0 || alphaSize < 0)
   6074                {
   6075                    val->setError(EGL_BAD_PARAMETER, "incorrect channel size requested");
   6076                    return false;
   6077                }
   6078                break;
   6079            case EGL_NATIVE_BUFFER_USAGE_ANDROID:
   6080                // The buffer must be used for either a texture or a renderbuffer.
   6081                if ((usage & ~(EGL_NATIVE_BUFFER_USAGE_PROTECTED_BIT_ANDROID |
   6082                               EGL_NATIVE_BUFFER_USAGE_RENDERBUFFER_BIT_ANDROID |
   6083                               EGL_NATIVE_BUFFER_USAGE_TEXTURE_BIT_ANDROID)) != 0)
   6084                {
   6085                    val->setError(EGL_BAD_PARAMETER, "invalid usage flag");
   6086                    return false;
   6087                }
   6088                break;
   6089            case EGL_NONE:
   6090                break;
   6091            default:
   6092                val->setError(EGL_BAD_ATTRIBUTE, "invalid attribute");
   6093                return false;
   6094        }
   6095    }
   6096 
   6097    // Validate EGL_WIDTH and EGL_HEIGHT values passed in. Done here to account
   6098    // for the case where EGL_WIDTH and EGL_HEIGHT were not part of the attribute list.
   6099    if (width <= 0 || height <= 0)
   6100    {
   6101        val->setError(EGL_BAD_PARAMETER, "incorrect buffer dimensions requested");
   6102        return false;
   6103    }
   6104 
   6105    if (gl::GetAndroidHardwareBufferFormatFromChannelSizes(attribMap) == 0)
   6106    {
   6107        val->setError(EGL_BAD_PARAMETER, "unsupported format");
   6108        return false;
   6109    }
   6110    return true;
   6111 }
   6112 
   6113 bool ValidateCopyMetalSharedEventANGLE(const ValidationContext *val,
   6114                                       const Display *display,
   6115                                       const Sync *sync)
   6116 {
   6117    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6118 
   6119    if (!display->getExtensions().mtlSyncSharedEventANGLE)
   6120    {
   6121        val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_metal_shared_event_sync is not available.");
   6122        return false;
   6123    }
   6124 
   6125    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   6126 
   6127    return true;
   6128 }
   6129 
   6130 bool ValidateDupNativeFenceFDANDROID(const ValidationContext *val,
   6131                                     const Display *display,
   6132                                     const Sync *sync)
   6133 {
   6134    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6135 
   6136    if (!display->getExtensions().nativeFenceSyncANDROID)
   6137    {
   6138        val->setError(EGL_BAD_DISPLAY, "EGL_ANDROID_native_fence_sync extension is not available.");
   6139        return false;
   6140    }
   6141 
   6142    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   6143 
   6144    return true;
   6145 }
   6146 
   6147 bool ValidateSwapBuffersWithFrameTokenANGLE(const ValidationContext *val,
   6148                                            const Display *display,
   6149                                            const Surface *surface,
   6150                                            EGLFrameTokenANGLE frametoken)
   6151 {
   6152    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6153 
   6154    if (!display->getExtensions().swapWithFrameToken)
   6155    {
   6156        val->setError(EGL_BAD_DISPLAY, "EGL_ANGLE_swap_buffers_with_frame_token is not available.");
   6157        return false;
   6158    }
   6159 
   6160    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   6161 
   6162    return true;
   6163 }
   6164 
   6165 bool ValidatePrepareSwapBuffersANGLE(const ValidationContext *val,
   6166                                     const Display *display,
   6167                                     const Surface *surface)
   6168 {
   6169    return ValidateSwapBuffers(val, display, surface);
   6170 }
   6171 
   6172 bool ValidateSignalSyncKHR(const ValidationContext *val,
   6173                           const Display *display,
   6174                           const Sync *sync,
   6175                           EGLenum mode)
   6176 {
   6177    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6178 
   6179    ANGLE_VALIDATION_TRY(ValidateSync(val, display, sync));
   6180 
   6181    if (sync->getType() == EGL_SYNC_REUSABLE_KHR)
   6182    {
   6183        if (!display->getExtensions().reusableSyncKHR)
   6184        {
   6185            val->setError(EGL_BAD_MATCH, "EGL_KHR_reusable_sync extension is not available.");
   6186            return false;
   6187        }
   6188 
   6189        if ((mode != EGL_SIGNALED_KHR) && (mode != EGL_UNSIGNALED_KHR))
   6190        {
   6191            val->setError(EGL_BAD_PARAMETER, "eglSignalSyncKHR invalid mode.");
   6192            return false;
   6193        }
   6194 
   6195        return true;
   6196    }
   6197 
   6198    val->setError(EGL_BAD_MATCH);
   6199    return false;
   6200 }
   6201 
   6202 bool ValidateQuerySurfacePointerANGLE(const ValidationContext *val,
   6203                                      const Display *display,
   6204                                      const Surface *eglSurface,
   6205                                      EGLint attribute,
   6206                                      void *const *value)
   6207 {
   6208    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6209 
   6210    if (!display->getExtensions().querySurfacePointer)
   6211    {
   6212        val->setError(EGL_BAD_ACCESS);
   6213        return false;
   6214    }
   6215 
   6216    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
   6217 
   6218    // validate the attribute parameter
   6219    switch (attribute)
   6220    {
   6221        case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
   6222            if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
   6223            {
   6224                val->setError(EGL_BAD_ATTRIBUTE);
   6225                return false;
   6226            }
   6227            break;
   6228        case EGL_DXGI_KEYED_MUTEX_ANGLE:
   6229            if (!display->getExtensions().keyedMutex)
   6230            {
   6231                val->setError(EGL_BAD_ATTRIBUTE);
   6232                return false;
   6233            }
   6234            break;
   6235        default:
   6236            val->setError(EGL_BAD_ATTRIBUTE);
   6237            return false;
   6238    }
   6239 
   6240    return true;
   6241 }
   6242 
   6243 bool ValidatePostSubBufferNV(const ValidationContext *val,
   6244                             const Display *display,
   6245                             const Surface *eglSurface,
   6246                             EGLint x,
   6247                             EGLint y,
   6248                             EGLint width,
   6249                             EGLint height)
   6250 {
   6251    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6252 
   6253    if (!display->getExtensions().postSubBuffer)
   6254    {
   6255        val->setError(EGL_BAD_ACCESS);
   6256        return false;
   6257    }
   6258 
   6259    if (x < 0 || y < 0 || width < 0 || height < 0)
   6260    {
   6261        val->setError(EGL_BAD_PARAMETER);
   6262        return false;
   6263    }
   6264 
   6265    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, eglSurface));
   6266 
   6267    if (display->isDeviceLost())
   6268    {
   6269        val->setError(EGL_CONTEXT_LOST);
   6270        return false;
   6271    }
   6272 
   6273    return true;
   6274 }
   6275 
   6276 bool ValidateQueryDeviceAttribEXT(const ValidationContext *val,
   6277                                  const Device *device,
   6278                                  EGLint attribute,
   6279                                  const EGLAttrib *value)
   6280 {
   6281    ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
   6282 
   6283    if (!Display::GetClientExtensions().deviceQueryEXT)
   6284    {
   6285        val->setError(EGL_BAD_ACCESS, "EGL_EXT_device_query not supported.");
   6286        return false;
   6287    }
   6288 
   6289    // validate the attribute parameter
   6290    switch (attribute)
   6291    {
   6292        case EGL_D3D11_DEVICE_ANGLE:
   6293        case EGL_D3D9_DEVICE_ANGLE:
   6294            if (!device->getExtensions().deviceD3D || device->getType() != attribute)
   6295            {
   6296                val->setError(EGL_BAD_ATTRIBUTE);
   6297                return false;
   6298            }
   6299            break;
   6300        case EGL_EAGL_CONTEXT_ANGLE:
   6301            if (!device->getExtensions().deviceEAGL)
   6302            {
   6303                val->setError(EGL_BAD_ATTRIBUTE);
   6304                return false;
   6305            }
   6306            break;
   6307        case EGL_METAL_DEVICE_ANGLE:
   6308            if (!device->getExtensions().deviceMetal)
   6309            {
   6310                val->setError(EGL_BAD_ATTRIBUTE);
   6311                return false;
   6312            }
   6313            break;
   6314        case EGL_VULKAN_VERSION_ANGLE:
   6315        case EGL_VULKAN_INSTANCE_ANGLE:
   6316        case EGL_VULKAN_INSTANCE_EXTENSIONS_ANGLE:
   6317        case EGL_VULKAN_PHYSICAL_DEVICE_ANGLE:
   6318        case EGL_VULKAN_DEVICE_ANGLE:
   6319        case EGL_VULKAN_DEVICE_EXTENSIONS_ANGLE:
   6320        case EGL_VULKAN_FEATURES_ANGLE:
   6321        case EGL_VULKAN_QUEUE_ANGLE:
   6322        case EGL_VULKAN_QUEUE_FAMILIY_INDEX_ANGLE:
   6323        case EGL_VULKAN_GET_INSTANCE_PROC_ADDR:
   6324            if (!device->getExtensions().deviceVulkan)
   6325            {
   6326                val->setError(EGL_BAD_ATTRIBUTE);
   6327                return false;
   6328            }
   6329            break;
   6330        case EGL_CGL_CONTEXT_ANGLE:
   6331        case EGL_CGL_PIXEL_FORMAT_ANGLE:
   6332            if (!device->getExtensions().deviceCGL)
   6333            {
   6334                val->setError(EGL_BAD_ATTRIBUTE);
   6335                return false;
   6336            }
   6337            break;
   6338        default:
   6339            val->setError(EGL_BAD_ATTRIBUTE);
   6340            return false;
   6341    }
   6342    return true;
   6343 }
   6344 
   6345 bool ValidateQueryDeviceStringEXT(const ValidationContext *val, const Device *device, EGLint name)
   6346 {
   6347    ANGLE_VALIDATION_TRY(ValidateDevice(val, device));
   6348    return true;
   6349 }
   6350 
   6351 bool ValidateReleaseHighPowerGPUANGLE(const ValidationContext *val,
   6352                                      const Display *display,
   6353                                      const gl::Context *context)
   6354 {
   6355    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   6356    return true;
   6357 }
   6358 
   6359 bool ValidateReacquireHighPowerGPUANGLE(const ValidationContext *val,
   6360                                        const Display *display,
   6361                                        const gl::Context *context)
   6362 {
   6363    ANGLE_VALIDATION_TRY(ValidateContext(val, display, context));
   6364    return true;
   6365 }
   6366 
   6367 bool ValidateHandleGPUSwitchANGLE(const ValidationContext *val, const Display *display)
   6368 {
   6369    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6370    return true;
   6371 }
   6372 
   6373 bool ValidateForceGPUSwitchANGLE(const ValidationContext *val,
   6374                                 const Display *display,
   6375                                 EGLint gpuIDHigh,
   6376                                 EGLint gpuIDLow)
   6377 {
   6378    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6379    return true;
   6380 }
   6381 
   6382 bool ValidateGetCurrentDisplay(const ValidationContext *val)
   6383 {
   6384    return true;
   6385 }
   6386 
   6387 bool ValidateGetCurrentSurface(const ValidationContext *val, EGLint readdraw)
   6388 {
   6389    return true;
   6390 }
   6391 
   6392 bool ValidateGetDisplay(const ValidationContext *val, EGLNativeDisplayType display_id)
   6393 {
   6394    return true;
   6395 }
   6396 
   6397 bool ValidateGetError(const ValidationContext *val)
   6398 {
   6399    return true;
   6400 }
   6401 
   6402 bool ValidateGetProcAddress(const ValidationContext *val, const char *procname)
   6403 {
   6404    return true;
   6405 }
   6406 
   6407 bool ValidateQueryString(const ValidationContext *val, const Display *dpyPacked, EGLint name)
   6408 {
   6409    // The only situation where EGL_NO_DISPLAY is allowed is when querying
   6410    // EGL_EXTENSIONS or EGL_VERSION.
   6411    const bool canQueryWithoutDisplay = (name == EGL_VERSION || name == EGL_EXTENSIONS);
   6412 
   6413    if (dpyPacked != nullptr || !canQueryWithoutDisplay)
   6414    {
   6415        ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpyPacked));
   6416    }
   6417 
   6418    switch (name)
   6419    {
   6420        case EGL_CLIENT_APIS:
   6421        case EGL_EXTENSIONS:
   6422        case EGL_VENDOR:
   6423        case EGL_VERSION:
   6424            break;
   6425        default:
   6426            val->setError(EGL_BAD_PARAMETER);
   6427            return false;
   6428    }
   6429    return true;
   6430 }
   6431 
   6432 bool ValidateWaitGL(const ValidationContext *val)
   6433 {
   6434    if (val->eglThread->getDisplay() == nullptr)
   6435    {
   6436        // EGL spec says this about eglWaitGL -
   6437        //    eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
   6438        return true;
   6439    }
   6440 
   6441    ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
   6442    return true;
   6443 }
   6444 
   6445 bool ValidateQueryAPI(const ValidationContext *val)
   6446 {
   6447    return true;
   6448 }
   6449 
   6450 bool ValidateReleaseThread(const ValidationContext *val)
   6451 {
   6452    return true;
   6453 }
   6454 
   6455 bool ValidateWaitClient(const ValidationContext *val)
   6456 {
   6457    if (val->eglThread->getDisplay() == nullptr)
   6458    {
   6459        // EGL spec says this about eglWaitClient -
   6460        //    If there is no current context for the current rendering API,
   6461        //    the function has no effect but still returns EGL_TRUE.
   6462        return true;
   6463    }
   6464 
   6465    ANGLE_VALIDATION_TRY(ValidateDisplay(val, val->eglThread->getDisplay()));
   6466    return true;
   6467 }
   6468 
   6469 bool ValidateGetCurrentContext(const ValidationContext *val)
   6470 {
   6471    return true;
   6472 }
   6473 
   6474 bool ValidateCreatePlatformPixmapSurface(const ValidationContext *val,
   6475                                         const Display *dpyPacked,
   6476                                         const Config *configPacked,
   6477                                         const void *native_pixmap,
   6478                                         const AttributeMap &attrib_listPacked)
   6479 {
   6480    EGLNativePixmapType nativePixmap =
   6481        reinterpret_cast<EGLNativePixmapType>(const_cast<void *>(native_pixmap));
   6482    return ValidateCreatePixmapSurface(val, dpyPacked, configPacked, nativePixmap,
   6483                                       attrib_listPacked);
   6484 }
   6485 
   6486 bool ValidateCreatePlatformWindowSurface(const ValidationContext *val,
   6487                                         const Display *dpyPacked,
   6488                                         const Config *configPacked,
   6489                                         const void *native_window,
   6490                                         const AttributeMap &attrib_listPacked)
   6491 {
   6492    EGLNativeWindowType nativeWindow =
   6493        reinterpret_cast<EGLNativeWindowType>(const_cast<void *>(native_window));
   6494    return ValidateCreateWindowSurface(val, dpyPacked, configPacked, nativeWindow,
   6495                                       attrib_listPacked);
   6496 }
   6497 
   6498 bool ValidateLockSurfaceKHR(const ValidationContext *val,
   6499                            const egl::Display *dpy,
   6500                            const Surface *surface,
   6501                            const AttributeMap &attributes)
   6502 {
   6503    ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
   6504    ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
   6505 
   6506    if (!dpy->getExtensions().lockSurface3KHR)
   6507    {
   6508        val->setError(EGL_BAD_ACCESS);
   6509        return false;
   6510    }
   6511 
   6512    if (surface->isLocked())
   6513    {
   6514        val->setError(EGL_BAD_ACCESS);
   6515        return false;
   6516    }
   6517 
   6518    if ((surface->getConfig()->surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == false)
   6519    {
   6520        val->setError(EGL_BAD_ACCESS, "Config does not support EGL_LOCK_SURFACE_BIT");
   6521        return false;
   6522    }
   6523 
   6524    if (surface->isCurrentOnAnyContext())
   6525    {
   6526        val->setError(EGL_BAD_ACCESS,
   6527                      "Surface cannot be current to a context for eglLockSurface()");
   6528        return false;
   6529    }
   6530 
   6531    if (surface->hasProtectedContent())
   6532    {
   6533        val->setError(EGL_BAD_ACCESS, "Surface cannot be protected content for eglLockSurface()");
   6534        return false;
   6535    }
   6536 
   6537    attributes.initializeWithoutValidation();
   6538 
   6539    for (const auto &attributeIter : attributes)
   6540    {
   6541        EGLAttrib attribute = attributeIter.first;
   6542        EGLAttrib value     = attributeIter.second;
   6543 
   6544        switch (attribute)
   6545        {
   6546            case EGL_MAP_PRESERVE_PIXELS_KHR:
   6547                if (!((value == EGL_FALSE) || (value == EGL_TRUE)))
   6548                {
   6549                    val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_MAP_PRESERVE_PIXELS_KHR value");
   6550                    return false;
   6551                }
   6552                break;
   6553            case EGL_LOCK_USAGE_HINT_KHR:
   6554                if ((value & (EGL_READ_SURFACE_BIT_KHR | EGL_WRITE_SURFACE_BIT_KHR)) != value)
   6555                {
   6556                    val->setError(EGL_BAD_ATTRIBUTE, "Invalid EGL_LOCK_USAGE_HINT_KHR value");
   6557                    return false;
   6558                }
   6559                break;
   6560            default:
   6561                val->setError(EGL_BAD_ATTRIBUTE, "Invalid query surface64 attribute");
   6562                return false;
   6563        }
   6564    }
   6565 
   6566    return true;
   6567 }
   6568 
   6569 bool ValidateQuerySurface64KHR(const ValidationContext *val,
   6570                               const egl::Display *dpy,
   6571                               const Surface *surface,
   6572                               EGLint attribute,
   6573                               const EGLAttribKHR *value)
   6574 {
   6575    ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
   6576    ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
   6577 
   6578    if (!dpy->getExtensions().lockSurface3KHR)
   6579    {
   6580        val->setError(EGL_BAD_ACCESS);
   6581        return false;
   6582    }
   6583 
   6584    switch (attribute)
   6585    {
   6586        case EGL_BITMAP_PITCH_KHR:
   6587        case EGL_BITMAP_ORIGIN_KHR:
   6588        case EGL_BITMAP_PIXEL_RED_OFFSET_KHR:
   6589        case EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR:
   6590        case EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR:
   6591        case EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR:
   6592        case EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR:
   6593        case EGL_BITMAP_PIXEL_SIZE_KHR:
   6594        case EGL_BITMAP_POINTER_KHR:
   6595            break;
   6596        default:
   6597            val->setError(EGL_BAD_ATTRIBUTE, "Invalid eglQuerySurface64 attribute");
   6598            return false;
   6599    }
   6600 
   6601    if (value == nullptr)
   6602    {
   6603        val->setError(EGL_BAD_PARAMETER, "value is NULL.");
   6604        return false;
   6605    }
   6606 
   6607    if (!surface->isLocked())
   6608    {
   6609        val->setError(EGL_BAD_ACCESS, "Surface is not locked");
   6610        return false;
   6611    }
   6612 
   6613    return true;
   6614 }
   6615 
   6616 bool ValidateUnlockSurfaceKHR(const ValidationContext *val,
   6617                              const egl::Display *dpy,
   6618                              const Surface *surface)
   6619 {
   6620    ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
   6621    ANGLE_VALIDATION_TRY(ValidateSurface(val, dpy, surface));
   6622 
   6623    if (!dpy->getExtensions().lockSurface3KHR)
   6624    {
   6625        val->setError(EGL_BAD_ACCESS);
   6626        return false;
   6627    }
   6628 
   6629    if (!surface->isLocked())
   6630    {
   6631        val->setError(EGL_BAD_PARAMETER, "Surface is not locked.");
   6632        return false;
   6633    }
   6634 
   6635    return true;
   6636 }
   6637 
   6638 bool ValidateExportVkImageANGLE(const ValidationContext *val,
   6639                                const Display *dpy,
   6640                                const Image *image,
   6641                                const void *vkImage,
   6642                                const void *vkImageCreateInfo)
   6643 {
   6644    ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
   6645    ANGLE_VALIDATION_TRY(ValidateImage(val, dpy, image));
   6646 
   6647    if (!dpy->getExtensions().vulkanImageANGLE)
   6648    {
   6649        val->setError(EGL_BAD_ACCESS);
   6650        return false;
   6651    }
   6652 
   6653    if (!vkImage)
   6654    {
   6655        val->setError(EGL_BAD_PARAMETER, "Output VkImage pointer is null.");
   6656        return false;
   6657    }
   6658 
   6659    if (!vkImageCreateInfo)
   6660    {
   6661        val->setError(EGL_BAD_PARAMETER, "Output VkImageCreateInfo pointer is null.");
   6662        return false;
   6663    }
   6664 
   6665    return true;
   6666 }
   6667 
   6668 bool ValidateSetDamageRegionKHR(const ValidationContext *val,
   6669                                const Display *display,
   6670                                const Surface *surface,
   6671                                const EGLint *rects,
   6672                                EGLint n_rects)
   6673 {
   6674    ANGLE_VALIDATION_TRY(ValidateDisplay(val, display));
   6675    ANGLE_VALIDATION_TRY(ValidateSurface(val, display, surface));
   6676 
   6677    if (!(surface->getType() & EGL_WINDOW_BIT))
   6678    {
   6679        val->setError(EGL_BAD_MATCH, "surface is not a postable surface");
   6680        return false;
   6681    }
   6682 
   6683    if (surface != val->eglThread->getCurrentDrawSurface())
   6684    {
   6685        val->setError(EGL_BAD_MATCH,
   6686                      "surface is not the current draw surface for the calling thread");
   6687        return false;
   6688    }
   6689 
   6690    if (surface->getSwapBehavior() != EGL_BUFFER_DESTROYED)
   6691    {
   6692        val->setError(EGL_BAD_MATCH, "surface's swap behavior is not EGL_BUFFER_DESTROYED");
   6693        return false;
   6694    }
   6695 
   6696    if (surface->isDamageRegionSet())
   6697    {
   6698        val->setError(
   6699            EGL_BAD_ACCESS,
   6700            "damage region has already been set on surface since the most recent frame boundary");
   6701        return false;
   6702    }
   6703 
   6704    if (!surface->bufferAgeQueriedSinceLastSwap())
   6705    {
   6706        val->setError(EGL_BAD_ACCESS,
   6707                      "EGL_BUFFER_AGE_KHR attribute of surface has not been queried since the most "
   6708                      "recent frame boundary");
   6709        return false;
   6710    }
   6711 
   6712    return true;
   6713 }
   6714 
   6715 bool ValidateQueryDmaBufFormatsEXT(ValidationContext const *val,
   6716                                   Display const *dpy,
   6717                                   EGLint max_formats,
   6718                                   const EGLint *formats,
   6719                                   const EGLint *num_formats)
   6720 {
   6721    ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
   6722 
   6723    if (!dpy->getExtensions().imageDmaBufImportModifiersEXT)
   6724    {
   6725        val->setError(EGL_BAD_ACCESS, "EGL_EXT_dma_buf_import_modfier not supported");
   6726        return false;
   6727    }
   6728 
   6729    if (max_formats < 0)
   6730    {
   6731        val->setError(EGL_BAD_PARAMETER, "max_formats should not be negative");
   6732        return false;
   6733    }
   6734 
   6735    if (max_formats > 0 && formats == nullptr)
   6736    {
   6737        val->setError(EGL_BAD_PARAMETER, "if max_formats is positive, formats should not be NULL");
   6738        return false;
   6739    }
   6740 
   6741    return true;
   6742 }
   6743 
   6744 bool ValidateQueryDmaBufModifiersEXT(ValidationContext const *val,
   6745                                     Display const *dpy,
   6746                                     EGLint format,
   6747                                     EGLint max_modifiers,
   6748                                     const EGLuint64KHR *modifiers,
   6749                                     const EGLBoolean *external_only,
   6750                                     const EGLint *num_modifiers)
   6751 {
   6752    ANGLE_VALIDATION_TRY(ValidateDisplay(val, dpy));
   6753 
   6754    if (!dpy->getExtensions().imageDmaBufImportModifiersEXT)
   6755    {
   6756        val->setError(EGL_BAD_ACCESS, "EGL_EXT_dma_buf_import_modfier not supported");
   6757        return false;
   6758    }
   6759 
   6760    if (max_modifiers < 0)
   6761    {
   6762        val->setError(EGL_BAD_PARAMETER, "max_modifiers should not be negative");
   6763        return false;
   6764    }
   6765 
   6766    if (max_modifiers > 0 && modifiers == nullptr)
   6767    {
   6768        val->setError(EGL_BAD_PARAMETER,
   6769                      "if max_modifiers is positive, modifiers should not be NULL");
   6770        return false;
   6771    }
   6772 
   6773    if (!dpy->supportsDmaBufFormat(format))
   6774    {
   6775        val->setError(EGL_BAD_PARAMETER,
   6776                      "format should be one of the formats advertised by QueryDmaBufFormatsEXT");
   6777        return false;
   6778    }
   6779    return true;
   6780 }
   6781 
   6782 }  // namespace egl