tor-browser

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

egl_stubs.cpp (27194B)


      1 //
      2 // Copyright 2020 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 // egl_stubs.cpp: Stubs for EGL entry points.
      7 //
      8 
      9 #include "libGLESv2/egl_stubs_autogen.h"
     10 
     11 #include "common/angle_version_info.h"
     12 #include "libANGLE/Context.h"
     13 #include "libANGLE/Display.h"
     14 #include "libANGLE/EGLSync.h"
     15 #include "libANGLE/Surface.h"
     16 #include "libANGLE/Thread.h"
     17 #include "libANGLE/capture/capture_egl.h"
     18 #include "libANGLE/capture/frame_capture_utils_autogen.h"
     19 #include "libANGLE/capture/gl_enum_utils_autogen.h"
     20 #include "libANGLE/queryutils.h"
     21 #include "libANGLE/validationEGL.h"
     22 #include "libGLESv2/global_state.h"
     23 #include "libGLESv2/proc_table_egl.h"
     24 
     25 namespace egl
     26 {
     27 namespace
     28 {
     29 
     30 bool CompareProc(const ProcEntry &a, const char *b)
     31 {
     32    return strcmp(a.first, b) < 0;
     33 }
     34 
     35 void ClipConfigs(const std::vector<const Config *> &filteredConfigs,
     36                 EGLConfig *outputConfigs,
     37                 EGLint configSize,
     38                 EGLint *numConfigs)
     39 {
     40    EGLint resultSize = static_cast<EGLint>(filteredConfigs.size());
     41    if (outputConfigs)
     42    {
     43        resultSize = std::max(std::min(resultSize, configSize), 0);
     44        for (EGLint i = 0; i < resultSize; i++)
     45        {
     46            outputConfigs[i] = const_cast<Config *>(filteredConfigs[i]);
     47        }
     48    }
     49    *numConfigs = resultSize;
     50 }
     51 }  // anonymous namespace
     52 
     53 EGLBoolean BindAPI(Thread *thread, EGLenum api)
     54 {
     55    thread->setAPI(api);
     56 
     57    thread->setSuccess();
     58    return EGL_TRUE;
     59 }
     60 
     61 EGLBoolean BindTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer)
     62 {
     63    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglBindTexImage",
     64                         GetDisplayIfValid(display), EGL_FALSE);
     65 
     66    gl::Context *context = thread->getContext();
     67    if (context && !context->isContextLost())
     68    {
     69        gl::TextureType type =
     70            egl_gl::EGLTextureTargetToTextureType(eglSurface->getTextureTarget());
     71        gl::Texture *textureObject = context->getTextureByType(type);
     72        ANGLE_EGL_TRY_RETURN(thread, eglSurface->bindTexImage(context, textureObject, buffer),
     73                             "eglBindTexImage", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
     74 
     75        ANGLE_CAPTURE_EGL(EGLBindTexImage, thread, eglSurface, buffer);
     76    }
     77 
     78    thread->setSuccess();
     79    return EGL_TRUE;
     80 }
     81 
     82 EGLBoolean ChooseConfig(Thread *thread,
     83                        Display *display,
     84                        const AttributeMap &attribMap,
     85                        EGLConfig *configs,
     86                        EGLint config_size,
     87                        EGLint *num_config)
     88 {
     89    ClipConfigs(display->chooseConfig(attribMap), configs, config_size, num_config);
     90 
     91    thread->setSuccess();
     92    return EGL_TRUE;
     93 }
     94 
     95 EGLint ClientWaitSync(Thread *thread,
     96                      Display *display,
     97                      Sync *syncObject,
     98                      EGLint flags,
     99                      EGLTime timeout)
    100 {
    101    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglClientWaitSync",
    102                         GetDisplayIfValid(display), EGL_FALSE);
    103    gl::Context *currentContext = thread->getContext();
    104    EGLint syncStatus           = EGL_FALSE;
    105    ANGLE_EGL_TRY_RETURN(
    106        thread, syncObject->clientWait(display, currentContext, flags, timeout, &syncStatus),
    107        "eglClientWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
    108 
    109    thread->setSuccess();
    110    return syncStatus;
    111 }
    112 
    113 EGLBoolean CopyBuffers(Thread *thread,
    114                       Display *display,
    115                       Surface *eglSurface,
    116                       EGLNativePixmapType target)
    117 {
    118    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCopyBuffers",
    119                         GetDisplayIfValid(display), EGL_FALSE);
    120    UNIMPLEMENTED();  // FIXME
    121 
    122    thread->setSuccess();
    123    return 0;
    124 }
    125 
    126 EGLContext CreateContext(Thread *thread,
    127                         Display *display,
    128                         Config *configuration,
    129                         gl::Context *sharedGLContext,
    130                         const AttributeMap &attributes)
    131 {
    132    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateContext",
    133                         GetDisplayIfValid(display), EGL_NO_CONTEXT);
    134    gl::Context *context = nullptr;
    135    ANGLE_EGL_TRY_RETURN(thread,
    136                         display->createContext(configuration, sharedGLContext, thread->getAPI(),
    137                                                attributes, &context),
    138                         "eglCreateContext", GetDisplayIfValid(display), EGL_NO_CONTEXT);
    139 
    140    thread->setSuccess();
    141    return static_cast<EGLContext>(context);
    142 }
    143 
    144 EGLImage CreateImage(Thread *thread,
    145                     Display *display,
    146                     gl::Context *context,
    147                     EGLenum target,
    148                     EGLClientBuffer buffer,
    149                     const AttributeMap &attributes)
    150 {
    151    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateImage",
    152                         GetDisplayIfValid(display), EGL_FALSE);
    153 
    154    Image *image = nullptr;
    155    Error error  = display->createImage(context, target, buffer, attributes, &image);
    156    if (error.isError())
    157    {
    158        thread->setError(error, "eglCreateImage", GetDisplayIfValid(display));
    159        return EGL_NO_IMAGE;
    160    }
    161 
    162    ANGLE_CAPTURE_EGL(EGLCreateImage, thread, context, target, buffer, attributes, image);
    163 
    164    thread->setSuccess();
    165    return static_cast<EGLImage>(image);
    166 }
    167 
    168 EGLSurface CreatePbufferFromClientBuffer(Thread *thread,
    169                                         Display *display,
    170                                         EGLenum buftype,
    171                                         EGLClientBuffer buffer,
    172                                         Config *configuration,
    173                                         const AttributeMap &attributes)
    174 {
    175    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferFromClientBuffer",
    176                         GetDisplayIfValid(display), EGL_NO_SURFACE);
    177    Surface *surface = nullptr;
    178    ANGLE_EGL_TRY_RETURN(thread,
    179                         display->createPbufferFromClientBuffer(configuration, buftype, buffer,
    180                                                                attributes, &surface),
    181                         "eglCreatePbufferFromClientBuffer", GetDisplayIfValid(display),
    182                         EGL_NO_SURFACE);
    183 
    184    return static_cast<EGLSurface>(surface);
    185 }
    186 
    187 EGLSurface CreatePbufferSurface(Thread *thread,
    188                                Display *display,
    189                                Config *configuration,
    190                                const AttributeMap &attributes)
    191 {
    192    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePbufferSurface",
    193                         GetDisplayIfValid(display), EGL_NO_SURFACE);
    194    Surface *surface = nullptr;
    195    ANGLE_EGL_TRY_RETURN(thread, display->createPbufferSurface(configuration, attributes, &surface),
    196                         "eglCreatePbufferSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
    197 
    198    ANGLE_CAPTURE_EGL(EGLCreatePbufferSurface, thread, attributes, surface);
    199 
    200    return static_cast<EGLSurface>(surface);
    201 }
    202 
    203 EGLSurface CreatePixmapSurface(Thread *thread,
    204                               Display *display,
    205                               Config *configuration,
    206                               EGLNativePixmapType pixmap,
    207                               const AttributeMap &attributes)
    208 {
    209    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePixmapSurface",
    210                         GetDisplayIfValid(display), EGL_NO_SURFACE);
    211    Surface *surface = nullptr;
    212    ANGLE_EGL_TRY_RETURN(thread,
    213                         display->createPixmapSurface(configuration, pixmap, attributes, &surface),
    214                         "eglCreatePixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
    215 
    216    thread->setSuccess();
    217    return static_cast<EGLSurface>(surface);
    218 }
    219 
    220 EGLSurface CreatePlatformPixmapSurface(Thread *thread,
    221                                       Display *display,
    222                                       Config *configuration,
    223                                       void *pixmap,
    224                                       const AttributeMap &attributes)
    225 {
    226    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformPixmapSurface",
    227                         GetDisplayIfValid(display), EGL_NO_SURFACE);
    228    Surface *surface                 = nullptr;
    229    EGLNativePixmapType nativePixmap = reinterpret_cast<EGLNativePixmapType>(pixmap);
    230    ANGLE_EGL_TRY_RETURN(
    231        thread, display->createPixmapSurface(configuration, nativePixmap, attributes, &surface),
    232        "eglCreatePlatformPixmapSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
    233 
    234    thread->setSuccess();
    235    return static_cast<EGLSurface>(surface);
    236 }
    237 
    238 EGLSurface CreatePlatformWindowSurface(Thread *thread,
    239                                       Display *display,
    240                                       Config *configuration,
    241                                       void *win,
    242                                       const AttributeMap &attributes)
    243 {
    244    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreatePlatformWindowSurface",
    245                         GetDisplayIfValid(display), EGL_NO_SURFACE);
    246    Surface *surface                 = nullptr;
    247    EGLNativeWindowType nativeWindow = reinterpret_cast<EGLNativeWindowType>(win);
    248    ANGLE_EGL_TRY_RETURN(
    249        thread, display->createWindowSurface(configuration, nativeWindow, attributes, &surface),
    250        "eglPlatformCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
    251 
    252    return static_cast<EGLSurface>(surface);
    253 }
    254 
    255 EGLSync CreateSync(Thread *thread, Display *display, EGLenum type, const AttributeMap &attributes)
    256 {
    257    gl::Context *currentContext = thread->getContext();
    258 
    259    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateSync",
    260                         GetDisplayIfValid(display), EGL_FALSE);
    261    Sync *syncObject = nullptr;
    262    ANGLE_EGL_TRY_RETURN(thread, display->createSync(currentContext, type, attributes, &syncObject),
    263                         "eglCreateSync", GetDisplayIfValid(display), EGL_NO_SYNC);
    264 
    265    thread->setSuccess();
    266    return static_cast<EGLSync>(syncObject);
    267 }
    268 
    269 EGLSurface CreateWindowSurface(Thread *thread,
    270                               Display *display,
    271                               Config *configuration,
    272                               EGLNativeWindowType win,
    273                               const AttributeMap &attributes)
    274 {
    275    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglCreateWindowSurface",
    276                         GetDisplayIfValid(display), EGL_NO_SURFACE);
    277 
    278    Surface *surface = nullptr;
    279    ANGLE_EGL_TRY_RETURN(thread,
    280                         display->createWindowSurface(configuration, win, attributes, &surface),
    281                         "eglCreateWindowSurface", GetDisplayIfValid(display), EGL_NO_SURFACE);
    282 
    283    return static_cast<EGLSurface>(surface);
    284 }
    285 
    286 EGLBoolean DestroyContext(Thread *thread, Display *display, gl::Context *context)
    287 {
    288    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyContext",
    289                         GetDisplayIfValid(display), EGL_FALSE);
    290 
    291    ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
    292 
    293    ANGLE_EGL_TRY_RETURN(thread, display->destroyContext(thread, context), "eglDestroyContext",
    294                         GetContextIfValid(display, context), EGL_FALSE);
    295    thread->setSuccess();
    296    return EGL_TRUE;
    297 }
    298 
    299 EGLBoolean DestroyImage(Thread *thread, Display *display, Image *img)
    300 {
    301    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroyImage",
    302                         GetDisplayIfValid(display), EGL_FALSE);
    303    display->destroyImage(img);
    304 
    305    ANGLE_CAPTURE_EGL(EGLDestroyImage, thread, display, img);
    306 
    307    thread->setSuccess();
    308    return EGL_TRUE;
    309 }
    310 
    311 EGLBoolean DestroySurface(Thread *thread, Display *display, Surface *eglSurface)
    312 {
    313    ANGLE_CAPTURE_EGL(EGLDestroySurface, thread, display, eglSurface);
    314 
    315    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySurface",
    316                         GetDisplayIfValid(display), EGL_FALSE);
    317 
    318    ANGLE_EGL_TRY_RETURN(thread, display->destroySurface(eglSurface), "eglDestroySurface",
    319                         GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
    320 
    321    thread->setSuccess();
    322    return EGL_TRUE;
    323 }
    324 
    325 EGLBoolean DestroySync(Thread *thread, Display *display, Sync *syncObject)
    326 {
    327    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglDestroySync",
    328                         GetDisplayIfValid(display), EGL_FALSE);
    329    display->destroySync(syncObject);
    330 
    331    thread->setSuccess();
    332    return EGL_TRUE;
    333 }
    334 
    335 EGLBoolean GetConfigAttrib(Thread *thread,
    336                           Display *display,
    337                           Config *configuration,
    338                           EGLint attribute,
    339                           EGLint *value)
    340 {
    341    QueryConfigAttrib(configuration, attribute, value);
    342 
    343    thread->setSuccess();
    344    return EGL_TRUE;
    345 }
    346 
    347 EGLBoolean GetConfigs(Thread *thread,
    348                      Display *display,
    349                      EGLConfig *configs,
    350                      EGLint config_size,
    351                      EGLint *num_config)
    352 {
    353    ClipConfigs(display->getConfigs(AttributeMap()), configs, config_size, num_config);
    354 
    355    thread->setSuccess();
    356    return EGL_TRUE;
    357 }
    358 
    359 EGLContext GetCurrentContext(Thread *thread)
    360 {
    361    gl::Context *context = thread->getContext();
    362 
    363    thread->setSuccess();
    364    return static_cast<EGLContext>(context);
    365 }
    366 
    367 EGLDisplay GetCurrentDisplay(Thread *thread)
    368 {
    369    thread->setSuccess();
    370    if (thread->getContext() != nullptr)
    371    {
    372        return thread->getContext()->getDisplay();
    373    }
    374    return EGL_NO_DISPLAY;
    375 }
    376 
    377 EGLSurface GetCurrentSurface(Thread *thread, EGLint readdraw)
    378 {
    379    if (readdraw == EGL_READ)
    380    {
    381        thread->setSuccess();
    382        return thread->getCurrentReadSurface();
    383    }
    384    else if (readdraw == EGL_DRAW)
    385    {
    386        thread->setSuccess();
    387        return thread->getCurrentDrawSurface();
    388    }
    389    else
    390    {
    391        thread->setError(EglBadParameter(), "eglGetCurrentSurface", nullptr);
    392        return EGL_NO_SURFACE;
    393    }
    394 }
    395 
    396 EGLDisplay GetDisplay(Thread *thread, EGLNativeDisplayType display_id)
    397 {
    398    return Display::GetDisplayFromNativeDisplay(EGL_PLATFORM_ANGLE_ANGLE, display_id,
    399                                                AttributeMap());
    400 }
    401 
    402 EGLint GetError(Thread *thread)
    403 {
    404    EGLint error = thread->getError();
    405    thread->setSuccess();
    406    return error;
    407 }
    408 
    409 EGLDisplay GetPlatformDisplay(Thread *thread,
    410                              EGLenum platform,
    411                              void *native_display,
    412                              const AttributeMap &attribMap)
    413 {
    414    switch (platform)
    415    {
    416        case EGL_PLATFORM_ANGLE_ANGLE:
    417        case EGL_PLATFORM_GBM_KHR:
    418        case EGL_PLATFORM_WAYLAND_EXT:
    419        {
    420            return Display::GetDisplayFromNativeDisplay(
    421                platform, gl::bitCast<EGLNativeDisplayType>(native_display), attribMap);
    422        }
    423        case EGL_PLATFORM_DEVICE_EXT:
    424        {
    425            Device *eglDevice = static_cast<Device *>(native_display);
    426            return Display::GetDisplayFromDevice(eglDevice, attribMap);
    427        }
    428        default:
    429        {
    430            UNREACHABLE();
    431            return EGL_NO_DISPLAY;
    432        }
    433    }
    434 }
    435 
    436 __eglMustCastToProperFunctionPointerType GetProcAddress(Thread *thread, const char *procname)
    437 {
    438    const ProcEntry *entry =
    439        std::lower_bound(&g_procTable[0], &g_procTable[g_numProcs], procname, CompareProc);
    440 
    441    thread->setSuccess();
    442 
    443    if (entry == &g_procTable[g_numProcs] || strcmp(entry->first, procname) != 0)
    444    {
    445        return nullptr;
    446    }
    447 
    448    return entry->second;
    449 }
    450 
    451 EGLBoolean GetSyncAttrib(Thread *thread,
    452                         Display *display,
    453                         Sync *syncObject,
    454                         EGLint attribute,
    455                         EGLAttrib *value)
    456 {
    457    EGLint valueExt;
    458    ANGLE_EGL_TRY_RETURN(thread, GetSyncAttrib(display, syncObject, attribute, &valueExt),
    459                         "eglGetSyncAttrib", GetSyncIfValid(display, syncObject), EGL_FALSE);
    460    *value = valueExt;
    461 
    462    thread->setSuccess();
    463    return EGL_TRUE;
    464 }
    465 
    466 EGLBoolean Initialize(Thread *thread, Display *display, EGLint *major, EGLint *minor)
    467 {
    468    ANGLE_EGL_TRY_RETURN(thread, display->initialize(), "eglInitialize", GetDisplayIfValid(display),
    469                         EGL_FALSE);
    470 
    471    if (major)
    472    {
    473        *major = kEglMajorVersion;
    474    }
    475    if (minor)
    476    {
    477        *minor = kEglMinorVersion;
    478    }
    479 
    480    thread->setSuccess();
    481    return EGL_TRUE;
    482 }
    483 
    484 EGLBoolean MakeCurrent(Thread *thread,
    485                       Display *display,
    486                       Surface *drawSurface,
    487                       Surface *readSurface,
    488                       gl::Context *context)
    489 {
    490    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglMakeCurrent",
    491                         GetDisplayIfValid(display), EGL_FALSE);
    492    ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
    493 
    494    Surface *previousDraw        = thread->getCurrentDrawSurface();
    495    Surface *previousRead        = thread->getCurrentReadSurface();
    496    gl::Context *previousContext = thread->getContext();
    497 
    498    // Only call makeCurrent if the context or surfaces have changed.
    499    if (previousDraw != drawSurface || previousRead != readSurface || previousContext != context)
    500    {
    501        ANGLE_EGL_TRY_RETURN(
    502            thread,
    503            display->makeCurrent(thread, previousContext, drawSurface, readSurface, context),
    504            "eglMakeCurrent", GetContextIfValid(display, context), EGL_FALSE);
    505 
    506        ANGLE_CAPTURE_EGL(EGLMakeCurrent, thread, drawSurface, readSurface, context);
    507    }
    508 
    509    thread->setSuccess();
    510    return EGL_TRUE;
    511 }
    512 
    513 EGLenum QueryAPI(Thread *thread)
    514 {
    515    EGLenum API = thread->getAPI();
    516 
    517    thread->setSuccess();
    518    return API;
    519 }
    520 
    521 EGLBoolean QueryContext(Thread *thread,
    522                        Display *display,
    523                        gl::Context *context,
    524                        EGLint attribute,
    525                        EGLint *value)
    526 {
    527    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryContext",
    528                         GetDisplayIfValid(display), EGL_FALSE);
    529    QueryContextAttrib(context, attribute, value);
    530 
    531    thread->setSuccess();
    532    return EGL_TRUE;
    533 }
    534 
    535 const char *QueryString(Thread *thread, Display *display, EGLint name)
    536 {
    537    if (display)
    538    {
    539        ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQueryString",
    540                             GetDisplayIfValid(display), nullptr);
    541    }
    542 
    543    const char *result = nullptr;
    544    switch (name)
    545    {
    546        case EGL_CLIENT_APIS:
    547            result = display->getClientAPIString().c_str();
    548            break;
    549        case EGL_EXTENSIONS:
    550            if (display == EGL_NO_DISPLAY)
    551            {
    552                result = Display::GetClientExtensionString().c_str();
    553            }
    554            else
    555            {
    556                result = display->getExtensionString().c_str();
    557            }
    558            break;
    559        case EGL_VENDOR:
    560            result = display->getVendorString().c_str();
    561            break;
    562        case EGL_VERSION:
    563        {
    564            static const char *sVersionString =
    565                MakeStaticString(std::string("1.5 (ANGLE ") + angle::GetANGLEVersionString() + ")");
    566            result = sVersionString;
    567            break;
    568        }
    569        default:
    570            UNREACHABLE();
    571            break;
    572    }
    573 
    574    thread->setSuccess();
    575    return result;
    576 }
    577 
    578 EGLBoolean QuerySurface(Thread *thread,
    579                        Display *display,
    580                        Surface *eglSurface,
    581                        EGLint attribute,
    582                        EGLint *value)
    583 {
    584    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglQuerySurface",
    585                         GetDisplayIfValid(display), EGL_FALSE);
    586    ANGLE_EGL_TRY_RETURN(
    587        thread, QuerySurfaceAttrib(display, thread->getContext(), eglSurface, attribute, value),
    588        "eglQuerySurface", GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
    589 
    590    thread->setSuccess();
    591    return EGL_TRUE;
    592 }
    593 
    594 EGLBoolean ReleaseTexImage(Thread *thread, Display *display, Surface *eglSurface, EGLint buffer)
    595 {
    596    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglReleaseTexImage",
    597                         GetDisplayIfValid(display), EGL_FALSE);
    598    gl::Context *context = thread->getContext();
    599    if (context && !context->isContextLost())
    600    {
    601        gl::Texture *texture = eglSurface->getBoundTexture();
    602 
    603        if (texture)
    604        {
    605            ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer),
    606                                 "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface),
    607                                 EGL_FALSE);
    608            ANGLE_CAPTURE_EGL(EGLReleaseTexImage, thread, eglSurface, buffer);
    609        }
    610    }
    611    thread->setSuccess();
    612    return EGL_TRUE;
    613 }
    614 
    615 EGLBoolean ReleaseThread(Thread *thread)
    616 {
    617    ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
    618 
    619    Surface *previousDraw        = thread->getCurrentDrawSurface();
    620    Surface *previousRead        = thread->getCurrentReadSurface();
    621    gl::Context *previousContext = thread->getContext();
    622    Display *previousDisplay     = thread->getDisplay();
    623 
    624    if (previousDisplay != EGL_NO_DISPLAY)
    625    {
    626        ANGLE_EGL_TRY_RETURN(thread, previousDisplay->prepareForCall(), "eglReleaseThread",
    627                             GetDisplayIfValid(previousDisplay), EGL_FALSE);
    628        // Only call makeCurrent if the context or surfaces have changed.
    629        if (previousDraw != EGL_NO_SURFACE || previousRead != EGL_NO_SURFACE ||
    630            previousContext != EGL_NO_CONTEXT)
    631        {
    632            ANGLE_EGL_TRY_RETURN(
    633                thread,
    634                previousDisplay->makeCurrent(thread, previousContext, nullptr, nullptr, nullptr),
    635                "eglReleaseThread", nullptr, EGL_FALSE);
    636        }
    637        ANGLE_EGL_TRY_RETURN(thread, previousDisplay->releaseThread(), "eglReleaseThread",
    638                             GetDisplayIfValid(previousDisplay), EGL_FALSE);
    639    }
    640 
    641    thread->setSuccess();
    642    return EGL_TRUE;
    643 }
    644 
    645 EGLBoolean SurfaceAttrib(Thread *thread,
    646                         Display *display,
    647                         Surface *eglSurface,
    648                         EGLint attribute,
    649                         EGLint value)
    650 {
    651    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSurfaceAttrib",
    652                         GetDisplayIfValid(display), EGL_FALSE);
    653 
    654    ANGLE_EGL_TRY_RETURN(thread, SetSurfaceAttrib(eglSurface, attribute, value), "eglSurfaceAttrib",
    655                         GetDisplayIfValid(display), EGL_FALSE);
    656 
    657    thread->setSuccess();
    658    return EGL_TRUE;
    659 }
    660 
    661 EGLBoolean SwapBuffers(Thread *thread, Display *display, Surface *eglSurface)
    662 {
    663    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapBuffers",
    664                         GetDisplayIfValid(display), EGL_FALSE);
    665 
    666    ANGLE_EGL_TRY_RETURN(thread, eglSurface->swap(thread->getContext()), "eglSwapBuffers",
    667                         GetSurfaceIfValid(display, eglSurface), EGL_FALSE);
    668 
    669    thread->setSuccess();
    670    return EGL_TRUE;
    671 }
    672 
    673 EGLBoolean SwapInterval(Thread *thread, Display *display, EGLint interval)
    674 {
    675    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglSwapInterval",
    676                         GetDisplayIfValid(display), EGL_FALSE);
    677 
    678    Surface *drawSurface        = static_cast<Surface *>(thread->getCurrentDrawSurface());
    679    const Config *surfaceConfig = drawSurface->getConfig();
    680    EGLint clampedInterval      = std::min(std::max(interval, surfaceConfig->minSwapInterval),
    681                                           surfaceConfig->maxSwapInterval);
    682 
    683    drawSurface->setSwapInterval(clampedInterval);
    684 
    685    thread->setSuccess();
    686    return EGL_TRUE;
    687 }
    688 
    689 EGLBoolean Terminate(Thread *thread, Display *display)
    690 {
    691    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglTerminate",
    692                         GetDisplayIfValid(display), EGL_FALSE);
    693 
    694    ScopedSyncCurrentContextFromThread scopedSyncCurrent(thread);
    695 
    696    ANGLE_EGL_TRY_RETURN(thread, display->terminate(thread, Display::TerminateReason::Api),
    697                         "eglTerminate", GetDisplayIfValid(display), EGL_FALSE);
    698 
    699    thread->setSuccess();
    700    return EGL_TRUE;
    701 }
    702 
    703 EGLBoolean WaitClient(Thread *thread)
    704 {
    705    Display *display = thread->getDisplay();
    706    if (display == nullptr)
    707    {
    708        // EGL spec says this about eglWaitClient -
    709        //    If there is no current context for the current rendering API,
    710        //    the function has no effect but still returns EGL_TRUE.
    711        return EGL_TRUE;
    712    }
    713 
    714    gl::Context *context = thread->getContext();
    715 
    716    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitClient",
    717                         GetDisplayIfValid(display), EGL_FALSE);
    718    ANGLE_EGL_TRY_RETURN(thread, display->waitClient(context), "eglWaitClient",
    719                         GetContextIfValid(display, context), EGL_FALSE);
    720 
    721    thread->setSuccess();
    722    return EGL_TRUE;
    723 }
    724 
    725 EGLBoolean WaitGL(Thread *thread)
    726 {
    727    Display *display = thread->getDisplay();
    728    if (display == nullptr)
    729    {
    730        // EGL spec says this about eglWaitGL -
    731        //    eglWaitGL is ignored if there is no current EGL rendering context for OpenGL ES.
    732        return EGL_TRUE;
    733    }
    734 
    735    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitGL", GetDisplayIfValid(display),
    736                         EGL_FALSE);
    737 
    738    // eglWaitGL like calling eglWaitClient with the OpenGL ES API bound. Since we only implement
    739    // OpenGL ES we can do the call directly.
    740    ANGLE_EGL_TRY_RETURN(thread, display->waitClient(thread->getContext()), "eglWaitGL",
    741                         GetDisplayIfValid(display), EGL_FALSE);
    742 
    743    thread->setSuccess();
    744    return EGL_TRUE;
    745 }
    746 
    747 EGLBoolean WaitNative(Thread *thread, EGLint engine)
    748 {
    749    Display *display = thread->getDisplay();
    750    if (display == nullptr)
    751    {
    752        // EGL spec says this about eglWaitNative -
    753        //    eglWaitNative is ignored if there is no current EGL rendering context.
    754        return EGL_TRUE;
    755    }
    756 
    757    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitNative",
    758                         GetDisplayIfValid(display), EGL_FALSE);
    759    ANGLE_EGL_TRY_RETURN(thread, display->waitNative(thread->getContext(), engine), "eglWaitNative",
    760                         GetThreadIfValid(thread), EGL_FALSE);
    761 
    762    thread->setSuccess();
    763    return EGL_TRUE;
    764 }
    765 
    766 EGLBoolean WaitSync(Thread *thread, Display *display, Sync *syncObject, EGLint flags)
    767 {
    768    ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglWaitSync",
    769                         GetDisplayIfValid(display), EGL_FALSE);
    770    gl::Context *currentContext = thread->getContext();
    771    ANGLE_EGL_TRY_RETURN(thread, syncObject->serverWait(display, currentContext, flags),
    772                         "eglWaitSync", GetSyncIfValid(display, syncObject), EGL_FALSE);
    773 
    774    thread->setSuccess();
    775    return EGL_TRUE;
    776 }
    777 }  // namespace egl