// GENERATED FILE - DO NOT EDIT.
// Generated by generate_entry_points.py using data from egl.xml.
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// entry_points_egl_autogen.cpp:
//   Defines the EGL entry points.

#include "libGLESv2/entry_points_egl_autogen.h"
#include "libGLESv2/entry_points_egl_ext_autogen.h"

#include "libANGLE/capture/capture_egl_autogen.h"
#include "libANGLE/entry_points_utils.h"
#include "libANGLE/validationEGL_autogen.h"
#include "libGLESv2/egl_context_lock_impl.h"
#include "libGLESv2/egl_ext_stubs_autogen.h"
#include "libGLESv2/egl_stubs_autogen.h"
#include "libGLESv2/global_state.h"

using namespace egl;

extern "C" {

// EGL 1.0
EGLBoolean EGLAPIENTRY EGL_ChooseConfig(EGLDisplay dpy,
                                        const EGLint *attrib_list,
                                        EGLConfig *configs,
                                        EGLint config_size,
                                        EGLint *num_config)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(ChooseConfig,
                                    "dpy = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR
                                    ", configs = 0x%016" PRIxPTR
                                    ", config_size = %d, num_config = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)attrib_list, (uintptr_t)configs,
                                    config_size, (uintptr_t)num_config));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(ChooseConfig, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, ChooseConfig, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, attrib_listPacked, configs, config_size, num_config);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = ChooseConfig(thread, dpyPacked, attrib_listPacked, configs, config_size,
                                       num_config);
        }

        ANGLE_CAPTURE_EGL(ChooseConfig, true, thread, dpyPacked, attrib_listPacked, configs,
                          config_size, num_config, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_CopyBuffers(EGLDisplay dpy,
                                       EGLSurface surface,
                                       EGLNativePixmapType target)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(CopyBuffers,
                                    "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR
                                    ", target = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)surface, (uintptr_t)target));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CopyBuffers, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CopyBuffers, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, surfacePacked, target);
            }
            else
            {
            }

            returnValue = CopyBuffers(thread, dpyPacked, surfacePacked, target);
        }

        ANGLE_CAPTURE_EGL(CopyBuffers, true, thread, dpyPacked, surfacePacked, target, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLContext EGLAPIENTRY EGL_CreateContext(EGLDisplay dpy,
                                         EGLConfig config,
                                         EGLContext share_context,
                                         const EGLint *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLContext returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            CreateContext,
            "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", share_context = 0x%016" PRIxPTR
            ", attrib_list = 0x%016" PRIxPTR "",
            (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)share_context, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        gl::ContextID share_contextPacked     = PackParam<gl::ContextID>(share_context);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreateContext, thread, dpyPacked, share_contextPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreateContext, GetDisplayIfValid(dpyPacked), EGLContext,
                                   dpyPacked, configPacked, share_contextPacked, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = CreateContext(thread, dpyPacked, configPacked, share_contextPacked,
                                        attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreateContext, true, thread, dpyPacked, configPacked, share_contextPacked,
                          attrib_listPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_CreatePbufferSurface(EGLDisplay dpy,
                                                EGLConfig config,
                                                const EGLint *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(CreatePbufferSurface,
                                    "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR
                                    ", attrib_list = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreatePbufferSurface, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreatePbufferSurface, GetDisplayIfValid(dpyPacked),
                                   EGLSurface, dpyPacked, configPacked, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = CreatePbufferSurface(thread, dpyPacked, configPacked, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreatePbufferSurface, true, thread, dpyPacked, configPacked,
                          attrib_listPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_CreatePixmapSurface(EGLDisplay dpy,
                                               EGLConfig config,
                                               EGLNativePixmapType pixmap,
                                               const EGLint *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(CreatePixmapSurface,
                                    "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR
                                    ", pixmap = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)pixmap,
                                    (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreatePixmapSurface, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreatePixmapSurface, GetDisplayIfValid(dpyPacked),
                                   EGLSurface, dpyPacked, configPacked, pixmap, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue =
                CreatePixmapSurface(thread, dpyPacked, configPacked, pixmap, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreatePixmapSurface, true, thread, dpyPacked, configPacked, pixmap,
                          attrib_listPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_CreateWindowSurface(EGLDisplay dpy,
                                               EGLConfig config,
                                               EGLNativeWindowType win,
                                               const EGLint *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(CreateWindowSurface,
                                    "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR
                                    ", win = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)win,
                                    (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreateWindowSurface, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreateWindowSurface, GetDisplayIfValid(dpyPacked),
                                   EGLSurface, dpyPacked, configPacked, win, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue =
                CreateWindowSurface(thread, dpyPacked, configPacked, win, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreateWindowSurface, true, thread, dpyPacked, configPacked, win,
                          attrib_listPacked, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_DestroyContext(EGLDisplay dpy, EGLContext ctx)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(DestroyContext,
                                    "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)ctx));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        gl::ContextID ctxPacked = PackParam<gl::ContextID>(ctx);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(DestroyContext, thread, dpyPacked, ctxPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, DestroyContext, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, ctxPacked);
            }
            else
            {
            }

            returnValue = DestroyContext(thread, dpyPacked, ctxPacked);
        }

        ANGLE_CAPTURE_EGL(DestroyContext, true, thread, dpyPacked, ctxPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_DestroySurface(EGLDisplay dpy, EGLSurface surface)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(DestroySurface,
                                    "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)surface));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(DestroySurface, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, DestroySurface, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, surfacePacked);
            }
            else
            {
            }

            returnValue = DestroySurface(thread, dpyPacked, surfacePacked);
        }

        ANGLE_CAPTURE_EGL(DestroySurface, true, thread, dpyPacked, surfacePacked, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_GetConfigAttrib(EGLDisplay dpy,
                                           EGLConfig config,
                                           EGLint attribute,
                                           EGLint *value)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(GetConfigAttrib,
                                    "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR
                                    ", attribute = %d, value = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)config, attribute,
                                    (uintptr_t)value));

        egl::Display *dpyPacked   = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked = PackParam<egl::Config *>(config);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetConfigAttrib, thread, dpyPacked, attribute);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, GetConfigAttrib, GetDisplayIfValid(dpyPacked),
                                   EGLBoolean, dpyPacked, configPacked, attribute, value);
            }
            else
            {
            }

            returnValue = GetConfigAttrib(thread, dpyPacked, configPacked, attribute, value);
        }

        ANGLE_CAPTURE_EGL(GetConfigAttrib, true, thread, dpyPacked, configPacked, attribute, value,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_GetConfigs(EGLDisplay dpy,
                                      EGLConfig *configs,
                                      EGLint config_size,
                                      EGLint *num_config)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(GetConfigs,
                                    "dpy = 0x%016" PRIxPTR ", configs = 0x%016" PRIxPTR
                                    ", config_size = %d, num_config = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)configs, config_size,
                                    (uintptr_t)num_config));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetConfigs, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, GetConfigs, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, configs, config_size, num_config);
            }
            else
            {
            }

            returnValue = GetConfigs(thread, dpyPacked, configs, config_size, num_config);
        }

        ANGLE_CAPTURE_EGL(GetConfigs, true, thread, dpyPacked, configs, config_size, num_config,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLDisplay EGLAPIENTRY EGL_GetCurrentDisplay()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLDisplay returnValue;

    ANGLE_UNSAFE_TODO(EGL_EVENT(GetCurrentDisplay, ""));

    if (IsEGLValidationEnabled())
    {
        ANGLE_EGL_VALIDATE(thread, GetCurrentDisplay, nullptr, EGLDisplay);
    }
    else
    {
    }

    returnValue = GetCurrentDisplay(thread);

    ANGLE_CAPTURE_EGL(GetCurrentDisplay, true, thread, returnValue);

    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_GetCurrentSurface(EGLint readdraw)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;

    ANGLE_UNSAFE_TODO(EGL_EVENT(GetCurrentSurface, "readdraw = %d", readdraw));

    if (IsEGLValidationEnabled())
    {
        ANGLE_EGL_VALIDATE(thread, GetCurrentSurface, nullptr, EGLSurface, readdraw);
    }
    else
    {
    }

    returnValue = GetCurrentSurface(thread, readdraw);

    ANGLE_CAPTURE_EGL(GetCurrentSurface, true, thread, readdraw, returnValue);

    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLDisplay EGLAPIENTRY EGL_GetDisplay(EGLNativeDisplayType display_id)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLDisplay returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(
            EGL_EVENT(GetDisplay, "display_id = 0x%016" PRIxPTR "", (uintptr_t)display_id));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetDisplay, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, GetDisplay, nullptr, EGLDisplay, display_id);
            }
            else
            {
            }

            returnValue = GetDisplay(thread, display_id);
        }

        ANGLE_CAPTURE_EGL(GetDisplay, true, thread, display_id, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLint EGLAPIENTRY EGL_GetError()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLint returnValue;

    ANGLE_UNSAFE_TODO(EGL_EVENT(GetError, ""));

    if (IsEGLValidationEnabled())
    {
        ANGLE_EGL_VALIDATE(thread, GetError, nullptr, EGLint);
    }
    else
    {
    }

    returnValue = GetError(thread);

    ANGLE_CAPTURE_EGL(GetError, true, thread, returnValue);

    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

__eglMustCastToProperFunctionPointerType EGLAPIENTRY EGL_GetProcAddress(const char *procname)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    __eglMustCastToProperFunctionPointerType returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(
            EGL_EVENT(GetProcAddress, "procname = 0x%016" PRIxPTR "", (uintptr_t)procname));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetProcAddress, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, GetProcAddress, nullptr,
                                   __eglMustCastToProperFunctionPointerType, procname);
            }
            else
            {
            }

            returnValue = GetProcAddress(thread, procname);
        }

        ANGLE_CAPTURE_EGL(GetProcAddress, true, thread, procname, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(Initialize,
                                    "dpy = 0x%016" PRIxPTR ", major = 0x%016" PRIxPTR
                                    ", minor = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)major, (uintptr_t)minor));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(Initialize, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, Initialize, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, major, minor);
            }
            else
            {
            }

            returnValue = Initialize(thread, dpyPacked, major, minor);
        }

        ANGLE_CAPTURE_EGL(Initialize, true, thread, dpyPacked, major, minor, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_MakeCurrent(EGLDisplay dpy,
                                       EGLSurface draw,
                                       EGLSurface read,
                                       EGLContext ctx)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(MakeCurrent,
                                    "dpy = 0x%016" PRIxPTR ", draw = 0x%016" PRIxPTR
                                    ", read = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)draw, (uintptr_t)read,
                                    (uintptr_t)ctx));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID drawPacked    = PackParam<SurfaceID>(draw);
        SurfaceID readPacked    = PackParam<SurfaceID>(read);
        gl::ContextID ctxPacked = PackParam<gl::ContextID>(ctx);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(MakeCurrent, thread, dpyPacked, ctxPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, MakeCurrent, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, drawPacked, readPacked, ctxPacked);
            }
            else
            {
            }

            returnValue = MakeCurrent(thread, dpyPacked, drawPacked, readPacked, ctxPacked);
        }

        ANGLE_CAPTURE_EGL(MakeCurrent, true, thread, dpyPacked, drawPacked, readPacked, ctxPacked,
                          returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_QueryContext(EGLDisplay dpy,
                                        EGLContext ctx,
                                        EGLint attribute,
                                        EGLint *value)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(QueryContext,
                                    "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR
                                    ", attribute = %d, value = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)ctx, attribute, (uintptr_t)value));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        gl::ContextID ctxPacked = PackParam<gl::ContextID>(ctx);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(QueryContext, thread, dpyPacked, ctxPacked, attribute);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, QueryContext, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, ctxPacked, attribute, value);
            }
            else
            {
            }

            returnValue = QueryContext(thread, dpyPacked, ctxPacked, attribute, value);
        }

        ANGLE_CAPTURE_EGL(QueryContext, true, thread, dpyPacked, ctxPacked, attribute, value,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

const char *EGLAPIENTRY EGL_QueryString(EGLDisplay dpy, EGLint name)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    const char *returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(
            EGL_EVENT(QueryString, "dpy = 0x%016" PRIxPTR ", name = %d", (uintptr_t)dpy, name));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(QueryString, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, QueryString, GetDisplayIfValid(dpyPacked), const char *,
                                   dpyPacked, name);
            }
            else
            {
            }

            returnValue = QueryString(thread, dpyPacked, name);
        }

        ANGLE_CAPTURE_EGL(QueryString, true, thread, dpyPacked, name, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_QuerySurface(EGLDisplay dpy,
                                        EGLSurface surface,
                                        EGLint attribute,
                                        EGLint *value)
{
    if (attribute == EGL_BUFFER_AGE_EXT || attribute == EGL_SURFACE_COMPRESSION_EXT)
    {
        ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(dpy, surface));
    }
    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(QuerySurface,
                                    "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR
                                    ", attribute = %d, value = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)surface, attribute,
                                    (uintptr_t)value));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(QuerySurface, thread, dpyPacked, attribute);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, QuerySurface, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, surfacePacked, attribute, value);
            }
            else
            {
            }

            returnValue = QuerySurface(thread, dpyPacked, surfacePacked, attribute, value);
        }

        ANGLE_CAPTURE_EGL(QuerySurface, true, thread, dpyPacked, surfacePacked, attribute, value,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_SwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
    ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(dpy, surface));
    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(SwapBuffers,
                                    "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)surface));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(SwapBuffers, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, SwapBuffers, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, surfacePacked);
            }
            else
            {
            }

            returnValue = SwapBuffers(thread, dpyPacked, surfacePacked);
        }

        ANGLE_CAPTURE_EGL(SwapBuffers, true, thread, dpyPacked, surfacePacked, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_Terminate(EGLDisplay dpy)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(Terminate, "dpy = 0x%016" PRIxPTR "", (uintptr_t)dpy));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(Terminate, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, Terminate, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked);
            }
            else
            {
            }

            returnValue = Terminate(thread, dpyPacked);
        }

        ANGLE_CAPTURE_EGL(Terminate, true, thread, dpyPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_WaitGL()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(WaitGL, ""));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitGL, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, WaitGL, nullptr, EGLBoolean);
            }
            else
            {
            }

            returnValue = WaitGL(thread);
        }

        ANGLE_CAPTURE_EGL(WaitGL, true, thread, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_WaitNative(EGLint engine)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(WaitNative, "engine = %d", engine));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitNative, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, WaitNative, nullptr, EGLBoolean, engine);
            }
            else
            {
            }

            returnValue = WaitNative(thread, engine);
        }

        ANGLE_CAPTURE_EGL(WaitNative, true, thread, engine, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

// EGL 1.1
EGLBoolean EGLAPIENTRY EGL_BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            BindTexImage, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", buffer = %d",
            (uintptr_t)dpy, (uintptr_t)surface, buffer));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(BindTexImage, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, BindTexImage, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, surfacePacked, buffer);
            }
            else
            {
            }

            returnValue = BindTexImage(thread, dpyPacked, surfacePacked, buffer);
        }

        ANGLE_CAPTURE_EGL(BindTexImage, true, thread, dpyPacked, surfacePacked, buffer,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            ReleaseTexImage, "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR ", buffer = %d",
            (uintptr_t)dpy, (uintptr_t)surface, buffer));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(ReleaseTexImage, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, ReleaseTexImage, GetDisplayIfValid(dpyPacked),
                                   EGLBoolean, dpyPacked, surfacePacked, buffer);
            }
            else
            {
            }

            returnValue = ReleaseTexImage(thread, dpyPacked, surfacePacked, buffer);
        }

        ANGLE_CAPTURE_EGL(ReleaseTexImage, true, thread, dpyPacked, surfacePacked, buffer,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_SurfaceAttrib(EGLDisplay dpy,
                                         EGLSurface surface,
                                         EGLint attribute,
                                         EGLint value)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(SurfaceAttrib,
                                    "dpy = 0x%016" PRIxPTR ", surface = 0x%016" PRIxPTR
                                    ", attribute = %d, value = %d",
                                    (uintptr_t)dpy, (uintptr_t)surface, attribute, value));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        SurfaceID surfacePacked = PackParam<SurfaceID>(surface);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(SurfaceAttrib, thread, dpyPacked, attribute);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, SurfaceAttrib, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, surfacePacked, attribute, value);
            }
            else
            {
            }

            returnValue = SurfaceAttrib(thread, dpyPacked, surfacePacked, attribute, value);
        }

        ANGLE_CAPTURE_EGL(SurfaceAttrib, true, thread, dpyPacked, surfacePacked, attribute, value,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_SwapInterval(EGLDisplay dpy, EGLint interval)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(SwapInterval, "dpy = 0x%016" PRIxPTR ", interval = %d",
                                    (uintptr_t)dpy, interval));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(SwapInterval, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, SwapInterval, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, interval);
            }
            else
            {
            }

            returnValue = SwapInterval(thread, dpyPacked, interval);
        }

        ANGLE_CAPTURE_EGL(SwapInterval, true, thread, dpyPacked, interval, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

// EGL 1.2
EGLBoolean EGLAPIENTRY EGL_BindAPI(EGLenum api)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(BindAPI, "api = 0x%X", api));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(BindAPI, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, BindAPI, nullptr, EGLBoolean, api);
            }
            else
            {
            }

            returnValue = BindAPI(thread, api);
        }

        ANGLE_CAPTURE_EGL(BindAPI, true, thread, api, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_CreatePbufferFromClientBuffer(EGLDisplay dpy,
                                                         EGLenum buftype,
                                                         EGLClientBuffer buffer,
                                                         EGLConfig config,
                                                         const EGLint *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            CreatePbufferFromClientBuffer,
            "dpy = 0x%016" PRIxPTR ", buftype = 0x%X, buffer = 0x%016" PRIxPTR
            ", config = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "",
            (uintptr_t)dpy, buftype, (uintptr_t)buffer, (uintptr_t)config, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreatePbufferFromClientBuffer, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreatePbufferFromClientBuffer,
                                   GetDisplayIfValid(dpyPacked), EGLSurface, dpyPacked, buftype,
                                   buffer, configPacked, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = CreatePbufferFromClientBuffer(thread, dpyPacked, buftype, buffer,
                                                        configPacked, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreatePbufferFromClientBuffer, true, thread, dpyPacked, buftype, buffer,
                          configPacked, attrib_listPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLenum EGLAPIENTRY EGL_QueryAPI()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLenum returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(QueryAPI, ""));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(QueryAPI, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, QueryAPI, nullptr, EGLenum);
            }
            else
            {
            }

            returnValue = QueryAPI(thread);
        }

        ANGLE_CAPTURE_EGL(QueryAPI, true, thread, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_ReleaseThread()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_AND_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(ReleaseThread, ""));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(ReleaseThread, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, ReleaseThread, nullptr, EGLBoolean);
            }
            else
            {
            }

            returnValue = ReleaseThread(thread);
        }

        ANGLE_CAPTURE_EGL(ReleaseThread, true, thread, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_WaitClient()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(WaitClient, ""));

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitClient, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, WaitClient, nullptr, EGLBoolean);
            }
            else
            {
            }

            returnValue = WaitClient(thread);
        }

        ANGLE_CAPTURE_EGL(WaitClient, true, thread, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

// EGL 1.4
EGLContext EGLAPIENTRY EGL_GetCurrentContext()
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLContext returnValue;

    ANGLE_UNSAFE_TODO(EGL_EVENT(GetCurrentContext, ""));

    if (IsEGLValidationEnabled())
    {
        ANGLE_EGL_VALIDATE(thread, GetCurrentContext, nullptr, EGLContext);
    }
    else
    {
    }

    returnValue = GetCurrentContext(thread);

    ANGLE_CAPTURE_EGL(GetCurrentContext, true, thread, returnValue);

    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

// EGL 1.5
EGLint EGLAPIENTRY EGL_ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLint returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            ClientWaitSync,
            "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d, timeout = %llu",
            (uintptr_t)dpy, (uintptr_t)sync, flags, static_cast<unsigned long long>(timeout)));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        egl::SyncID syncPacked  = PackParam<egl::SyncID>(sync);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(ClientWaitSync, thread, dpyPacked, flags);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, ClientWaitSync, GetDisplayIfValid(dpyPacked), EGLint,
                                   dpyPacked, syncPacked, flags, timeout);
            }
            else
            {
            }

            returnValue = ClientWaitSync(thread, dpyPacked, syncPacked, flags, timeout);
        }

        ANGLE_CAPTURE_EGL(ClientWaitSync, true, thread, dpyPacked, syncPacked, flags, timeout,
                          returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
    return returnValue;
}

