Edit

kc3-lang/angle/scripts/generate_entry_points.py

Branch :

  • Show log

    Commit

  • Author : John Plate
    Date : 2021-05-29 16:26:57
    Hash : baca10b7
    Message : CL: Remove object cache and fix multi-threading All CL front end objects used to be cached to be able to determine if an object has been created by the front end to check its validity. The validity is now checked with the existence of an intrinsic value (the dispatch table pointer), which is consistent with the patterns found in Mesa and clvk (though clvk uses a magic value). This allows the removal of all cached objects. The cached objects were stored with std::unique_ptr. These are now gone and all remaining pointers are now custom intrinsic reference count pointers. Also remove global lock which causes deadlocks, e.g. when CL API is called from a separate thread to unlock a blocking call with a user event. Most of the front end is constant and already thread-safe. The ref count is also thread-safe now (atomic). A few remaining locks will follow. Without the global lock it was now possible to make the API reentrant, and to remove the workaround with the Khronos ICD loader to skip ANGLE's OpenCL library. Bug: angleproject:6001 Change-Id: I7d3b52db9011a02cb7ea9ebdeb6e22c4c702ef5b Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2927395 Commit-Queue: John Plate <jplate@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Cody Northrop <cnorthrop@google.com>

  • scripts/generate_entry_points.py
  • #!/usr/bin/python3
    #
    # Copyright 2017 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.
    #
    # generate_entry_points.py:
    #   Generates the OpenGL bindings and entry point layers for ANGLE.
    #   NOTE: don't run this script directly. Run scripts/run_code_generation.py.
    
    import sys, os, pprint, json
    import registry_xml
    from registry_xml import apis, script_relative, strip_api_prefix
    
    # Paths
    CL_STUBS_HEADER_PATH = "../src/libGLESv2/cl_stubs_autogen.h"
    EGL_GET_LABELED_OBJECT_DATA_PATH = "../src/libGLESv2/egl_get_labeled_object_data.json"
    EGL_STUBS_HEADER_PATH = "../src/libGLESv2/egl_stubs_autogen.h"
    EGL_EXT_STUBS_HEADER_PATH = "../src/libGLESv2/egl_ext_stubs_autogen.h"
    
    # List of GLES1 extensions for which we don't need to add Context.h decls.
    GLES1_NO_CONTEXT_DECL_EXTENSIONS = [
        "GL_OES_framebuffer_object",
    ]
    
    # This is a list of exceptions for entry points which don't want to have
    # the EVENT macro. This is required for some debug marker entry points.
    NO_EVENT_MARKER_EXCEPTIONS_LIST = sorted([
        "glPushGroupMarkerEXT",
        "glPopGroupMarkerEXT",
        "glInsertEventMarkerEXT",
    ])
    
    # glRenderbufferStorageMultisampleEXT aliases glRenderbufferStorageMultisample on desktop GL, and is
    # marked as such in the registry.  However, that is not correct for GLES where this entry point
    # comes from GL_EXT_multisampled_render_to_texture which is never promoted to core GLES.
    ALIASING_EXCEPTIONS = [
        'glRenderbufferStorageMultisampleEXT',
        'renderbufferStorageMultisampleEXT',
    ]
    
    # These are the entry points which potentially are used first by an application
    # and require that the back ends are initialized before the front end is called.
    INIT_DICT = {
        "clGetPlatformIDs": "false",
        "clGetPlatformInfo": "false",
        "clGetDeviceIDs": "false",
        "clCreateContext": "false",
        "clCreateContextFromType": "false",
        "clIcdGetPlatformIDsKHR": "true",
    }
    
    # Strip these suffixes from Context entry point names. NV is excluded (for now).
    STRIP_SUFFIXES = ["ANDROID", "ANGLE", "EXT", "KHR", "OES", "CHROMIUM", "OVR"]
    
    TEMPLATE_ENTRY_POINT_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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_{annotation_lower}_autogen.h:
    //   Defines the {comment} entry points.
    
    #ifndef {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
    #define {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
    
    {includes}
    
    {entry_points}
    
    #endif  // {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
    """
    
    TEMPLATE_ENTRY_POINT_SOURCE = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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_{annotation_lower}_autogen.cpp:
    //   Defines the {comment} entry points.
    
    {includes}
    
    {entry_points}
    """
    
    TEMPLATE_ENTRY_POINTS_ENUM_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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_enum_autogen.h:
    //   Defines the {lib} entry points enumeration.
    
    #ifndef COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
    #define COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
    
    namespace angle
    {{
    enum class EntryPoint
    {{
    {entry_points_list}
    }};
    
    const char *GetEntryPointName(EntryPoint ep);
    }}  // namespace angle
    #endif  // COMMON_ENTRY_POINTS_ENUM_AUTOGEN_H_
    """
    
    TEMPLATE_ENTRY_POINTS_NAME_CASE = """\
            case EntryPoint::{enum}:
                return "{cmd}";"""
    
    TEMPLATE_ENTRY_POINTS_ENUM_SOURCE = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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_enum_autogen.cpp:
    //   Helper methods for the {lib} entry points enumeration.
    
    #include "common/entry_points_enum_autogen.h"
    
    #include "common/debug.h"
    
    namespace angle
    {{
    const char *GetEntryPointName(EntryPoint ep)
    {{
        switch (ep)
        {{
    {entry_points_name_cases}
            default:
                UNREACHABLE();
                return "error";
        }}
    }}
    }}  // namespace angle
    """
    
    TEMPLATE_LIB_ENTRY_POINT_SOURCE = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // {lib_name}_autogen.cpp: Implements the exported {lib_description} functions.
    
    {includes}
    extern "C" {{
    {entry_points}
    }} // extern "C"
    """
    
    TEMPLATE_ENTRY_POINT_DECL = """{angle_export}{return_type} {export_def} {name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params});"""
    
    TEMPLATE_GLES_ENTRY_POINT_NO_RETURN = """\
    void GL_APIENTRY GL_{name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params})
    {{
        Context *context = {context_getter};
        {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
    
        if ({valid_context_check})
        {{{assert_explicit_context}{packed_gl_enum_conversions}
            std::unique_lock<angle::GlobalMutex> shareContextLock = GetContextLock(context);
            bool isCallValid = (context->skipValidation() || Validate{name}({validate_params}));
            if (isCallValid)
            {{
                context->{name_lower_no_suffix}({internal_params});
            }}
            ANGLE_CAPTURE({name}, isCallValid, {validate_params});
        }}
        else
        {{
            {constext_lost_error_generator}
        }}
    }}
    """
    
    TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN = """\
    {return_type} GL_APIENTRY GL_{name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params})
    {{
        Context *context = {context_getter};
        {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
    
        {return_type} returnValue;
        if ({valid_context_check})
        {{{assert_explicit_context}{packed_gl_enum_conversions}
            std::unique_lock<angle::GlobalMutex> shareContextLock = GetContextLock(context);
            bool isCallValid = (context->skipValidation() || Validate{name}({validate_params}));
            if (isCallValid)
            {{
                returnValue = context->{name_lower_no_suffix}({internal_params});
            }}
            else
            {{
                returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
        }}
            ANGLE_CAPTURE({name}, isCallValid, {validate_params}, returnValue);
        }}
        else
        {{
            {constext_lost_error_generator}
            returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
        }}
        return returnValue;
    }}
    """
    
    TEMPLATE_EGL_ENTRY_POINT_NO_RETURN = """\
    void EGLAPIENTRY EGL_{name}({params})
    {{
        ANGLE_SCOPED_GLOBAL_LOCK();
        EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
    
        Thread *thread = egl::GetCurrentThread();
    
        {packed_gl_enum_conversions}
    
        ANGLE_EGL_VALIDATE_VOID(thread, {name}, {labeled_object}, {internal_params});
    
        {name}(thread{comma_if_needed}{internal_params});
    }}
    """
    
    TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN = """\
    {return_type} EGLAPIENTRY EGL_{name}({params})
    {{
        ANGLE_SCOPED_GLOBAL_LOCK();
        EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
    
        Thread *thread = egl::GetCurrentThread();
    
        {packed_gl_enum_conversions}
    
        ANGLE_EGL_VALIDATE(thread, {name}, {labeled_object}, {return_type}{comma_if_needed}{internal_params});
    
        return {name}(thread{comma_if_needed}{internal_params});
    }}
    """
    
    TEMPLATE_CL_ENTRY_POINT_NO_RETURN = """\
    void CL_API_CALL cl{name}({params})
    {{
        CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
    
        {packed_gl_enum_conversions}
    
        ANGLE_CL_VALIDATE_VOID({name}{comma_if_needed}{internal_params});
    
        {name}({internal_params});
    }}
    """
    
    TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR = """\
    cl_int CL_API_CALL cl{name}({params})
    {{{initialization}
        CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
    
        {packed_gl_enum_conversions}
    
        ANGLE_CL_VALIDATE_ERROR({name}{comma_if_needed}{internal_params});
    
        return {name}({internal_params});
    }}
    """
    
    TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET = """\
    {return_type} CL_API_CALL cl{name}({params})
    {{{initialization}
        CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
    
        {packed_gl_enum_conversions}
    
        ANGLE_CL_VALIDATE_ERRCODE_RET({name}{comma_if_needed}{internal_params});
    
        cl_int errorCode = CL_SUCCESS;
        {return_type} object = {name}({internal_params}, errorCode);
    
        ASSERT((errorCode == CL_SUCCESS) == (object != nullptr));
        if (errcode_ret != nullptr)
        {{
            *errcode_ret = errorCode;
        }}
        return object;
    }}
    """
    
    TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER = """\
    {return_type} CL_API_CALL cl{name}({params})
    {{{initialization}
        CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
    
        {packed_gl_enum_conversions}
    
        ANGLE_CL_VALIDATE_POINTER({name}{comma_if_needed}{internal_params});
    
        return {name}({internal_params});
    }}
    """
    
    TEMPLATE_CL_STUBS_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // Copyright 2021 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.
    //
    // {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
    
    #ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
    #define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
    
    #include "libANGLE/CLtypes.h"
    
    namespace cl
    {{
    {stubs}
    }}  // namespace cl
    #endif  // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
    """
    
    TEMPLATE_EGL_STUBS_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
    
    #ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
    #define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
    
    #include <EGL/egl.h>
    #include <EGL/eglext.h>
    
    #include "common/PackedEGLEnums_autogen.h"
    
    namespace gl
    {{
    class Context;
    }}  // namespace gl
    
    namespace egl
    {{
    class AttributeMap;
    class Device;
    class Display;
    class Image;
    class Stream;
    class Surface;
    class Sync;
    class Thread;
    struct Config;
    
    {stubs}
    }}  // namespace egl
    #endif  // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
    """
    
    CONTEXT_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // Context_{annotation_lower}_autogen.h: Creates a macro for interfaces in Context.
    
    #ifndef ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
    #define ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
    
    #define ANGLE_{annotation_upper}_CONTEXT_API \\
    {interface}
    
    #endif // ANGLE_CONTEXT_API_{version}_AUTOGEN_H_
    """
    
    CONTEXT_DECL_FORMAT = """    {return_type} {name_lower_no_suffix}({internal_params}){maybe_const}; \\"""
    
    TEMPLATE_CL_ENTRY_POINT_EXPORT = """\
    {return_type} CL_API_CALL cl{name}({params})
    {{
        return cl::GetDispatch().cl{name}({internal_params});
    }}
    """
    
    TEMPLATE_GL_ENTRY_POINT_EXPORT = """\
    {return_type} GL_APIENTRY gl{name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params})
    {{
        return GL_{name}{explicit_context_suffix}({explicit_context_internal_param}{explicit_context_comma}{internal_params});
    }}
    """
    
    TEMPLATE_EGL_ENTRY_POINT_EXPORT = """\
    {return_type} EGLAPIENTRY egl{name}({params})
    {{
        EnsureEGLLoaded();
        return EGL_{name}({internal_params});
    }}
    """
    
    TEMPLATE_GLEXT_EXPLICIT_CONTEXT_INC = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // gl{version}ext_explicit_context_autogen.inc:
    //   Function declarations for the EGL_ANGLE_explicit_context extension
    
    {function_pointers}
    #ifdef GL_GLEXT_PROTOTYPES
    {function_prototypes}
    #endif
    """
    
    TEMPLATE_GLEXT_FUNCTION_POINTER = """typedef {return_type}(GL_APIENTRYP PFN{name_upper}{explicit_context_suffix_upper}PROC)({explicit_context_param}{explicit_context_comma}{params});"""
    TEMPLATE_GLEXT_FUNCTION_PROTOTYPE = """{apicall} {return_type}GL_APIENTRY {name}{explicit_context_suffix}({explicit_context_param}{explicit_context_comma}{params});"""
    
    TEMPLATE_GL_VALIDATION_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // validation{annotation}_autogen.h:
    //   Validation functions for the OpenGL {comment} entry points.
    
    #ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    #define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    
    #include "common/PackedEnums.h"
    
    namespace gl
    {{
    class Context;
    
    {prototypes}
    }}  // namespace gl
    
    #endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    """
    
    TEMPLATE_CL_VALIDATION_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // Copyright 2021 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.
    //
    // validation{annotation}_autogen.h:
    //   Validation functions for the {comment} entry points.
    
    #ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    #define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    
    #include "libANGLE/validationCL.h"
    
    namespace cl
    {{
    {prototypes}
    }}  // namespace cl
    
    #endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    """
    
    TEMPLATE_EGL_VALIDATION_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // validation{annotation}_autogen.h:
    //   Validation functions for the {comment} entry points.
    
    #ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    #define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    
    #include "libANGLE/validationEGL.h"
    
    namespace egl
    {{
    {prototypes}
    }}  // namespace egl
    
    #endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
    """
    
    TEMPLATE_CAPTURE_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // capture_gles_{annotation_lower}_autogen.h:
    //   Capture functions for the OpenGL ES {comment} entry points.
    
    #ifndef LIBANGLE_CAPTURE_GLES_{annotation_upper}_AUTOGEN_H_
    #define LIBANGLE_CAPTURE_GLES_{annotation_upper}_AUTOGEN_H_
    
    #include "common/PackedEnums.h"
    #include "libANGLE/capture/FrameCapture.h"
    
    namespace gl
    {{
    {prototypes}
    }}  // namespace gl
    
    #endif  // LIBANGLE_CAPTURE_GLES_{annotation_upper}_AUTOGEN_H_
    """
    
    TEMPLATE_CAPTURE_SOURCE = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // capture_gles_{annotation_with_dash}_autogen.cpp:
    //   Capture functions for the OpenGL ES {comment} entry points.
    
    #include "libANGLE/capture/capture_gles_{annotation_with_dash}_autogen.h"
    
    #include "libANGLE/Context.h"
    #include "libANGLE/capture/FrameCapture.h"
    #include "libANGLE/capture/gl_enum_utils.h"
    #include "libANGLE/validation{annotation_no_dash}.h"
    
    using namespace angle;
    
    namespace gl
    {{
    {capture_methods}
    }}  // namespace gl
    """
    
    TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE = """
    CallCapture Capture{short_name}({params_with_type}, {return_value_type_original} returnValue)
    {{
        ParamBuffer paramBuffer;
    
        {parameter_captures}
    
        ParamCapture returnValueCapture("returnValue", ParamType::T{return_value_type_custom});
        InitParamValue(ParamType::T{return_value_type_custom}, returnValue, &returnValueCapture.value);
        paramBuffer.addReturnValue(std::move(returnValueCapture));
    
        return CallCapture(angle::EntryPoint::GL{short_name}, std::move(paramBuffer));
    }}
    """
    
    TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE = """
    CallCapture Capture{short_name}({params_with_type})
    {{
        ParamBuffer paramBuffer;
    
        {parameter_captures}
    
        return CallCapture(angle::EntryPoint::GL{short_name}, std::move(paramBuffer));
    }}
    """
    
    TEMPLATE_PARAMETER_CAPTURE_VALUE = """paramBuffer.addValueParam("{name}", ParamType::T{type}, {name});"""
    
    TEMPLATE_PARAMETER_CAPTURE_GL_ENUM = """paramBuffer.addEnumParam("{name}", GLenumGroup::{group}, ParamType::T{type}, {name});"""
    
    TEMPLATE_PARAMETER_CAPTURE_POINTER = """
        if (isCallValid)
        {{
            ParamCapture {name}Param("{name}", ParamType::T{type});
            InitParamValue(ParamType::T{type}, {name}, &{name}Param.value);
            {capture_name}({params}, &{name}Param);
            paramBuffer.addParam(std::move({name}Param));
        }}
        else
        {{
            ParamCapture {name}Param("{name}", ParamType::T{type});
            InitParamValue(ParamType::T{type}, static_cast<{cast_type}>(nullptr), &{name}Param.value);
            paramBuffer.addParam(std::move({name}Param));
        }}
    """
    
    TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC = """void {name}({params});"""
    
    TEMPLATE_CAPTURE_REPLAY_SOURCE = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // frame_capture_replay_autogen.cpp:
    //   Util function to dispatch captured GL calls through Context and replay them.
    
    #include "angle_gl.h"
    
    #include "common/debug.h"
    #include "common/debug.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Context.inl.h"
    #include "libANGLE/capture/FrameCapture.h"
    
    using namespace gl;
    
    namespace angle
    {{
    
    void FrameCapture::ReplayCall(gl::Context *context,
                                  ReplayContext *replayContext,
                                  const CallCapture &call)
    {{
        const ParamBuffer &params = call.params;
        switch (call.entryPoint)
        {{
            {call_replay_cases}
            default:
                UNREACHABLE();
        }}
    }}
    
    }}  // namespace angle
    
    """
    
    TEMPLATE_CAPTURE_REPLAY_CALL_CASE = """case angle::EntryPoint::GL{entry_point}:
        context->{context_call}({param_value_access});break;"""
    
    POINTER_FORMAT = "0x%016\" PRIxPTR \""
    UNSIGNED_LONG_LONG_FORMAT = "%llu"
    HEX_LONG_LONG_FORMAT = "0x%llX"
    
    FORMAT_DICT = {
        "GLbitfield": "%s",
        "GLboolean": "%s",
        "GLbyte": "%d",
        "GLclampx": "0x%X",
        "GLDEBUGPROC": POINTER_FORMAT,
        "GLDEBUGPROCKHR": POINTER_FORMAT,
        "GLdouble": "%f",
        "GLeglClientBufferEXT": POINTER_FORMAT,
        "GLeglImageOES": POINTER_FORMAT,
        "GLenum": "%s",
        "GLfixed": "0x%X",
        "GLfloat": "%f",
        "GLint": "%d",
        "GLintptr": UNSIGNED_LONG_LONG_FORMAT,
        "GLshort": "%d",
        "GLsizei": "%d",
        "GLsizeiptr": UNSIGNED_LONG_LONG_FORMAT,
        "GLsync": POINTER_FORMAT,
        "GLubyte": "%d",
        "GLuint": "%u",
        "GLuint64": UNSIGNED_LONG_LONG_FORMAT,
        "GLushort": "%u",
        "int": "%d",
        # EGL-specific types
        "EGLConfig": POINTER_FORMAT,
        "EGLContext": POINTER_FORMAT,
        "EGLDisplay": POINTER_FORMAT,
        "EGLSurface": POINTER_FORMAT,
        "EGLSync": POINTER_FORMAT,
        "EGLNativeDisplayType": POINTER_FORMAT,
        "EGLNativePixmapType": POINTER_FORMAT,
        "EGLNativeWindowType": POINTER_FORMAT,
        "EGLClientBuffer": POINTER_FORMAT,
        "EGLenum": "0x%X",
        "EGLint": "%d",
        "EGLImage": POINTER_FORMAT,
        "EGLTime": UNSIGNED_LONG_LONG_FORMAT,
        "EGLGetBlobFuncANDROID": POINTER_FORMAT,
        "EGLSetBlobFuncANDROID": POINTER_FORMAT,
        "EGLuint64KHR": UNSIGNED_LONG_LONG_FORMAT,
        "EGLSyncKHR": POINTER_FORMAT,
        "EGLnsecsANDROID": UNSIGNED_LONG_LONG_FORMAT,
        "EGLDeviceEXT": POINTER_FORMAT,
        "EGLDEBUGPROCKHR": POINTER_FORMAT,
        "EGLObjectKHR": POINTER_FORMAT,
        "EGLLabelKHR": POINTER_FORMAT,
        "EGLTimeKHR": UNSIGNED_LONG_LONG_FORMAT,
        "EGLImageKHR": POINTER_FORMAT,
        "EGLStreamKHR": POINTER_FORMAT,
        "EGLFrameTokenANGLE": HEX_LONG_LONG_FORMAT,
        # WGL-specific types
        "BOOL": "%u",
        "DWORD": POINTER_FORMAT,
        "FLOAT": "%f",
        "HDC": POINTER_FORMAT,
        "HENHMETAFILE": POINTER_FORMAT,
        "HGLRC": POINTER_FORMAT,
        "LPCSTR": POINTER_FORMAT,
        "LPGLYPHMETRICSFLOAT": POINTER_FORMAT,
        "UINT": "%u",
        # CL-specific types
        "size_t": "%zu",
        "cl_char": "%hhd",
        "cl_uchar": "%hhu",
        "cl_short": "%hd",
        "cl_ushort": "%hu",
        "cl_int": "%d",
        "cl_uint": "%u",
        "cl_long": "%lld",
        "cl_ulong": "%llu",
        "cl_half": "%hu",
        "cl_float": "%f",
        "cl_double": "%f",
        "cl_platform_id": POINTER_FORMAT,
        "cl_device_id": POINTER_FORMAT,
        "cl_context": POINTER_FORMAT,
        "cl_command_queue": POINTER_FORMAT,
        "cl_mem": POINTER_FORMAT,
        "cl_program": POINTER_FORMAT,
        "cl_kernel": POINTER_FORMAT,
        "cl_event": POINTER_FORMAT,
        "cl_sampler": POINTER_FORMAT,
        "cl_bool": "%u",
        "cl_bitfield": "%llu",
        "cl_properties": "%llu",
        "cl_device_type": "%llu",
        "cl_platform_info": "%u",
        "cl_device_info": "%u",
        "cl_device_fp_config": "%llu",
        "cl_device_mem_cache_type": "%u",
        "cl_device_local_mem_type": "%u",
        "cl_device_exec_capabilities": "%llu",
        "cl_device_svm_capabilities": "%llu",
        "cl_command_queue_properties": "%llu",
        "cl_device_partition_property": "%zu",
        "cl_device_affinity_domain": "%llu",
        "cl_context_properties": "%zu",
        "cl_context_info": "%u",
        "cl_queue_properties": "%llu",
        "cl_command_queue_info": "%u",
        "cl_channel_order": "%u",
        "cl_channel_type": "%u",
        "cl_mem_flags": "%llu",
        "cl_svm_mem_flags": "%llu",
        "cl_mem_object_type": "%u",
        "cl_mem_info": "%u",
        "cl_mem_migration_flags": "%llu",
        "cl_mem_properties": "%llu",
        "cl_image_info": "%u",
        "cl_buffer_create_type": "%u",
        "cl_addressing_mode": "%u",
        "cl_filter_mode": "%u",
        "cl_sampler_info": "%u",
        "cl_map_flags": "%llu",
        "cl_pipe_properties": "%zu",
        "cl_pipe_info": "%u",
        "cl_program_info": "%u",
        "cl_program_build_info": "%u",
        "cl_program_binary_type": "%u",
        "cl_build_status": "%d",
        "cl_kernel_info": "%u",
        "cl_kernel_arg_info": "%u",
        "cl_kernel_arg_address_qualifier": "%u",
        "cl_kernel_arg_access_qualifier": "%u",
        "cl_kernel_arg_type_qualifier": "%llu",
        "cl_kernel_work_group_info": "%u",
        "cl_kernel_sub_group_info": "%u",
        "cl_event_info": "%u",
        "cl_command_type": "%u",
        "cl_profiling_info": "%u",
        "cl_sampler_properties": "%llu",
        "cl_kernel_exec_info": "%u",
        "cl_device_atomic_capabilities": "%llu",
        "cl_khronos_vendor_id": "%u",
        "cl_version": "%u",
        "cl_device_device_enqueue_capabilities": "%llu",
    }
    
    TEMPLATE_HEADER_INCLUDES = """\
    #include <GLES{major}/gl{major}{minor}.h>
    #include <export.h>"""
    
    TEMPLATE_SOURCES_INCLUDES = """\
    #include "libGLESv2/entry_points_{header_version}_autogen.h"
    
    #include "common/entry_points_enum_autogen.h"
    #include "libANGLE/Context.h"
    #include "libANGLE/Context.inl.h"
    #include "libANGLE/capture/capture_{header_version}_autogen.h"
    #include "libANGLE/capture/gl_enum_utils.h"
    #include "libANGLE/validation{validation_header_version}.h"
    #include "libANGLE/entry_points_utils.h"
    #include "libGLESv2/global_state.h"
    
    using namespace gl;
    """
    
    GLES_EXT_HEADER_INCLUDES = TEMPLATE_HEADER_INCLUDES.format(
        major="", minor="") + """
    #include <GLES/glext.h>
    #include <GLES2/gl2.h>
    #include <GLES2/gl2ext.h>
    #include <GLES3/gl32.h>
    """
    
    GLES_EXT_SOURCE_INCLUDES = TEMPLATE_SOURCES_INCLUDES.format(
        header_version="gles_ext", validation_header_version="ESEXT") + """
    #include "libANGLE/capture/capture_gles_1_0_autogen.h"
    #include "libANGLE/capture/capture_gles_2_0_autogen.h"
    #include "libANGLE/capture/capture_gles_3_0_autogen.h"
    #include "libANGLE/capture/capture_gles_3_1_autogen.h"
    #include "libANGLE/capture/capture_gles_3_2_autogen.h"
    #include "libANGLE/validationES1.h"
    #include "libANGLE/validationES2.h"
    #include "libANGLE/validationES3.h"
    #include "libANGLE/validationES31.h"
    #include "libANGLE/validationES32.h"
    
    using namespace gl;
    """
    
    DESKTOP_GL_HEADER_INCLUDES = """\
    #include <export.h>
    #include "angle_gl.h"
    """
    
    TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES = """\
    #include "libGL/entry_points_{}_autogen.h"
    
    #include "libANGLE/Context.h"
    #include "libANGLE/Context.inl.h"
    #include "libANGLE/capture/gl_enum_utils.h"
    #include "libANGLE/validationEGL.h"
    #include "libANGLE/validationES.h"
    #include "libANGLE/validationES1.h"
    #include "libANGLE/validationES2.h"
    #include "libANGLE/validationES3.h"
    #include "libANGLE/validationES31.h"
    #include "libANGLE/validationES32.h"
    #include "libANGLE/validationESEXT.h"
    #include "libANGLE/validationGL{}_autogen.h"
    #include "libANGLE/entry_points_utils.h"
    #include "libGLESv2/global_state.h"
    
    using namespace gl;
    """
    
    EGL_HEADER_INCLUDES = """\
    #include <EGL/egl.h>
    #include <export.h>
    """
    
    EGL_SOURCE_INCLUDES = """\
    #include "libGLESv2/entry_points_egl_autogen.h"
    
    #include "libANGLE/entry_points_utils.h"
    #include "libANGLE/validationEGL_autogen.h"
    #include "libGLESv2/egl_stubs_autogen.h"
    #include "libGLESv2/global_state.h"
    
    using namespace egl;
    """
    
    EGL_EXT_HEADER_INCLUDES = """\
    #include <EGL/egl.h>
    #include <EGL/eglext.h>
    #include <export.h>
    """
    
    EGL_EXT_SOURCE_INCLUDES = """\
    #include "libGLESv2/entry_points_egl_ext_autogen.h"
    
    #include "libANGLE/entry_points_utils.h"
    #include "libANGLE/validationEGL_autogen.h"
    #include "libGLESv2/egl_ext_stubs_autogen.h"
    #include "libGLESv2/global_state.h"
    
    using namespace egl;
    """
    
    LIBCL_EXPORT_INCLUDES = """
    #include "libOpenCL/dispatch.h"
    """
    
    LIBGLESV2_EXPORT_INCLUDES = """
    #include "angle_gl.h"
    
    #include "libGLESv2/entry_points_gles_1_0_autogen.h"
    #include "libGLESv2/entry_points_gles_2_0_autogen.h"
    #include "libGLESv2/entry_points_gles_3_0_autogen.h"
    #include "libGLESv2/entry_points_gles_3_1_autogen.h"
    #include "libGLESv2/entry_points_gles_3_2_autogen.h"
    #include "libGLESv2/entry_points_gles_ext_autogen.h"
    
    #include "common/event_tracer.h"
    """
    
    LIBGL_EXPORT_INCLUDES = """
    #include "angle_gl.h"
    
    #include "libGL/entry_points_gl_1_autogen.h"
    #include "libGL/entry_points_gl_2_autogen.h"
    #include "libGL/entry_points_gl_3_autogen.h"
    #include "libGL/entry_points_gl_4_autogen.h"
    
    #include "common/event_tracer.h"
    """
    
    LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE = """
    #include "anglebase/no_destructor.h"
    #include "common/system_utils.h"
    
    #include <memory>
    
    #if defined(ANGLE_USE_EGL_LOADER)
    #    include "libEGL/egl_loader_autogen.h"
    #else
    #    include "libGLESv2/entry_points_egl_autogen.h"
    #    include "libGLESv2/entry_points_egl_ext_autogen.h"
    #endif  // defined(ANGLE_USE_EGL_LOADER)
    
    namespace
    {
    #if defined(ANGLE_USE_EGL_LOADER)
    bool gLoaded = false;
    
    std::unique_ptr<angle::Library> &EntryPointsLib()
    {
        static angle::base::NoDestructor<std::unique_ptr<angle::Library>> sEntryPointsLib;
        return *sEntryPointsLib;
    }
    
    angle::GenericProc KHRONOS_APIENTRY GlobalLoad(const char *symbol)
    {
        return reinterpret_cast<angle::GenericProc>(EntryPointsLib()->getSymbol(symbol));
    }
    
    void EnsureEGLLoaded()
    {
        if (gLoaded)
        {
            return;
        }
    
        EntryPointsLib().reset(
            angle::OpenSharedLibrary(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ApplicationDir));
        angle::LoadEGL_EGL(GlobalLoad);
        if (!EGL_GetPlatformDisplay)
        {
            fprintf(stderr, "Error loading EGL entry points.\\n");
        }
        else
        {
            gLoaded = true;
        }
    }
    #else
    void EnsureEGLLoaded() {}
    #endif  // defined(ANGLE_USE_EGL_LOADER)
    }  // anonymous namespace
    """
    
    LIBCL_HEADER_INCLUDES = """\
    #include "angle_cl.h"
    """
    
    LIBCL_SOURCE_INCLUDES = """\
    #include "libGLESv2/entry_points_cl_autogen.h"
    
    #include "libANGLE/validationCL_autogen.h"
    #include "libGLESv2/cl_stubs_autogen.h"
    #include "libGLESv2/entry_points_cl_utils.h"
    """
    
    TEMPLATE_EVENT_COMMENT = """\
        // Don't run the EVENT() macro on the EXT_debug_marker entry points.
        // It can interfere with the debug events being set by the caller.
        // """
    
    TEMPLATE_CAPTURE_PROTO = "angle::CallCapture Capture%s(%s);"
    
    TEMPLATE_VALIDATION_PROTO = "%s Validate%s(%s);"
    
    TEMPLATE_WINDOWS_DEF_FILE = """\
    ; GENERATED FILE - DO NOT EDIT.
    ; Generated by {script_name} using data from {data_source_name}.
    ;
    ; 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.
    LIBRARY {lib}
    EXPORTS
    {exports}
    """
    
    TEMPLATE_FRAME_CAPTURE_UTILS_HEADER = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // frame_capture_utils_autogen.h:
    //   ANGLE Frame capture types and helper functions.
    
    #ifndef LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
    #define LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
    
    #include "common/PackedEnums.h"
    
    namespace angle
    {{
    enum class ParamType
    {{
        {param_types}
    }};
    
    constexpr uint32_t kParamTypeCount = {param_type_count};
    
    union ParamValue
    {{
        {param_union_values}
    }};
    
    template <ParamType PType, typename T>
    T GetParamVal(const ParamValue &value);
    
    {get_param_val_specializations}
    
    template <ParamType PType, typename T>
    T GetParamVal(const ParamValue &value)
    {{
        UNREACHABLE();
        return T();
    }}
    
    template <typename T>
    T AccessParamValue(ParamType paramType, const ParamValue &value)
    {{
        switch (paramType)
        {{
    {access_param_value_cases}
        }}
    }}
    
    template <ParamType PType, typename T>
    void SetParamVal(T valueIn, ParamValue *valueOut);
    
    {set_param_val_specializations}
    
    template <ParamType PType, typename T>
    void SetParamVal(T valueIn, ParamValue *valueOut)
    {{
        UNREACHABLE();
    }}
    
    template <typename T>
    void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut)
    {{
        switch (paramType)
        {{
    {init_param_value_cases}
        }}
    }}
    
    struct CallCapture;
    struct ParamCapture;
    
    void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param);
    const char *ParamTypeToString(ParamType paramType);
    
    enum class ResourceIDType
    {{
        {resource_id_types}
    }};
    
    ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType);
    const char *GetResourceIDTypeName(ResourceIDType resourceIDType);
    }}  // namespace angle
    
    #endif  // LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
    """
    
    TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE = """\
    // GENERATED FILE - DO NOT EDIT.
    // Generated by {script_name} using data from {data_source_name}.
    //
    // 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.
    //
    // frame_capture_utils_autogen.cpp:
    //   ANGLE Frame capture types and helper functions.
    
    #include "libANGLE/capture/frame_capture_utils_autogen.h"
    
    #include "libANGLE/capture/FrameCapture.h"
    
    namespace angle
    {{
    void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param)
    {{
        switch (param.type)
        {{
    {write_param_type_to_stream_cases}
            default:
                os << "unknown";
                break;
        }}
    }}
    
    const char *ParamTypeToString(ParamType paramType)
    {{
        switch (paramType)
        {{
    {param_type_to_string_cases}
            default:
                UNREACHABLE();
                return "unknown";
        }}
    }}
    
    ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType)
    {{
        switch (paramType)
        {{
    {param_type_resource_id_cases}
            default:
                return ResourceIDType::InvalidEnum;
        }}
    }}
    
    const char *GetResourceIDTypeName(ResourceIDType resourceIDType)
    {{
        switch (resourceIDType)
        {{
    {resource_id_type_name_cases}
            default:
                UNREACHABLE();
                return "GetResourceIDTypeName error";
        }}
    }}
    }}  // namespace angle
    """
    
    TEMPLATE_GET_PARAM_VAL_SPECIALIZATION = """\
    template <>
    inline {type} GetParamVal<ParamType::T{enum}, {type}>(const ParamValue &value)
    {{
        return value.{union_name};
    }}"""
    
    TEMPLATE_ACCESS_PARAM_VALUE_CASE = """\
            case ParamType::T{enum}:
                return GetParamVal<ParamType::T{enum}, T>(value);"""
    
    TEMPLATE_SET_PARAM_VAL_SPECIALIZATION = """\
    template <>
    inline void SetParamVal<ParamType::T{enum}>({type} valueIn, ParamValue *valueOut)
    {{
        valueOut->{union_name} = valueIn;
    }}"""
    
    TEMPLATE_INIT_PARAM_VALUE_CASE = """\
            case ParamType::T{enum}:
                SetParamVal<ParamType::T{enum}>(valueIn, valueOut);
                break;"""
    
    TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE = """\
            case ParamType::T{enum_in}:
                WriteParamValueReplay<ParamType::T{enum_out}>(os, call, param.value.{union_name});
                break;"""
    
    TEMPLATE_PARAM_TYPE_TO_STRING_CASE = """\
            case ParamType::T{enum}:
                return "{type}";"""
    
    TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE = """\
            case ParamType::T{enum}:
                return ResourceIDType::{resource_id_type};"""
    
    TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE = """\
            case ResourceIDType::{resource_id_type}:
                return "{resource_id_type}";"""
    
    CL_PACKED_TYPES = {
        # Enums
        "cl_platform_info": "PlatformInfo",
        "cl_device_info": "DeviceInfo",
        "cl_context_info": "ContextInfo",
        "cl_command_queue_info": "CommandQueueInfo",
        "cl_mem_object_type": "MemObjectType",
        "cl_mem_info": "MemInfo",
        "cl_image_info": "ImageInfo",
        "cl_pipe_info": "PipeInfo",
        "cl_addressing_mode": "AddressingMode",
        "cl_filter_mode": "FilterMode",
        "cl_sampler_info": "SamplerInfo",
        "cl_program_info": "ProgramInfo",
        "cl_program_build_info": "ProgramBuildInfo",
        "cl_kernel_info": "KernelInfo",
        "cl_kernel_arg_info": "KernelArgInfo",
        "cl_kernel_work_group_info": "KernelWorkGroupInfo",
        "cl_kernel_sub_group_info": "KernelSubGroupInfo",
        "cl_kernel_exec_info": "KernelExecInfo",
        "cl_event_info": "EventInfo",
        "cl_profiling_info": "ProfilingInfo",
        # Bit fields
        "cl_device_type": "DeviceType",
        "cl_device_fp_config": "DeviceFpConfig",
        "cl_device_exec_capabilities": "DeviceExecCapabilities",
        "cl_device_svm_capabilities": "DeviceSvmCapabilities",
        "cl_command_queue_properties": "CommandQueueProperties",
        "cl_device_affinity_domain": "DeviceAffinityDomain",
        "cl_mem_flags": "MemFlags",
        "cl_svm_mem_flags": "SVM_MemFlags",
        "cl_mem_migration_flags": "MemMigrationFlags",
        "cl_map_flags": "MapFlags",
        "cl_kernel_arg_type_qualifier": "KernelArgTypeQualifier",
        "cl_device_atomic_capabilities": "DeviceAtomicCapabilities",
        "cl_device_device_enqueue_capabilities": "DeviceEnqueueCapabilities",
    }
    
    EGL_PACKED_TYPES = {
        "EGLContext": "gl::Context *",
        "EGLConfig": "Config *",
        "EGLDeviceEXT": "Device *",
        # Needs an explicit namespace to avoid an X11 namespace collision.
        "EGLDisplay": "egl::Display *",
        "EGLImage": "Image *",
        "EGLImageKHR": "Image *",
        "EGLStreamKHR": "Stream *",
        "EGLSurface": "Surface *",
        "EGLSync": "Sync *",
        "EGLSyncKHR": "Sync *",
    }
    
    
    def is_aliasing_excepted(api, cmd_name):
        return api == apis.GLES and cmd_name in ALIASING_EXCEPTIONS
    
    
    def entry_point_export(api):
        if api == apis.CL:
            return ""
        return "ANGLE_EXPORT "
    
    
    def entry_point_prefix(api):
        if api == apis.CL:
            return "cl"
        if api == apis.GLES:
            return "GL_"
        return api + "_"
    
    
    def get_api_entry_def(api):
        if api == apis.EGL:
            return "EGLAPIENTRY"
        elif api == apis.CL:
            return "CL_API_CALL"
        else:
            return "GL_APIENTRY"
    
    
    def get_stubs_header_template(api):
        if api == apis.CL:
            return TEMPLATE_CL_STUBS_HEADER
        elif api == apis.EGL:
            return TEMPLATE_EGL_STUBS_HEADER
        else:
            return ""
    
    
    def format_entry_point_decl(api, cmd_name, proto, params, is_explicit_context):
        comma_if_needed = ", " if len(params) > 0 else ""
        stripped = strip_api_prefix(cmd_name)
        return TEMPLATE_ENTRY_POINT_DECL.format(
            angle_export=entry_point_export(api),
            export_def=get_api_entry_def(api),
            name="%s%s" % (entry_point_prefix(api), stripped),
            return_type=proto[:-len(cmd_name)].strip(),
            params=", ".join(params),
            comma_if_needed=comma_if_needed,
            explicit_context_suffix="ContextANGLE" if is_explicit_context else "",
            explicit_context_param="GLeglContext ctx" if is_explicit_context else "",
            explicit_context_comma=", " if is_explicit_context and len(params) > 0 else "")
    
    
    # Returns index range of identifier in function parameter
    def find_name_range(param):
    
        def is_allowed_in_identifier(char):
            return char.isalpha() or char.isdigit() or char == "_"
    
        # If type is a function declaration, only search in first parentheses
        left_paren = param.find("(")
        if left_paren >= 0:
            min = left_paren + 1
            end = param.index(")")
        else:
            min = 0
            end = len(param)
    
        # Find last identifier in search range
        while end > min and not is_allowed_in_identifier(param[end - 1]):
            end -= 1
        if end == min:
            raise ValueError
        start = end - 1
        while start > min and is_allowed_in_identifier(param[start - 1]):
            start -= 1
        return start, end
    
    
    def just_the_type(param):
        start, end = find_name_range(param)
        return param[:start].strip() + param[end:].strip()
    
    
    def just_the_name(param):
        start, end = find_name_range(param)
        return param[start:end]
    
    
    def make_param(param_type, param_name):
    
        def insert_name(param_type, param_name, pos):
            return param_type[:pos] + " " + param_name + param_type[pos:]
    
        # If type is a function declaration, insert identifier before first closing parentheses
        left_paren = param_type.find("(")
        if left_paren >= 0:
            right_paren = param_type.index(")")
            return insert_name(param_type, param_name, right_paren)
    
        # If type is an array declaration, insert identifier before brackets
        brackets = param_type.find("[")
        if brackets >= 0:
            return insert_name(param_type, param_name, brackets)
    
        # Otherwise just append identifier
        return param_type + " " + param_name
    
    
    def just_the_type_packed(param, entry):
        name = just_the_name(param)
        if name in entry:
            return entry[name]
        else:
            return just_the_type(param)
    
    
    def just_the_name_packed(param, reserved_set):
        name = just_the_name(param)
        if name in reserved_set:
            return name + 'Packed'
        else:
            return name
    
    
    def is_unsigned_long_format(fmt):
        return fmt == UNSIGNED_LONG_LONG_FORMAT or fmt == HEX_LONG_LONG_FORMAT
    
    
    def param_print_argument(command_node, param):
        name_only = just_the_name(param)
        type_only = just_the_type(param)
    
        if "*" not in param and type_only not in FORMAT_DICT:
            print(" ".join(param))
            raise Exception("Missing '%s %s' from '%s' entry point" %
                            (type_only, name_only, registry_xml.get_cmd_name(command_node)))
    
        if "*" in param or FORMAT_DICT[type_only] == POINTER_FORMAT:
            return "(uintptr_t)%s" % name_only
    
        if is_unsigned_long_format(FORMAT_DICT[type_only]):
            return "static_cast<unsigned long long>(%s)" % name_only
    
        if type_only == "GLboolean":
            return "GLbooleanToString(%s)" % name_only
    
        if type_only == "GLbitfield":
            group_name = find_gl_enum_group_in_command(command_node, name_only)
            return "GLbitfieldToString(GLenumGroup::%s, %s).c_str()" % (group_name, name_only)
    
        if type_only == "GLenum":
            group_name = find_gl_enum_group_in_command(command_node, name_only)
            return "GLenumToString(GLenumGroup::%s, %s)" % (group_name, name_only)
    
        return name_only
    
    
    def param_format_string(param):
        if "*" in param:
            return just_the_name(param) + " = 0x%016\" PRIxPTR \""
        else:
            type_only = just_the_type(param)
            if type_only not in FORMAT_DICT:
                raise Exception(type_only + " is not a known type in 'FORMAT_DICT'")
    
            return just_the_name(param) + " = " + FORMAT_DICT[type_only]
    
    
    def is_context_lost_acceptable_cmd(cmd_name):
        lost_context_acceptable_cmds = [
            "glGetError",
            "glGetSync",
            "glGetQueryObjecti",
            "glGetProgramiv",
            "glGetGraphicsResetStatus",
            "glGetShaderiv",
        ]
    
        for context_lost_entry_pont in lost_context_acceptable_cmds:
            if cmd_name.startswith(context_lost_entry_pont):
                return True
        return False
    
    
    def get_context_getter_function(cmd_name, is_explicit_context):
        if is_explicit_context:
            return "static_cast<gl::Context *>(ctx)"
    
        if is_context_lost_acceptable_cmd(cmd_name):
            return "GetGlobalContext()"
    
        return "GetValidGlobalContext()"
    
    
    def get_valid_context_check(cmd_name, is_explicit_context):
        if is_explicit_context:
            if is_context_lost_acceptable_cmd(cmd_name):
                return "context"
            else:
                return "context && !context->isContextLost()"
    
        return "context"
    
    
    def get_constext_lost_error_generator(cmd_name, is_explicit_context):
        # Don't generate context lost errors on commands that accept lost contexts
        if is_context_lost_acceptable_cmd(cmd_name):
            return ""
    
        if is_explicit_context:
            return "GenerateContextLostErrorOnContext(context);"
        else:
            return "GenerateContextLostErrorOnCurrentGlobalContext();"
    
    
    def strip_suffix(api, name):
        # For commands where aliasing is excepted, keep the suffix
        if is_aliasing_excepted(api, name):
            return name
    
        for suffix in STRIP_SUFFIXES:
            if name.endswith(suffix):
                name = name[0:-len(suffix)]
        return name
    
    
    def find_gl_enum_group_in_command(command_node, param_name):
        group_name = None
        for param_node in command_node.findall('./param'):
            if param_node.find('./name').text == param_name:
                group_name = param_node.attrib.get('group', None)
                break
    
        if group_name is None or group_name in registry_xml.unsupported_enum_group_names:
            group_name = registry_xml.default_enum_group_name
    
        return group_name
    
    
    def get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types, params):
        # Always strip the suffix when querying packed enums.
        result = cmd_packed_gl_enums.get(strip_suffix(api, cmd_name), {})
        for param in params:
            param_type = just_the_type(param)
            if param_type in packed_param_types:
                result[just_the_name(param)] = packed_param_types[param_type]
        return result
    
    
    def get_def_template(api, return_type, has_errcode_ret):
        if return_type == "void":
            if api == apis.EGL:
                return TEMPLATE_EGL_ENTRY_POINT_NO_RETURN
            elif api == apis.CL:
                return TEMPLATE_CL_ENTRY_POINT_NO_RETURN
            else:
                return TEMPLATE_GLES_ENTRY_POINT_NO_RETURN
        elif return_type == "cl_int":
            return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR
        else:
            if api == apis.EGL:
                return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN
            elif api == apis.CL:
                if has_errcode_ret:
                    return TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET
                else:
                    return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER
            else:
                return TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN
    
    
    def format_entry_point_def(api, command_node, cmd_name, proto, params, is_explicit_context,
                               cmd_packed_enums, packed_param_types, ep_to_object):
        packed_enums = get_packed_enums(api, cmd_packed_enums, cmd_name, packed_param_types, params)
        internal_params = [just_the_name_packed(param, packed_enums) for param in params]
        if internal_params and internal_params[-1] == "errcode_ret":
            internal_params.pop()
            has_errcode_ret = True
        else:
            has_errcode_ret = False
        packed_gl_enum_conversions = []
        for param in params:
            name = just_the_name(param)
            if name in packed_enums:
                internal_name = name + "Packed"
                internal_type = packed_enums[name]
                packed_gl_enum_conversions += [
                    "\n        " + internal_type + " " + internal_name + " = PackParam<" +
                    internal_type + ">(" + name + ");"
                ]
    
        pass_params = [param_print_argument(command_node, param) for param in params]
        format_params = [param_format_string(param) for param in params]
        return_type = proto[:-len(cmd_name)].strip()
        initialization = "InitBackEnds(%s);\n" % INIT_DICT[cmd_name] if cmd_name in INIT_DICT else ""
        event_comment = TEMPLATE_EVENT_COMMENT if cmd_name in NO_EVENT_MARKER_EXCEPTIONS_LIST else ""
        name_lower_no_suffix = strip_suffix(api, cmd_name[2:3].lower() + cmd_name[3:])
    
        format_params = {
            "name":
                strip_api_prefix(cmd_name),
            "name_lower_no_suffix":
                name_lower_no_suffix,
            "return_type":
                return_type,
            "params":
                ", ".join(params),
            "internal_params":
                ", ".join(internal_params),
            "initialization":
                initialization,
            "packed_gl_enum_conversions":
                "".join(packed_gl_enum_conversions),
            "pass_params":
                ", ".join(pass_params),
            "comma_if_needed":
                ", " if len(params) > 0 else "",
            "validate_params":
                ", ".join(["context"] + internal_params),
            "format_params":
                ", ".join(format_params),
            "context_getter":
                get_context_getter_function(cmd_name, is_explicit_context),
            "valid_context_check":
                get_valid_context_check(cmd_name, is_explicit_context),
            "constext_lost_error_generator":
                get_constext_lost_error_generator(cmd_name, is_explicit_context),
            "event_comment":
                event_comment,
            "explicit_context_suffix":
                "ContextANGLE" if is_explicit_context else "",
            "explicit_context_param":
                "GLeglContext ctx" if is_explicit_context else "",
            "explicit_context_comma":
                ", " if is_explicit_context and len(params) > 0 else "",
            "assert_explicit_context":
                "\nASSERT(context == GetValidGlobalContext());" if is_explicit_context else "",
            "labeled_object":
                get_egl_entry_point_labeled_object(ep_to_object, cmd_name, params, packed_enums)
        }
    
        template = get_def_template(api, return_type, has_errcode_ret)
        return template.format(**format_params)
    
    
    def get_capture_param_type_name(param_type):
    
        pointer_count = param_type.count("*")
        is_const = "const" in param_type.split()
    
        param_type = param_type.replace("*", "").strip()
        param_type = " ".join([param for param in param_type.split() if param != "const"])
    
        if is_const:
            param_type += "Const"
        for x in range(pointer_count):
            param_type += "Pointer"
    
        return param_type
    
    
    def format_capture_method(api, command, cmd_name, proto, params, all_param_types,
                              capture_pointer_funcs, cmd_packed_gl_enums, packed_param_types):
    
        packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
                                           params)
    
        params_with_type = get_internal_params(api, cmd_name,
                                               ["const State &glState", "bool isCallValid"] + params,
                                               cmd_packed_gl_enums, packed_param_types)
        params_just_name = ", ".join(
            ["glState", "isCallValid"] +
            [just_the_name_packed(param, packed_gl_enums) for param in params])
    
        parameter_captures = []
        for param in params:
    
            param_name = just_the_name_packed(param, packed_gl_enums)
            param_type = just_the_type_packed(param, packed_gl_enums).strip()
            pointer_count = param_type.count("*")
            capture_param_type = get_capture_param_type_name(param_type)
    
            if pointer_count > 0:
                params = params_just_name
                capture_name = "Capture%s_%s" % (strip_api_prefix(cmd_name), param_name)
                capture = TEMPLATE_PARAMETER_CAPTURE_POINTER.format(
                    name=param_name,
                    type=capture_param_type,
                    capture_name=capture_name,
                    params=params,
                    cast_type=param_type)
    
                capture_pointer_func = TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC.format(
                    name=capture_name, params=params_with_type + ", angle::ParamCapture *paramCapture")
                capture_pointer_funcs += [capture_pointer_func]
            elif capture_param_type in ('GLenum', 'GLbitfield'):
                gl_enum_group = find_gl_enum_group_in_command(command, param_name)
                capture = TEMPLATE_PARAMETER_CAPTURE_GL_ENUM.format(
                    name=param_name, type=capture_param_type, group=gl_enum_group)
            else:
                capture = TEMPLATE_PARAMETER_CAPTURE_VALUE.format(
                    name=param_name, type=capture_param_type)
    
            all_param_types.add(capture_param_type)
    
            parameter_captures += [capture]
    
        return_type = proto[:-len(cmd_name)].strip()
    
        format_args = {
            "full_name": cmd_name,
            "short_name": strip_api_prefix(cmd_name),
            "params_with_type": params_with_type,
            "params_just_name": params_just_name,
            "parameter_captures": "\n    ".join(parameter_captures),
            "return_value_type_original": return_type,
            "return_value_type_custom": get_capture_param_type_name(return_type)
        }
    
        if return_type == "void":
            return TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE.format(**format_args)
        else:
            return TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE.format(**format_args)
    
    
    def const_pointer_type(param, packed_gl_enums):
        type = just_the_type_packed(param, packed_gl_enums)
        if just_the_name(param) == "errcode_ret" or "(" in type:
            return type
        elif "**" in type and "const" not in type:
            return type.replace("**", "* const *")
        elif "*" in type and "const" not in type:
            return type.replace("*", "*const ") if "[]" in type else "const " + type
        else:
            return type
    
    
    def get_internal_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
        packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
                                           params)
        return ", ".join([
            make_param(
                just_the_type_packed(param, packed_gl_enums),
                just_the_name_packed(param, packed_gl_enums)) for param in params
        ])
    
    
    def get_validation_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
        packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
                                           params)
        last = -1 if params and just_the_name(params[-1]) == "errcode_ret" else None
        return ", ".join([
            make_param(
                const_pointer_type(param, packed_gl_enums),
                just_the_name_packed(param, packed_gl_enums)) for param in params[:last]
        ])
    
    
    def format_context_decl(api, cmd_name, proto, params, template, cmd_packed_gl_enums,
                            packed_param_types):
        internal_params = get_internal_params(api, cmd_name, params, cmd_packed_gl_enums,
                                              packed_param_types)
    
        return_type = proto[:-len(cmd_name)].strip()
        name_lower_no_suffix = cmd_name[2:3].lower() + cmd_name[3:]
        name_lower_no_suffix = strip_suffix(api, name_lower_no_suffix)
        maybe_const = " const" if name_lower_no_suffix.startswith(
            "is") and name_lower_no_suffix[2].isupper() else ""
    
        return template.format(
            return_type=return_type,
            name_lower_no_suffix=name_lower_no_suffix,
            internal_params=internal_params,
            maybe_const=maybe_const)
    
    
    def format_entry_point_export(cmd_name, proto, params, is_explicit_context, template):
        internal_params = [just_the_name(param) for param in params]
        return_type = proto[:-len(cmd_name)].strip()
    
        return template.format(
            name=strip_api_prefix(cmd_name),
            return_type=return_type,
            params=", ".join(params),
            internal_params=", ".join(internal_params),
            explicit_context_suffix="ContextANGLE" if is_explicit_context else "",
            explicit_context_param="GLeglContext ctx" if is_explicit_context else "",
            explicit_context_comma=", " if is_explicit_context and len(params) > 0 else "",
            explicit_context_internal_param="ctx" if is_explicit_context else "")
    
    
    def format_validation_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
        if api == apis.CL:
            return_type = "cl_int"
        else:
            return_type = "bool"
        if api in [apis.GL, apis.GLES]:
            with_extra_params = ["Context *context"] + params
        elif api == apis.EGL:
            with_extra_params = ["ValidationContext *val"] + params
        else:
            with_extra_params = params
        internal_params = get_validation_params(api, cmd_name, with_extra_params, cmd_packed_gl_enums,
                                                packed_param_types)
        return TEMPLATE_VALIDATION_PROTO % (return_type, strip_api_prefix(cmd_name), internal_params)
    
    
    def format_capture_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
        internal_params = get_internal_params(api, cmd_name,
                                              ["const State &glState", "bool isCallValid"] + params,
                                              cmd_packed_gl_enums, packed_param_types)
        return_type = proto[:-len(cmd_name)].strip()
        if return_type != "void":
            internal_params += ", %s returnValue" % return_type
        return TEMPLATE_CAPTURE_PROTO % (strip_api_prefix(cmd_name), internal_params)
    
    
    def path_to(folder, file):
        return os.path.join(script_relative(".."), "src", folder, file)
    
    
    class ANGLEEntryPoints(registry_xml.EntryPoints):
    
        def __init__(self,
                     api,
                     xml,
                     commands,
                     all_param_types,
                     cmd_packed_enums,
                     export_template=TEMPLATE_GL_ENTRY_POINT_EXPORT,
                     is_explicit_context=False,
                     packed_param_types=[],
                     ep_to_object={}):
            super().__init__(api, xml, commands)
    
            self.decls = []
            self.defs = []
            self.export_defs = []
            self.validation_protos = []
            self.capture_protos = []
            self.capture_methods = []
            self.capture_pointer_funcs = []
    
            for (cmd_name, command_node, param_text, proto_text) in self.get_infos():
                self.decls.append(
                    format_entry_point_decl(self.api, cmd_name, proto_text, param_text,
                                            is_explicit_context))
                self.defs.append(
                    format_entry_point_def(self.api, command_node, cmd_name, proto_text, param_text,
                                           is_explicit_context, cmd_packed_enums, packed_param_types,
                                           ep_to_object))
    
                self.export_defs.append(
                    format_entry_point_export(cmd_name, proto_text, param_text, is_explicit_context,
                                              export_template))
    
                self.validation_protos.append(
                    format_validation_proto(self.api, cmd_name, proto_text, param_text,
                                            cmd_packed_enums, packed_param_types))
                self.capture_protos.append(
                    format_capture_proto(self.api, cmd_name, proto_text, param_text, cmd_packed_enums,
                                         packed_param_types))
                self.capture_methods.append(
                    format_capture_method(self.api, command_node, cmd_name, proto_text, param_text,
                                          all_param_types, self.capture_pointer_funcs,
                                          cmd_packed_enums, packed_param_types))
    
    
    class GLEntryPoints(ANGLEEntryPoints):
    
        all_param_types = set()
    
        def __init__(self, api, xml, commands, is_explicit_context=False):
            super().__init__(
                api,
                xml,
                commands,
                GLEntryPoints.all_param_types,
                GLEntryPoints.get_packed_enums(),
                is_explicit_context=is_explicit_context)
    
        _packed_enums = None
    
        @classmethod
        def get_packed_enums(cls):
            if not cls._packed_enums:
                with open(script_relative('entry_point_packed_gl_enums.json')) as f:
                    cls._packed_enums = json.loads(f.read())
            return cls._packed_enums
    
    
    class EGLEntryPoints(ANGLEEntryPoints):
    
        all_param_types = set()
    
        def __init__(self, xml, commands):
            super().__init__(
                apis.EGL,
                xml,
                commands,
                EGLEntryPoints.all_param_types,
                EGLEntryPoints.get_packed_enums(),
                export_template=TEMPLATE_EGL_ENTRY_POINT_EXPORT,
                packed_param_types=EGL_PACKED_TYPES,
                ep_to_object=EGLEntryPoints._get_ep_to_object())
    
        _ep_to_object = None
    
        @classmethod
        def _get_ep_to_object(cls):
    
            if cls._ep_to_object:
                return cls._ep_to_object
    
            with open(EGL_GET_LABELED_OBJECT_DATA_PATH) as f:
                try:
                    spec_json = json.loads(f.read())
                except ValueError:
                    raise Exception("Could not decode JSON from %s" % EGL_GET_LABELED_OBJECT_DATA_PATH)
    
            # Construct a mapping from EP to type. Fill in the gaps with Display/None.
            cls._ep_to_object = {}
    
            for category, eps in spec_json.items():
                if category == 'description':
                    continue
                for ep in eps:
                    cls._ep_to_object[ep] = category
    
            return cls._ep_to_object
    
        _packed_enums = None
    
        @classmethod
        def get_packed_enums(cls):
            if not cls._packed_enums:
                with open(script_relative('entry_point_packed_egl_enums.json')) as f:
                    cls._packed_enums = json.loads(f.read())
            return cls._packed_enums
    
    
    class CLEntryPoints(ANGLEEntryPoints):
    
        all_param_types = set()
    
        def __init__(self, xml, commands):
            super().__init__(
                apis.CL,
                xml,
                commands,
                CLEntryPoints.all_param_types,
                CLEntryPoints.get_packed_enums(),
                export_template=TEMPLATE_CL_ENTRY_POINT_EXPORT,
                packed_param_types=CL_PACKED_TYPES)
    
        @classmethod
        def get_packed_enums(cls):
            return {}
    
    
    def get_decls(api,
                  formatter,
                  all_commands,
                  gles_commands,
                  already_included,
                  cmd_packed_gl_enums,
                  packed_param_types=[]):
        decls = []
        for command in all_commands:
            proto = command.find('proto')
            cmd_name = proto.find('name').text
    
            if cmd_name not in gles_commands:
                continue
    
            name_no_suffix = strip_suffix(api, cmd_name)
            if name_no_suffix in already_included:
                continue
    
            param_text = ["".join(param.itertext()) for param in command.findall('param')]
            proto_text = "".join(proto.itertext())
            decls.append(
                format_context_decl(api, cmd_name, proto_text, param_text, formatter,
                                    cmd_packed_gl_enums, packed_param_types))
    
        return decls
    
    
    def get_glext_decls(all_commands, gles_commands, version, is_explicit_context):
        glext_ptrs = []
        glext_protos = []
        is_gles1 = False
    
        if (version == ""):
            is_gles1 = True
    
        for command in all_commands:
            proto = command.find('proto')
            cmd_name = proto.find('name').text
    
            if cmd_name not in gles_commands:
                continue
    
            param_text = ["".join(param.itertext()) for param in command.findall('param')]
            proto_text = "".join(proto.itertext())
    
            return_type = proto_text[:-len(cmd_name)]
            params = ", ".join(param_text)
    
            format_params = {
                "apicall": "GL_API" if is_gles1 else "GL_APICALL",
                "name": cmd_name,
                "name_upper": cmd_name.upper(),
                "return_type": return_type,
                "params": params,
                "explicit_context_comma": ", " if is_explicit_context and len(params) > 0 else "",
                "explicit_context_suffix": "ContextANGLE" if is_explicit_context else "",
                "explicit_context_suffix_upper": "CONTEXTANGLE" if is_explicit_context else "",
                "explicit_context_param": "GLeglContext ctx" if is_explicit_context else ""
            }
    
            glext_ptrs.append(TEMPLATE_GLEXT_FUNCTION_POINTER.format(**format_params))
            glext_protos.append(TEMPLATE_GLEXT_FUNCTION_PROTOTYPE.format(**format_params))
    
        return glext_ptrs, glext_protos
    
    
    def write_file(annotation, comment, template, entry_points, suffix, includes, lib, file):
    
        content = template.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name=file,
            annotation_lower=annotation.lower(),
            annotation_upper=annotation.upper(),
            comment=comment,
            lib=lib.upper(),
            includes=includes,
            entry_points=entry_points)
    
        path = path_to(lib, "entry_points_{}_autogen.{}".format(annotation.lower(), suffix))
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def write_export_files(entry_points, includes, source, lib_name, lib_description):
        content = TEMPLATE_LIB_ENTRY_POINT_SOURCE.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name=source,
            lib_name=lib_name,
            lib_description=lib_description,
            includes=includes,
            entry_points=entry_points)
    
        path = path_to(lib_name, "{}_autogen.cpp".format(lib_name))
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def write_context_api_decls(decls, api):
        for (major, minor), version_decls in sorted(decls['core'].items()):
            if minor == "X":
                annotation = '{}_{}'.format(api, major)
                version = str(major)
            else:
                annotation = '{}_{}_{}'.format(api, major, minor)
                version = '{}_{}'.format(major, minor)
            content = CONTEXT_HEADER.format(
                annotation_lower=annotation.lower(),
                annotation_upper=annotation.upper(),
                script_name=os.path.basename(sys.argv[0]),
                data_source_name="gl.xml",
                version=version,
                interface="\n".join(version_decls))
    
            path = path_to("libANGLE", "Context_%s_autogen.h" % annotation.lower())
    
            with open(path, "w") as out:
                out.write(content)
                out.close()
    
        if 'exts' in decls.keys():
            interface_lines = []
            for annotation in decls['exts'].keys():
                interface_lines.append("\\\n    /* " + annotation + " */ \\\n\\")
    
                for extname in sorted(decls['exts'][annotation].keys()):
                    interface_lines.append("    /* " + extname + " */ \\")
                    interface_lines.extend(decls['exts'][annotation][extname])
    
            content = CONTEXT_HEADER.format(
                annotation_lower='gles_ext',
                annotation_upper='GLES_EXT',
                script_name=os.path.basename(sys.argv[0]),
                data_source_name="gl.xml",
                version='EXT',
                interface="\n".join(interface_lines))
    
            path = path_to("libANGLE", "Context_gles_ext_autogen.h")
    
            with open(path, "w") as out:
                out.write(content)
                out.close()
    
    
    def write_glext_explicit_context_inc(version, ptrs, protos):
        possible_versions = ["31", "32"]
        folder_version = version if version not in possible_versions else "3"
    
        content = TEMPLATE_GLEXT_EXPLICIT_CONTEXT_INC.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            version=version,
            function_pointers=ptrs,
            function_prototypes=protos)
    
        path = os.path.join(
            script_relative(".."), "include", "GLES{}".format(folder_version),
            "gl{}ext_explicit_context_autogen.inc".format(version))
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def write_validation_header(annotation, comment, protos, source, template):
        content = template.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name=source,
            annotation=annotation,
            comment=comment,
            prototypes="\n".join(protos))
    
        path = path_to("libANGLE", "validation%s_autogen.h" % annotation)
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def write_gl_validation_header(annotation, comment, protos, source):
        return write_validation_header(annotation, comment, protos, source,
                                       TEMPLATE_GL_VALIDATION_HEADER)
    
    
    def write_capture_header(annotation, comment, protos, capture_pointer_funcs):
        content = TEMPLATE_CAPTURE_HEADER.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            annotation_lower=annotation.lower(),
            annotation_upper=annotation.upper(),
            comment=comment,
            prototypes="\n".join(["\n// Method Captures\n"] + protos + ["\n// Parameter Captures\n"] +
                                 capture_pointer_funcs))
    
        path = path_to(os.path.join("libANGLE", "capture"), "capture_gles_%s_autogen.h" % annotation)
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def write_capture_source(annotation_with_dash, annotation_no_dash, comment, capture_methods):
        content = TEMPLATE_CAPTURE_SOURCE.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            annotation_with_dash=annotation_with_dash,
            annotation_no_dash=annotation_no_dash,
            comment=comment,
            capture_methods="\n".join(capture_methods))
    
        path = path_to(
            os.path.join("libANGLE", "capture"), "capture_gles_%s_autogen.cpp" % annotation_with_dash)
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def is_packed_enum_param_type(param_type):
        return param_type[0:2] != "GL" and "void" not in param_type
    
    
    def get_gl_pointer_type(param_type):
    
        if "ConstPointerPointer" in param_type:
            return "const " + param_type.replace("ConstPointerPointer", "") + " * const *"
    
        if "ConstPointer" in param_type:
            return "const " + param_type.replace("ConstPointer", "") + " *"
    
        if "PointerPointer" in param_type:
            return param_type.replace("PointerPointer", "") + " **"
    
        if "Pointer" in param_type:
            return param_type.replace("Pointer", "") + " *"
    
        return param_type
    
    
    def get_param_type_type(param_type):
    
        if is_packed_enum_param_type(param_type):
            param_type = "gl::" + param_type
    
        return get_gl_pointer_type(param_type)
    
    
    def get_gl_param_type_type(param_type):
        if not is_packed_enum_param_type(param_type):
            return get_gl_pointer_type(param_type)
        else:
            base_type = param_type.replace("Pointer", "").replace("Const", "")
            if base_type[-2:] == "ID":
                replace_type = "GLuint"
            else:
                replace_type = "GLenum"
            param_type = param_type.replace(base_type, replace_type)
            return get_gl_pointer_type(param_type)
    
    
    def get_param_type_union_name(param_type):
        return param_type + "Val"
    
    
    def format_param_type_union_type(param_type):
        return "%s %s;" % (get_param_type_type(param_type), get_param_type_union_name(param_type))
    
    
    def format_get_param_val_specialization(param_type):
        return TEMPLATE_GET_PARAM_VAL_SPECIALIZATION.format(
            enum=param_type,
            type=get_param_type_type(param_type),
            union_name=get_param_type_union_name(param_type))
    
    
    def format_access_param_value_case(param_type):
        return TEMPLATE_ACCESS_PARAM_VALUE_CASE.format(enum=param_type)
    
    
    def format_set_param_val_specialization(param_type):
        return TEMPLATE_SET_PARAM_VAL_SPECIALIZATION.format(
            enum=param_type,
            type=get_param_type_type(param_type),
            union_name=get_param_type_union_name(param_type))
    
    
    def format_init_param_value_case(param_type):
        return TEMPLATE_INIT_PARAM_VALUE_CASE.format(enum=param_type)
    
    
    def format_write_param_type_to_stream_case(param_type):
        # Force all enum printing to go through "const void *"
        param_out = "voidConstPointer" if "Pointer" in param_type else param_type
        return TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE.format(
            enum_in=param_type, enum_out=param_out, union_name=get_param_type_union_name(param_out))
    
    
    def get_resource_id_types(all_param_types):
        return [t[:-2] for t in filter(lambda t: t.endswith("ID"), all_param_types)]
    
    
    def format_resource_id_types(all_param_types):
        resource_id_types = get_resource_id_types(all_param_types)
        resource_id_types += ["EnumCount", "InvalidEnum = EnumCount"]
        resource_id_types = ",\n    ".join(resource_id_types)
        return resource_id_types
    
    
    def write_capture_helper_header(all_param_types):
    
        param_types = "\n    ".join(["T%s," % t for t in all_param_types])
        param_union_values = "\n    ".join([format_param_type_union_type(t) for t in all_param_types])
        get_param_val_specializations = "\n\n".join(
            [format_get_param_val_specialization(t) for t in all_param_types])
        access_param_value_cases = "\n".join(
            [format_access_param_value_case(t) for t in all_param_types])
        set_param_val_specializations = "\n\n".join(
            [format_set_param_val_specialization(t) for t in all_param_types])
        init_param_value_cases = "\n".join([format_init_param_value_case(t) for t in all_param_types])
        resource_id_types = format_resource_id_types(all_param_types)
    
        content = TEMPLATE_FRAME_CAPTURE_UTILS_HEADER.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            param_types=param_types,
            param_type_count=len(all_param_types),
            param_union_values=param_union_values,
            get_param_val_specializations=get_param_val_specializations,
            access_param_value_cases=access_param_value_cases,
            set_param_val_specializations=set_param_val_specializations,
            init_param_value_cases=init_param_value_cases,
            resource_id_types=resource_id_types)
    
        path = path_to(os.path.join("libANGLE", "capture"), "frame_capture_utils_autogen.h")
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def format_param_type_to_string_case(param_type):
        return TEMPLATE_PARAM_TYPE_TO_STRING_CASE.format(
            enum=param_type, type=get_gl_param_type_type(param_type))
    
    
    def get_resource_id_type_from_param_type(param_type):
        if param_type.endswith("ConstPointer"):
            return param_type.replace("ConstPointer", "")[:-2]
        if param_type.endswith("Pointer"):
            return param_type.replace("Pointer", "")[:-2]
        return param_type[:-2]
    
    
    def format_param_type_to_resource_id_type_case(param_type):
        return TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE.format(
            enum=param_type, resource_id_type=get_resource_id_type_from_param_type(param_type))
    
    
    def format_param_type_resource_id_cases(all_param_types):
        id_types = filter(
            lambda t: t.endswith("ID") or t.endswith("IDConstPointer") or t.endswith("IDPointer"),
            all_param_types)
        return "\n".join([format_param_type_to_resource_id_type_case(t) for t in id_types])
    
    
    def format_resource_id_type_name_case(resource_id_type):
        return TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE.format(resource_id_type=resource_id_type)
    
    
    def write_capture_helper_source(all_param_types):
    
        write_param_type_to_stream_cases = "\n".join(
            [format_write_param_type_to_stream_case(t) for t in all_param_types])
        param_type_to_string_cases = "\n".join(
            [format_param_type_to_string_case(t) for t in all_param_types])
    
        param_type_resource_id_cases = format_param_type_resource_id_cases(all_param_types)
    
        resource_id_types = get_resource_id_types(all_param_types)
        resource_id_type_name_cases = "\n".join(
            [format_resource_id_type_name_case(t) for t in resource_id_types])
    
        content = TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            write_param_type_to_stream_cases=write_param_type_to_stream_cases,
            param_type_to_string_cases=param_type_to_string_cases,
            param_type_resource_id_cases=param_type_resource_id_cases,
            resource_id_type_name_cases=resource_id_type_name_cases)
    
        path = path_to(os.path.join("libANGLE", "capture"), "frame_capture_utils_autogen.cpp")
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def get_command_params_text(command_node, cmd_name):
        param_text_list = list()
        for param_node in command_node.findall('param'):
            param_text_list.append("".join(param_node.itertext()))
        return param_text_list
    
    
    def is_get_pointer_command(command_name):
        return command_name.endswith('Pointerv') and command_name.startswith('glGet')
    
    
    def format_capture_replay_param_access(api, command_name, param_text_list, cmd_packed_gl_enums,
                                           packed_param_types):
        param_access_strs = list()
        cmd_packed_enums = get_packed_enums(api, cmd_packed_gl_enums, command_name, packed_param_types,
                                            param_text_list)
        for i, param_text in enumerate(param_text_list):
            param_type = just_the_type_packed(param_text, cmd_packed_enums)
            param_name = just_the_name_packed(param_text, cmd_packed_enums)
    
            pointer_count = param_type.count('*')
            is_const = 'const' in param_type
            if pointer_count == 0:
                param_template = 'params.getParam("{name}", ParamType::T{enum_type}, {index}).value.{enum_type}Val'
            elif pointer_count == 1 and is_const:
                param_template = 'replayContext->getAsConstPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
            elif pointer_count == 2 and is_const:
                param_template = 'replayContext->getAsPointerConstPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
            elif pointer_count == 1 or (pointer_count == 2 and is_get_pointer_command(command_name)):
                param_template = 'replayContext->getReadBufferPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
            else:
                assert False, "Not supported param type %s" % param_type
    
            param_access_strs.append(
                param_template.format(
                    index=i,
                    name=param_name,
                    type=param_type,
                    enum_type=get_capture_param_type_name(param_type)))
        return ",".join(param_access_strs)
    
    
    def format_capture_replay_call_case(api, command_to_param_types_mapping, cmd_packed_gl_enums,
                                        packed_param_types):
        call_str_list = list()
        for command_name, cmd_param_texts in sorted(command_to_param_types_mapping.items()):
            entry_point_name = strip_api_prefix(command_name)
    
            call_str_list.append(
                TEMPLATE_CAPTURE_REPLAY_CALL_CASE.format(
                    entry_point=entry_point_name,
                    param_value_access=format_capture_replay_param_access(
                        api, command_name, cmd_param_texts, cmd_packed_gl_enums, packed_param_types),
                    context_call=entry_point_name[0].lower() + entry_point_name[1:],
                ))
    
        return '\n'.join(call_str_list)
    
    
    def write_capture_replay_source(api, all_commands_nodes, gles_command_names, cmd_packed_gl_enums,
                                    packed_param_types):
        all_commands_names = set(gles_command_names)
    
        command_to_param_types_mapping = dict()
        for command_node in all_commands_nodes:
            command_name = command_node.find('proto').find('name').text
            if command_name not in all_commands_names:
                continue
    
            command_to_param_types_mapping[command_name] = get_command_params_text(
                command_node, command_name)
    
        call_replay_cases = format_capture_replay_call_case(api, command_to_param_types_mapping,
                                                            cmd_packed_gl_enums, packed_param_types)
    
        source_content = TEMPLATE_CAPTURE_REPLAY_SOURCE.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            call_replay_cases=call_replay_cases,
        )
        source_file_path = registry_xml.script_relative(
            "../src/libANGLE/capture/frame_capture_replay_autogen.cpp")
        with open(source_file_path, 'w') as f:
            f.write(source_content)
    
    
    def write_windows_def_file(data_source_name, lib, libexport, folder, exports):
    
        content = TEMPLATE_WINDOWS_DEF_FILE.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name=data_source_name,
            exports="\n".join(exports),
            lib=libexport)
    
        path = path_to(folder, "%s_autogen.def" % lib)
    
        with open(path, "w") as out:
            out.write(content)
            out.close()
    
    
    def get_exports(commands, fmt=None):
        if fmt:
            return ["    %s" % fmt(cmd) for cmd in sorted(commands)]
        else:
            return ["    %s" % cmd for cmd in sorted(commands)]
    
    
    # Get EGL exports
    def get_egl_exports():
    
        egl = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
        exports = []
    
        capser = lambda fn: "EGL_" + fn[3:]
    
        for major, minor in registry_xml.EGL_VERSIONS:
            annotation = "{}_{}".format(major, minor)
            name_prefix = "EGL_VERSION_"
    
            feature_name = "{}{}".format(name_prefix, annotation)
    
            egl.AddCommands(feature_name, annotation)
    
            commands = egl.commands[annotation]
    
            if len(commands) == 0:
                continue
    
            exports.append("\n    ; EGL %d.%d" % (major, minor))
            exports += get_exports(commands, capser)
    
        egl.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
    
        for extension_name, ext_cmd_names in sorted(egl.ext_data.items()):
    
            if len(ext_cmd_names) == 0:
                continue
    
            exports.append("\n    ; %s" % extension_name)
            exports += get_exports(ext_cmd_names, capser)
    
        return exports
    
    
    # Construct a mapping from an EGL EP to object function
    def get_egl_entry_point_labeled_object(ep_to_object, cmd_stripped, params, packed_enums):
    
        if not ep_to_object:
            return ""
    
        # Finds a packed parameter name in a list of params
        def find_param(params, type_name, packed_enums):
            for param in params:
                if just_the_type_packed(param, packed_enums).split(' ')[0] == type_name:
                    return just_the_name_packed(param, packed_enums)
            return None
    
        display_param = find_param(params, "egl::Display", packed_enums)
    
        # For entry points not listed in the JSON file, they default to an EGLDisplay or nothing.
        if cmd_stripped not in ep_to_object:
            if display_param:
                return "GetDisplayIfValid(%s)" % display_param
            return "nullptr"
    
        # We first handle a few special cases for certain type categories.
        category = ep_to_object[cmd_stripped]
        if category == "Thread":
            return "GetThreadIfValid(thread)"
        found_param = find_param(params, category, packed_enums)
        if category == "Context" and not found_param:
            return "GetContextIfValid(thread->getDisplay(), thread->getContext())"
        assert found_param, "Did not find %s for %s: %s" % (category, cmd_stripped, str(params))
        if category == "Device":
            return "GetDeviceIfValid(%s)" % found_param
        if category == "LabeledObject":
            object_type_param = find_param(params, "ObjectType", packed_enums)
            return "GetLabeledObjectIfValid(thread, %s, %s, %s)" % (display_param, object_type_param,
                                                                    found_param)
    
        # We then handle the general case which handles the rest of the type categories.
        return "Get%sIfValid(%s, %s)" % (category, display_param, found_param)
    
    
    def write_stubs_header(api, annotation, title, data_source, out_file, all_commands, commands,
                           cmd_packed_egl_enums, packed_param_types):
    
        stubs = []
    
        for command in all_commands:
            proto = command.find('proto')
            cmd_name = proto.find('name').text
    
            if cmd_name not in commands:
                continue
    
            proto_text = "".join(proto.itertext())
            params = [] if api == apis.CL else ["Thread *thread"]
            params += ["".join(param.itertext()) for param in command.findall('param')]
            if params and just_the_name(params[-1]) == "errcode_ret":
                params[-1] = "cl_int &errorCode"
            return_type = proto_text[:-len(cmd_name)].strip()
    
            internal_params = get_internal_params(api, cmd_name, params, cmd_packed_egl_enums,
                                                  packed_param_types)
    
            stubs.append("%s %s(%s);" % (return_type, strip_api_prefix(cmd_name), internal_params))
    
        args = {
            "annotation_lower": annotation.lower(),
            "annotation_upper": annotation.upper(),
            "data_source_name": data_source,
            "script_name": os.path.basename(sys.argv[0]),
            "stubs": "\n".join(stubs),
            "title": title,
        }
    
        output = get_stubs_header_template(api).format(**args)
    
        with open(out_file, "w") as f:
            f.write(output)
    
    
    def main():
    
        # auto_script parameters.
        if len(sys.argv) > 1:
            inputs = [
                'entry_point_packed_egl_enums.json', 'entry_point_packed_gl_enums.json',
                EGL_GET_LABELED_OBJECT_DATA_PATH
            ] + registry_xml.xml_inputs
            outputs = [
                CL_STUBS_HEADER_PATH,
                EGL_STUBS_HEADER_PATH,
                EGL_EXT_STUBS_HEADER_PATH,
                '../src/libOpenCL/libOpenCL_autogen.cpp',
                '../src/common/entry_points_enum_autogen.cpp',
                '../src/common/entry_points_enum_autogen.h',
                '../src/libANGLE/Context_gl_1_autogen.h',
                '../src/libANGLE/Context_gl_2_autogen.h',
                '../src/libANGLE/Context_gl_3_autogen.h',
                '../src/libANGLE/Context_gl_4_autogen.h',
                '../src/libANGLE/Context_gles_1_0_autogen.h',
                '../src/libANGLE/Context_gles_2_0_autogen.h',
                '../src/libANGLE/Context_gles_3_0_autogen.h',
                '../src/libANGLE/Context_gles_3_1_autogen.h',
                '../src/libANGLE/Context_gles_3_2_autogen.h',
                '../src/libANGLE/Context_gles_ext_autogen.h',
                '../src/libANGLE/capture/capture_gles_1_0_autogen.cpp',
                '../src/libANGLE/capture/capture_gles_1_0_autogen.h',
                '../src/libANGLE/capture/capture_gles_2_0_autogen.cpp',
                '../src/libANGLE/capture/capture_gles_2_0_autogen.h',
                '../src/libANGLE/capture/capture_gles_3_0_autogen.cpp',
                '../src/libANGLE/capture/capture_gles_3_0_autogen.h',
                '../src/libANGLE/capture/capture_gles_3_1_autogen.cpp',
                '../src/libANGLE/capture/capture_gles_3_1_autogen.h',
                '../src/libANGLE/capture/capture_gles_3_2_autogen.cpp',
                '../src/libANGLE/capture/capture_gles_3_2_autogen.h',
                '../src/libANGLE/capture/capture_gles_ext_autogen.cpp',
                '../src/libANGLE/capture/capture_gles_ext_autogen.h',
                '../src/libANGLE/capture/frame_capture_replay_autogen.cpp',
                '../src/libANGLE/capture/frame_capture_utils_autogen.cpp',
                '../src/libANGLE/capture/frame_capture_utils_autogen.h',
                '../src/libANGLE/validationCL_autogen.h',
                '../src/libANGLE/validationEGL_autogen.h',
                '../src/libANGLE/validationES1_autogen.h',
                '../src/libANGLE/validationES2_autogen.h',
                '../src/libANGLE/validationES31_autogen.h',
                '../src/libANGLE/validationES32_autogen.h',
                '../src/libANGLE/validationES3_autogen.h',
                '../src/libANGLE/validationESEXT_autogen.h',
                '../src/libANGLE/validationGL1_autogen.h',
                '../src/libANGLE/validationGL2_autogen.h',
                '../src/libANGLE/validationGL3_autogen.h',
                '../src/libANGLE/validationGL4_autogen.h',
                '../src/libEGL/libEGL_autogen.cpp',
                '../src/libEGL/libEGL_autogen.def',
                '../src/libGLESv2/entry_points_cl_autogen.cpp',
                '../src/libGLESv2/entry_points_cl_autogen.h',
                '../src/libGLESv2/entry_points_egl_autogen.cpp',
                '../src/libGLESv2/entry_points_egl_autogen.h',
                '../src/libGLESv2/entry_points_egl_ext_autogen.cpp',
                '../src/libGLESv2/entry_points_egl_ext_autogen.h',
                '../src/libGLESv2/entry_points_gles_1_0_autogen.cpp',
                '../src/libGLESv2/entry_points_gles_1_0_autogen.h',
                '../src/libGLESv2/entry_points_gles_2_0_autogen.cpp',
                '../src/libGLESv2/entry_points_gles_2_0_autogen.h',
                '../src/libGLESv2/entry_points_gles_3_0_autogen.cpp',
                '../src/libGLESv2/entry_points_gles_3_0_autogen.h',
                '../src/libGLESv2/entry_points_gles_3_1_autogen.cpp',
                '../src/libGLESv2/entry_points_gles_3_1_autogen.h',
                '../src/libGLESv2/entry_points_gles_3_2_autogen.cpp',
                '../src/libGLESv2/entry_points_gles_3_2_autogen.h',
                '../src/libGLESv2/entry_points_gles_ext_autogen.cpp',
                '../src/libGLESv2/entry_points_gles_ext_autogen.h',
                '../src/libGLESv2/libGLESv2_autogen.cpp',
                '../src/libGLESv2/libGLESv2_autogen.def',
                '../src/libGLESv2/libGLESv2_no_capture_autogen.def',
                '../src/libGLESv2/libGLESv2_with_capture_autogen.def',
                '../src/libGL/entry_points_gl_1_autogen.cpp',
                '../src/libGL/entry_points_gl_1_autogen.h',
                '../src/libGL/entry_points_gl_2_autogen.cpp',
                '../src/libGL/entry_points_gl_2_autogen.h',
                '../src/libGL/entry_points_gl_3_autogen.cpp',
                '../src/libGL/entry_points_gl_3_autogen.h',
                '../src/libGL/entry_points_gl_4_autogen.cpp',
                '../src/libGL/entry_points_gl_4_autogen.h',
                '../src/libGL/libGL_autogen.cpp',
                '../src/libGL/libGL_autogen.def',
            ]
    
            if sys.argv[1] == 'inputs':
                print(','.join(inputs))
            elif sys.argv[1] == 'outputs':
                print(','.join(outputs))
            else:
                print('Invalid script parameters')
                return 1
            return 0
    
        glesdecls = {}
        glesdecls['core'] = {}
        glesdecls['exts'] = {}
        for ver in registry_xml.GLES_VERSIONS:
            glesdecls['core'][ver] = []
        for ver in ['GLES1 Extensions', 'GLES2+ Extensions', 'ANGLE Extensions']:
            glesdecls['exts'][ver] = {}
    
        libgles_ep_defs = []
        libgles_ep_exports = []
    
        xml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')
    
        # Stores core commands to keep track of duplicates
        all_commands_no_suffix = []
        all_commands_with_suffix = []
    
        # First run through the main GLES entry points.  Since ES2+ is the primary use
        # case, we go through those first and then add ES1-only APIs at the end.
        for major_version, minor_version in registry_xml.GLES_VERSIONS:
            version = "{}_{}".format(major_version, minor_version)
            annotation = "GLES_{}".format(version)
            name_prefix = "GL_ES_VERSION_"
    
            if major_version == 1:
                name_prefix = "GL_VERSION_ES_CM_"
    
            comment = version.replace("_", ".")
            feature_name = "{}{}".format(name_prefix, version)
    
            xml.AddCommands(feature_name, version)
    
            version_commands = xml.commands[version]
            all_commands_no_suffix.extend(xml.commands[version])
            all_commands_with_suffix.extend(xml.commands[version])
    
            eps = GLEntryPoints(apis.GLES, xml, version_commands)
            eps.decls.insert(0, "extern \"C\" {")
            eps.decls.append("} // extern \"C\"")
            eps.defs.insert(0, "extern \"C\" {")
            eps.defs.append("} // extern \"C\"")
    
            # Write the version as a comment before the first EP.
            libgles_ep_exports.append("\n    ; OpenGL ES %s" % comment)
    
            libgles_ep_defs += ["\n// OpenGL ES %s" % comment] + eps.export_defs
            libgles_ep_exports += get_exports(version_commands)
    
            major_if_not_one = major_version if major_version != 1 else ""
            minor_if_not_zero = minor_version if minor_version != 0 else ""
    
            header_includes = TEMPLATE_HEADER_INCLUDES.format(
                major=major_if_not_one, minor=minor_if_not_zero)
    
            # We include the platform.h header since it undefines the conflicting MemoryBarrier macro.
            if major_version == 3 and minor_version == 1:
                header_includes += "\n#include \"common/platform.h\"\n"
    
            version_annotation = "%s%s" % (major_version, minor_if_not_zero)
            source_includes = TEMPLATE_SOURCES_INCLUDES.format(
                header_version=annotation.lower(), validation_header_version="ES" + version_annotation)
    
            write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_HEADER,
                       "\n".join(eps.decls), "h", header_includes, "libGLESv2", "gl.xml")
            write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(eps.defs),
                       "cpp", source_includes, "libGLESv2", "gl.xml")
    
            glesdecls['core'][(major_version,
                               minor_version)] = get_decls(apis.GLES, CONTEXT_DECL_FORMAT,
                                                           xml.all_commands, version_commands, [],
                                                           GLEntryPoints.get_packed_enums())
    
            validation_annotation = "ES%s%s" % (major_version, minor_if_not_zero)
            write_gl_validation_header(validation_annotation, "ES %s" % comment, eps.validation_protos,
                                       "gl.xml and gl_angle_ext.xml")
    
            write_capture_header(version, comment, eps.capture_protos, eps.capture_pointer_funcs)
            write_capture_source(version, validation_annotation, comment, eps.capture_methods)
    
        # After we finish with the main entry points, we process the extensions.
        extension_decls = ["extern \"C\" {"]
        extension_defs = ["extern \"C\" {"]
        extension_commands = []
    
        # Accumulated validation prototypes.
        ext_validation_protos = []
        ext_capture_protos = []
        ext_capture_methods = []
        ext_capture_pointer_funcs = []
    
        for gles1ext in registry_xml.gles1_extensions:
            glesdecls['exts']['GLES1 Extensions'][gles1ext] = []
        for glesext in registry_xml.gles_extensions:
            glesdecls['exts']['GLES2+ Extensions'][glesext] = []
        for angle_ext in registry_xml.angle_extensions:
            glesdecls['exts']['ANGLE Extensions'][angle_ext] = []
    
        xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
    
        for extension_name, ext_cmd_names in sorted(xml.ext_data.items()):
            extension_commands.extend(xml.ext_data[extension_name])
    
            # Detect and filter duplicate extensions.
            eps = GLEntryPoints(apis.GLES, xml, ext_cmd_names)
    
            # Write the extension name as a comment before the first EP.
            comment = "\n// {}".format(extension_name)
            libgles_ep_exports.append("\n    ; %s" % extension_name)
    
            extension_defs += [comment] + eps.defs
            extension_decls += [comment] + eps.decls
    
            # Avoid writing out entry points defined by a prior extension.
            for dupe in xml.ext_dupes[extension_name]:
                msg = "// {} is already defined.\n".format(strip_api_prefix(dupe))
                extension_defs.append(msg)
    
            ext_validation_protos += [comment] + eps.validation_protos
            ext_capture_protos += [comment] + eps.capture_protos
            ext_capture_methods += eps.capture_methods
            ext_capture_pointer_funcs += eps.capture_pointer_funcs
    
            libgles_ep_defs += [comment] + eps.export_defs
            libgles_ep_exports += get_exports(ext_cmd_names)
    
            if (extension_name in registry_xml.gles1_extensions and
                    extension_name not in GLES1_NO_CONTEXT_DECL_EXTENSIONS):
                glesdecls['exts']['GLES1 Extensions'][extension_name] = get_decls(
                    apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
                    all_commands_no_suffix, GLEntryPoints.get_packed_enums())
            if extension_name in registry_xml.gles_extensions:
                glesdecls['exts']['GLES2+ Extensions'][extension_name] = get_decls(
                    apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
                    all_commands_no_suffix, GLEntryPoints.get_packed_enums())
            if extension_name in registry_xml.angle_extensions:
                glesdecls['exts']['ANGLE Extensions'][extension_name] = get_decls(
                    apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
                    all_commands_no_suffix, GLEntryPoints.get_packed_enums())
    
        for name in extension_commands:
            all_commands_with_suffix.append(name)
            all_commands_no_suffix.append(strip_suffix(apis.GLES, name))
    
        # Special handling for EGL_ANGLE_explicit_context extension
        if registry_xml.support_EGL_ANGLE_explicit_context:
            comment = "\n// EGL_ANGLE_explicit_context"
            extension_defs.append(comment)
            extension_decls.append(comment)
            libgles_ep_defs.append(comment)
    
            cmds = xml.all_cmd_names.get_all_commands()
    
            # Get the explicit context entry points
            eps = GLEntryPoints(apis.GLES, xml, cmds, is_explicit_context=True)
    
            # Append the explicit context entry points
            extension_decls += eps.decls
            extension_defs += eps.defs
            libgles_ep_defs += eps.export_defs
    
            libgles_ep_exports.append("\n    ; EGL_ANGLE_explicit_context")
            libgles_ep_exports += get_exports(cmds, lambda x: "%sContextANGLE" % x)
    
            # Generate .inc files for extension function pointers and declarations
            for major, minor in registry_xml.GLES_VERSIONS:
                annotation = "{}_{}".format(major, minor)
    
                major_if_not_one = major if major != 1 else ""
                minor_if_not_zero = minor if minor != 0 else ""
                version = "{}{}".format(major_if_not_one, minor_if_not_zero)
    
                glext_ptrs, glext_protos = get_glext_decls(xml.all_commands,
                                                           xml.all_cmd_names.get_commands(annotation),
                                                           version, True)
    
                glext_ext_ptrs = []
                glext_ext_protos = []
    
                # Append extensions for 1.0 and 2.0
                if (annotation == "1_0"):
                    glext_ext_ptrs, glext_ext_protos = get_glext_decls(
                        xml.all_commands, xml.all_cmd_names.get_commands("glext"), version, True)
                elif (annotation == "2_0"):
                    glext_ext_ptrs, glext_ext_protos = get_glext_decls(
                        xml.all_commands, xml.all_cmd_names.get_commands("gl2ext"), version, True)
    
                glext_ptrs += glext_ext_ptrs
                glext_protos += glext_ext_protos
    
                write_glext_explicit_context_inc(version, "\n".join(glext_ptrs),
                                                 "\n".join(glext_protos))
    
        # Now we generate entry points for the desktop implementation
        desktop_gl_decls = {}
        desktop_gl_decls['core'] = {}
        for major, _ in registry_xml.DESKTOP_GL_VERSIONS:
            desktop_gl_decls['core'][(major, "X")] = []
    
        libgl_ep_defs = []
        libgl_ep_exports = []
    
        glxml = registry_xml.RegistryXML('gl.xml')
    
        for major_version in sorted(
                set([major for (major, minor) in registry_xml.DESKTOP_GL_VERSIONS])):
            is_major = lambda ver: ver[0] == major_version
    
            ver_decls = ["extern \"C\" {"]
            ver_defs = ["extern \"C\" {"]
            validation_protos = []
    
            for _, minor_version in filter(is_major, registry_xml.DESKTOP_GL_VERSIONS):
                version = "{}_{}".format(major_version, minor_version)
                annotation = "GL_{}".format(version)
                name_prefix = "GL_VERSION_"
    
                comment = version.replace("_", ".")
                feature_name = "{}{}".format(name_prefix, version)
    
                glxml.AddCommands(feature_name, version)
    
                all_libgl_commands = glxml.commands[version]
    
                just_libgl_commands = [
                    cmd for cmd in all_libgl_commands if cmd not in all_commands_no_suffix
                ]
                just_libgl_commands_suffix = [
                    cmd for cmd in all_libgl_commands if cmd not in all_commands_with_suffix
                ]
    
                # Validation duplicates handled with suffix
                eps_suffix = GLEntryPoints(apis.GL, glxml, just_libgl_commands_suffix)
                eps = GLEntryPoints(apis.GL, glxml, all_libgl_commands)
    
                desktop_gl_decls['core'][(major_version,
                                          "X")] += get_decls(apis.GL, CONTEXT_DECL_FORMAT,
                                                             glxml.all_commands, just_libgl_commands,
                                                             all_commands_no_suffix,
                                                             GLEntryPoints.get_packed_enums())
    
                # Write the version as a comment before the first EP.
                cpp_comment = "\n// GL %s" % comment
                def_comment = "\n    ; GL %s" % comment
    
                libgl_ep_defs += [cpp_comment] + eps.export_defs
                libgl_ep_exports += [def_comment] + get_exports(all_libgl_commands)
                validation_protos += [cpp_comment] + eps_suffix.validation_protos
                ver_decls += [cpp_comment] + eps.decls
                ver_defs += [cpp_comment] + eps.defs
    
            ver_decls.append("} // extern \"C\"")
            ver_defs.append("} // extern \"C\"")
            annotation = "GL_%d" % major_version
            name = "Desktop GL %s.x" % major_version
    
            source_includes = TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES.format(annotation.lower(),
                                                                         major_version)
    
            # Entry point files
            write_file(annotation, name, TEMPLATE_ENTRY_POINT_HEADER, "\n".join(ver_decls), "h",
                       DESKTOP_GL_HEADER_INCLUDES, "libGL", "gl.xml")
            write_file(annotation, name, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(ver_defs), "cpp",
                       source_includes, "libGL", "gl.xml")
    
            # Validation files
            write_gl_validation_header("GL%s" % major_version, name, validation_protos, "gl.xml")
    
        # OpenCL
        clxml = registry_xml.RegistryXML('cl.xml')
    
        cl_validation_protos = []
        cl_decls = ["namespace cl\n{"]
        cl_defs = ["namespace cl\n{"]
        libcl_ep_defs = []
        libcl_windows_def_exports = []
        cl_commands = []
    
        for major_version, minor_version in registry_xml.CL_VERSIONS:
            version = "%d_%d" % (major_version, minor_version)
            annotation = "CL_%s" % version
            name_prefix = "CL_VERSION_"
    
            comment = version.replace("_", ".")
            feature_name = "%s%s" % (name_prefix, version)
    
            clxml.AddCommands(feature_name, version)
    
            cl_version_commands = clxml.commands[version]
            cl_commands += cl_version_commands
    
            # Spec revs may have no new commands.
            if not cl_version_commands:
                continue
    
            eps = CLEntryPoints(clxml, cl_version_commands)
    
            comment = "\n// CL %d.%d" % (major_version, minor_version)
            win_def_comment = "\n    ; CL %d.%d" % (major_version, minor_version)
    
            cl_decls += [comment] + eps.decls
            cl_defs += [comment] + eps.defs
            libcl_ep_defs += [comment] + eps.export_defs
            cl_validation_protos += [comment] + eps.validation_protos
            libcl_windows_def_exports += [win_def_comment] + get_exports(clxml.commands[version])
    
        clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl'])
        for extension_name, ext_cmd_names in sorted(clxml.ext_data.items()):
    
            # Extensions may have no new commands.
            if not ext_cmd_names:
                continue
    
            # Detect and filter duplicate extensions.
            eps = CLEntryPoints(clxml, ext_cmd_names)
    
            comment = "\n// %s" % extension_name
            win_def_comment = "\n    ; %s" % (extension_name)
    
            cl_commands += ext_cmd_names
    
            cl_decls += [comment] + eps.decls
            cl_defs += [comment] + eps.defs
            libcl_ep_defs += [comment] + eps.export_defs
            cl_validation_protos += [comment] + eps.validation_protos
            libcl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
    
            # Avoid writing out entry points defined by a prior extension.
            for dupe in clxml.ext_dupes[extension_name]:
                msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
                cl_defs.append(msg)
    
        cl_decls.append("}  // namespace cl")
        cl_defs.append("}  // namespace cl")
    
        write_file("cl", "CL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(cl_decls), "h",
                   LIBCL_HEADER_INCLUDES, "libGLESv2", "cl.xml")
        write_file("cl", "CL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(cl_defs), "cpp",
                   LIBCL_SOURCE_INCLUDES, "libGLESv2", "cl.xml")
        write_validation_header("CL", "CL", cl_validation_protos, "cl.xml",
                                TEMPLATE_CL_VALIDATION_HEADER)
        write_stubs_header("CL", "cl", "CL", "cl.xml", CL_STUBS_HEADER_PATH, clxml.all_commands,
                           cl_commands, CLEntryPoints.get_packed_enums(), CL_PACKED_TYPES)
    
        # EGL
        eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
    
        egl_validation_protos = []
        egl_decls = ["extern \"C\" {"]
        egl_defs = ["extern \"C\" {"]
        libegl_ep_defs = []
        libegl_windows_def_exports = []
        egl_commands = []
    
        for major_version, minor_version in registry_xml.EGL_VERSIONS:
            version = "%d_%d" % (major_version, minor_version)
            annotation = "EGL_%s" % version
            name_prefix = "EGL_VERSION_"
    
            comment = version.replace("_", ".")
            feature_name = "%s%s" % (name_prefix, version)
    
            eglxml.AddCommands(feature_name, version)
    
            egl_version_commands = eglxml.commands[version]
            egl_commands += egl_version_commands
    
            # Spec revs may have no new commands.
            if not egl_version_commands:
                continue
    
            eps = EGLEntryPoints(eglxml, egl_version_commands)
    
            comment = "\n// EGL %d.%d" % (major_version, minor_version)
            win_def_comment = "\n    ; EGL %d.%d" % (major_version, minor_version)
    
            egl_decls += [comment] + eps.decls
            egl_defs += [comment] + eps.defs
            libegl_ep_defs += [comment] + eps.export_defs
            egl_validation_protos += [comment] + eps.validation_protos
            libegl_windows_def_exports += [win_def_comment] + get_exports(eglxml.commands[version])
    
        egl_decls.append("} // extern \"C\"")
        egl_defs.append("} // extern \"C\"")
    
        write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_decls), "h",
                   EGL_HEADER_INCLUDES, "libGLESv2", "egl.xml")
        write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_defs), "cpp",
                   EGL_SOURCE_INCLUDES, "libGLESv2", "egl.xml")
        write_stubs_header("EGL", "egl", "EGL", "egl.xml", EGL_STUBS_HEADER_PATH, eglxml.all_commands,
                           egl_commands, EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
    
        eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
        egl_ext_decls = ["extern \"C\" {"]
        egl_ext_defs = ["extern \"C\" {"]
        egl_ext_commands = []
    
        for extension_name, ext_cmd_names in sorted(eglxml.ext_data.items()):
    
            # Extensions may have no new commands.
            if not ext_cmd_names:
                continue
    
            # Detect and filter duplicate extensions.
            eps = EGLEntryPoints(eglxml, ext_cmd_names)
    
            comment = "\n// %s" % extension_name
            win_def_comment = "\n    ; %s" % (extension_name)
    
            egl_ext_commands += ext_cmd_names
    
            egl_ext_decls += [comment] + eps.decls
            egl_ext_defs += [comment] + eps.defs
            libegl_ep_defs += [comment] + eps.export_defs
            egl_validation_protos += [comment] + eps.validation_protos
            libegl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
    
            # Avoid writing out entry points defined by a prior extension.
            for dupe in eglxml.ext_dupes[extension_name]:
                msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
                egl_ext_defs.append(msg)
    
        egl_ext_decls.append("} // extern \"C\"")
        egl_ext_defs.append("} // extern \"C\"")
    
        write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_ext_decls),
                   "h", EGL_EXT_HEADER_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
        write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_ext_defs),
                   "cpp", EGL_EXT_SOURCE_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
        write_validation_header("EGL", "EGL", egl_validation_protos, "egl.xml and egl_angle_ext.xml",
                                TEMPLATE_EGL_VALIDATION_HEADER)
        write_stubs_header("EGL", "egl_ext", "EXT extension", "egl.xml and egl_angle_ext.xml",
                           EGL_EXT_STUBS_HEADER_PATH, eglxml.all_commands, egl_ext_commands,
                           EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
    
        # WGL
        wglxml = registry_xml.RegistryXML('wgl.xml')
    
        name_prefix = "WGL_VERSION_"
        version = "1_0"
        comment = version.replace("_", ".")
        feature_name = "{}{}".format(name_prefix, version)
        wglxml.AddCommands(feature_name, version)
        wgl_commands = wglxml.commands[version]
    
        wgl_commands = [cmd if cmd[:3] == 'wgl' else 'wgl' + cmd for cmd in wgl_commands]
    
        # Write the version as a comment before the first EP.
        libgl_ep_exports.append("\n    ; WGL %s" % comment)
    
        # Other versions of these functions are used
        wgl_commands.remove("wglUseFontBitmaps")
        wgl_commands.remove("wglUseFontOutlines")
    
        libgl_ep_exports += get_exports(wgl_commands)
        extension_decls.append("} // extern \"C\"")
        extension_defs.append("} // extern \"C\"")
    
        write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_HEADER,
                   "\n".join([item for item in extension_decls]), "h", GLES_EXT_HEADER_INCLUDES,
                   "libGLESv2", "gl.xml and gl_angle_ext.xml")
        write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_SOURCE,
                   "\n".join([item for item in extension_defs]), "cpp", GLES_EXT_SOURCE_INCLUDES,
                   "libGLESv2", "gl.xml and gl_angle_ext.xml")
    
        write_gl_validation_header("ESEXT", "ES extension", ext_validation_protos,
                                   "gl.xml and gl_angle_ext.xml")
        write_capture_header("ext", "extension", ext_capture_protos, ext_capture_pointer_funcs)
        write_capture_source("ext", "ESEXT", "extension", ext_capture_methods)
    
        write_context_api_decls(glesdecls, "gles")
        write_context_api_decls(desktop_gl_decls, "gl")
    
        # Entry point enum
        cl_cmd_names = [strip_api_prefix(cmd) for cmd in clxml.all_cmd_names.get_all_commands()]
        egl_cmd_names = [strip_api_prefix(cmd) for cmd in eglxml.all_cmd_names.get_all_commands()]
        gles_cmd_names = ["Invalid"
                         ] + [strip_api_prefix(cmd) for cmd in xml.all_cmd_names.get_all_commands()]
        gl_cmd_names = [strip_api_prefix(cmd) for cmd in glxml.all_cmd_names.get_all_commands()]
        wgl_cmd_names = [strip_api_prefix(cmd) for cmd in wglxml.all_cmd_names.get_all_commands()]
        unsorted_enums = [("CL%s" % cmd, "cl%s" % cmd) for cmd in cl_cmd_names] + [
            ("EGL%s" % cmd, "egl%s" % cmd) for cmd in egl_cmd_names
        ] + [("GL%s" % cmd, "gl%s" % cmd) for cmd in set(gles_cmd_names + gl_cmd_names)
            ] + [("WGL%s" % cmd, "wgl%s" % cmd) for cmd in wgl_cmd_names]
        all_enums = sorted(unsorted_enums)
    
        entry_points_enum_header = TEMPLATE_ENTRY_POINTS_ENUM_HEADER.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            lib="GL/GLES",
            entry_points_list=",\n".join(["    " + enum for (enum, _) in all_enums]))
    
        entry_points_enum_header_path = path_to("common", "entry_points_enum_autogen.h")
        with open(entry_points_enum_header_path, "w") as out:
            out.write(entry_points_enum_header)
            out.close()
    
        entry_points_cases = [
            TEMPLATE_ENTRY_POINTS_NAME_CASE.format(enum=enum, cmd=cmd) for (enum, cmd) in all_enums
        ]
        entry_points_enum_source = TEMPLATE_ENTRY_POINTS_ENUM_SOURCE.format(
            script_name=os.path.basename(sys.argv[0]),
            data_source_name="gl.xml and gl_angle_ext.xml",
            lib="GL/GLES",
            entry_points_name_cases="\n".join(entry_points_cases))
    
        entry_points_enum_source_path = path_to("common", "entry_points_enum_autogen.cpp")
        with open(entry_points_enum_source_path, "w") as out:
            out.write(entry_points_enum_source)
            out.close()
    
        write_export_files("\n".join([item for item in libgles_ep_defs]), LIBGLESV2_EXPORT_INCLUDES,
                           "gl.xml and gl_angle_ext.xml", "libGLESv2", "OpenGL ES")
        write_export_files("\n".join([item for item in libgl_ep_defs]), LIBGL_EXPORT_INCLUDES,
                           "gl.xml and wgl.xml", "libGL", "Windows GL")
        write_export_files("\n".join([item for item in libegl_ep_defs]),
                           LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE, "egl.xml and egl_angle_ext.xml",
                           "libEGL", "EGL")
        write_export_files("\n".join([item for item in libcl_ep_defs]), LIBCL_EXPORT_INCLUDES,
                           "cl.xml", "libOpenCL", "CL")
    
        libgles_ep_exports += get_egl_exports()
    
        everything = "Khronos and ANGLE XML files"
    
        for lib in ["libGLESv2" + suffix for suffix in ["", "_no_capture", "_with_capture"]]:
            write_windows_def_file(everything, lib, lib, "libGLESv2", libgles_ep_exports)
        write_windows_def_file(everything, "libGL", "openGL32", "libGL", libgl_ep_exports)
        write_windows_def_file("egl.xml and egl_angle_ext.xml", "libEGL", "libEGL", "libEGL",
                               libegl_windows_def_exports)
    
        all_gles_param_types = sorted(GLEntryPoints.all_param_types)
        write_capture_helper_header(all_gles_param_types)
        write_capture_helper_source(all_gles_param_types)
        write_capture_replay_source(apis.GLES, xml.all_commands, all_commands_no_suffix,
                                    GLEntryPoints.get_packed_enums(), [])
    
    
    if __name__ == '__main__':
        sys.exit(main())