EGLImage EGLAPIENTRY EGL_CreateImage(EGLDisplay dpy,
                                     EGLContext ctx,
                                     EGLenum target,
                                     EGLClientBuffer buffer,
                                     const EGLAttrib *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLImage returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            CreateImage,
            "dpy = 0x%016" PRIxPTR ", ctx = 0x%016" PRIxPTR
            ", target = 0x%X, buffer = 0x%016" PRIxPTR ", attrib_list = 0x%016" PRIxPTR "",
            (uintptr_t)dpy, (uintptr_t)ctx, target, (uintptr_t)buffer, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        gl::ContextID ctxPacked               = PackParam<gl::ContextID>(ctx);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreateImage, thread, dpyPacked, ctxPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreateImage, GetDisplayIfValid(dpyPacked), EGLImage,
                                   dpyPacked, ctxPacked, target, buffer, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue =
                CreateImage(thread, dpyPacked, ctxPacked, target, buffer, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreateImage, true, thread, dpyPacked, ctxPacked, target, buffer,
                          attrib_listPacked, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_CreatePlatformPixmapSurface(EGLDisplay dpy,
                                                       EGLConfig config,
                                                       void *native_pixmap,
                                                       const EGLAttrib *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            CreatePlatformPixmapSurface,
            "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", native_pixmap = 0x%016" PRIxPTR
            ", attrib_list = 0x%016" PRIxPTR "",
            (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_pixmap, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreatePlatformPixmapSurface, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreatePlatformPixmapSurface,
                                   GetDisplayIfValid(dpyPacked), EGLSurface, dpyPacked,
                                   configPacked, native_pixmap, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = CreatePlatformPixmapSurface(thread, dpyPacked, configPacked,
                                                      native_pixmap, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreatePlatformPixmapSurface, true, thread, dpyPacked, configPacked,
                          native_pixmap, attrib_listPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLSurface EGLAPIENTRY EGL_CreatePlatformWindowSurface(EGLDisplay dpy,
                                                       EGLConfig config,
                                                       void *native_window,
                                                       const EGLAttrib *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSurface returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            CreatePlatformWindowSurface,
            "dpy = 0x%016" PRIxPTR ", config = 0x%016" PRIxPTR ", native_window = 0x%016" PRIxPTR
            ", attrib_list = 0x%016" PRIxPTR "",
            (uintptr_t)dpy, (uintptr_t)config, (uintptr_t)native_window, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        egl::Config *configPacked             = PackParam<egl::Config *>(config);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreatePlatformWindowSurface, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreatePlatformWindowSurface,
                                   GetDisplayIfValid(dpyPacked), EGLSurface, dpyPacked,
                                   configPacked, native_window, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = CreatePlatformWindowSurface(thread, dpyPacked, configPacked,
                                                      native_window, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreatePlatformWindowSurface, true, thread, dpyPacked, configPacked,
                          native_window, attrib_listPacked, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);
    return returnValue;
}

EGLSync EGLAPIENTRY EGL_CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLSync returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(
            CreateSync, "dpy = 0x%016" PRIxPTR ", type = 0x%X, attrib_list = 0x%016" PRIxPTR "",
            (uintptr_t)dpy, type, (uintptr_t)attrib_list));

        egl::Display *dpyPacked               = PackParam<egl::Display *>(dpy);
        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(CreateSync, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, CreateSync, GetDisplayIfValid(dpyPacked), EGLSync,
                                   dpyPacked, type, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = CreateSync(thread, dpyPacked, type, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(CreateSync, true, thread, dpyPacked, type, attrib_listPacked,
                          returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_DestroyImage(EGLDisplay dpy, EGLImage image)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(DestroyImage,
                                    "dpy = 0x%016" PRIxPTR ", image = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)image));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        ImageID imagePacked     = PackParam<ImageID>(image);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(DestroyImage, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, DestroyImage, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, imagePacked);
            }
            else
            {
            }

            returnValue = DestroyImage(thread, dpyPacked, imagePacked);
        }

        ANGLE_CAPTURE_EGL(DestroyImage, true, thread, dpyPacked, imagePacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_DestroySync(EGLDisplay dpy, EGLSync sync)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(DestroySync,
                                    "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)sync));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        egl::SyncID syncPacked  = PackParam<egl::SyncID>(sync);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(DestroySync, thread, dpyPacked);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, DestroySync, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, syncPacked);
            }
            else
            {
            }

            returnValue = DestroySync(thread, dpyPacked, syncPacked);
        }

        ANGLE_CAPTURE_EGL(DestroySync, true, thread, dpyPacked, syncPacked, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
    return returnValue;
}

EGLDisplay EGLAPIENTRY EGL_GetPlatformDisplay(EGLenum platform,
                                              void *native_display,
                                              const EGLAttrib *attrib_list)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLDisplay returnValue;
    {
        ANGLE_SCOPED_GLOBAL_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(GetPlatformDisplay,
                                    "platform = 0x%X, native_display = 0x%016" PRIxPTR
                                    ", attrib_list = 0x%016" PRIxPTR "",
                                    platform, (uintptr_t)native_display, (uintptr_t)attrib_list));

        const AttributeMap &attrib_listPacked = PackParam<const AttributeMap &>(attrib_list);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetPlatformDisplay, thread);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, GetPlatformDisplay, nullptr, EGLDisplay, platform,
                                   native_display, attrib_listPacked);
            }
            else
            {
                attrib_listPacked.initializeWithoutValidation();
            }

            returnValue = GetPlatformDisplay(thread, platform, native_display, attrib_listPacked);
        }

        ANGLE_CAPTURE_EGL(GetPlatformDisplay, true, thread, platform, native_display,
                          attrib_listPacked, returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_GetSyncAttrib(EGLDisplay dpy,
                                         EGLSync sync,
                                         EGLint attribute,
                                         EGLAttrib *value)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(GetSyncAttrib,
                                    "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR
                                    ", attribute = %d, value = 0x%016" PRIxPTR "",
                                    (uintptr_t)dpy, (uintptr_t)sync, attribute, (uintptr_t)value));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        egl::SyncID syncPacked  = PackParam<egl::SyncID>(sync);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(GetSyncAttrib, thread, dpyPacked, attribute);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, GetSyncAttrib, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, syncPacked, attribute, value);
            }
            else
            {
            }

            returnValue = GetSyncAttrib(thread, dpyPacked, syncPacked, attribute, value);
        }

        ANGLE_CAPTURE_EGL(GetSyncAttrib, true, thread, dpyPacked, syncPacked, attribute, value,
                          returnValue);
    }
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    return returnValue;
}

EGLBoolean EGLAPIENTRY EGL_WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
{

    Thread *thread = egl::GetCurrentThread();
    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
    EGLBoolean returnValue;
    {
        ANGLE_SCOPED_GLOBAL_EGL_SYNC_LOCK();
        ANGLE_UNSAFE_TODO(EGL_EVENT(WaitSync,
                                    "dpy = 0x%016" PRIxPTR ", sync = 0x%016" PRIxPTR ", flags = %d",
                                    (uintptr_t)dpy, (uintptr_t)sync, flags));

        egl::Display *dpyPacked = PackParam<egl::Display *>(dpy);
        egl::SyncID syncPacked  = PackParam<egl::SyncID>(sync);

        {
            ANGLE_EGL_SCOPED_CONTEXT_LOCK(WaitSync, thread, dpyPacked, flags);
            if (IsEGLValidationEnabled())
            {
                ANGLE_EGL_VALIDATE(thread, WaitSync, GetDisplayIfValid(dpyPacked), EGLBoolean,
                                   dpyPacked, syncPacked, flags);
            }
            else
            {
            }

            returnValue = WaitSync(thread, dpyPacked, syncPacked, flags);
        }

        ANGLE_CAPTURE_EGL(WaitSync, true, thread, dpyPacked, syncPacked, flags, returnValue);
    }
    egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);
    return returnValue;
}

}  // extern "C"
