• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python3
2#
3# Copyright 2017 The ANGLE Project Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6#
7# generate_entry_points.py:
8#   Generates the OpenGL bindings and entry point layers for ANGLE.
9#   NOTE: don't run this script directly. Run scripts/run_code_generation.py.
10
11import sys, os, pprint, json
12import registry_xml
13from registry_xml import apis, script_relative, strip_api_prefix
14
15# Paths
16CL_STUBS_HEADER_PATH = "../src/libGLESv2/cl_stubs_autogen.h"
17EGL_GET_LABELED_OBJECT_DATA_PATH = "../src/libGLESv2/egl_get_labeled_object_data.json"
18EGL_STUBS_HEADER_PATH = "../src/libGLESv2/egl_stubs_autogen.h"
19EGL_EXT_STUBS_HEADER_PATH = "../src/libGLESv2/egl_ext_stubs_autogen.h"
20
21# List of GLES1 extensions for which we don't need to add Context.h decls.
22GLES1_NO_CONTEXT_DECL_EXTENSIONS = [
23    "GL_OES_framebuffer_object",
24]
25
26# This is a list of exceptions for entry points which don't want to have
27# the EVENT macro. This is required for some debug marker entry points.
28NO_EVENT_MARKER_EXCEPTIONS_LIST = sorted([
29    "glPushGroupMarkerEXT",
30    "glPopGroupMarkerEXT",
31    "glInsertEventMarkerEXT",
32])
33
34# glRenderbufferStorageMultisampleEXT aliases glRenderbufferStorageMultisample on desktop GL, and is
35# marked as such in the registry.  However, that is not correct for GLES where this entry point
36# comes from GL_EXT_multisampled_render_to_texture which is never promoted to core GLES.
37ALIASING_EXCEPTIONS = [
38    'glRenderbufferStorageMultisampleEXT',
39    'renderbufferStorageMultisampleEXT',
40]
41
42# These are the entry points which potentially are used first by an application
43# and require that the back ends are initialized before the front end is called.
44INIT_DICT = {
45    "clGetPlatformIDs": "false",
46    "clGetPlatformInfo": "false",
47    "clGetDeviceIDs": "false",
48    "clCreateContext": "false",
49    "clCreateContextFromType": "false",
50    "clIcdGetPlatformIDsKHR": "true",
51}
52
53TEMPLATE_ENTRY_POINT_HEADER = """\
54// GENERATED FILE - DO NOT EDIT.
55// Generated by {script_name} using data from {data_source_name}.
56//
57// Copyright 2020 The ANGLE Project Authors. All rights reserved.
58// Use of this source code is governed by a BSD-style license that can be
59// found in the LICENSE file.
60//
61// entry_points_{annotation_lower}_autogen.h:
62//   Defines the {comment} entry points.
63
64#ifndef {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
65#define {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
66
67{includes}
68
69{entry_points}
70
71#endif  // {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
72"""
73
74TEMPLATE_ENTRY_POINT_SOURCE = """\
75// GENERATED FILE - DO NOT EDIT.
76// Generated by {script_name} using data from {data_source_name}.
77//
78// Copyright 2020 The ANGLE Project Authors. All rights reserved.
79// Use of this source code is governed by a BSD-style license that can be
80// found in the LICENSE file.
81//
82// entry_points_{annotation_lower}_autogen.cpp:
83//   Defines the {comment} entry points.
84
85{includes}
86
87{entry_points}
88"""
89
90TEMPLATE_ENTRY_POINTS_ENUM_HEADER = """\
91// GENERATED FILE - DO NOT EDIT.
92// Generated by {script_name} using data from {data_source_name}.
93//
94// Copyright 2020 The ANGLE Project Authors. All rights reserved.
95// Use of this source code is governed by a BSD-style license that can be
96// found in the LICENSE file.
97//
98// entry_points_enum_autogen.h:
99//   Defines the {lib} entry points enumeration.
100
101#ifndef COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
102#define COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
103
104namespace angle
105{{
106enum class EntryPoint
107{{
108{entry_points_list}
109}};
110
111const char *GetEntryPointName(EntryPoint ep);
112}}  // namespace angle
113#endif  // COMMON_ENTRY_POINTS_ENUM_AUTOGEN_H_
114"""
115
116TEMPLATE_ENTRY_POINTS_NAME_CASE = """\
117        case EntryPoint::{enum}:
118            return "{cmd}";"""
119
120TEMPLATE_ENTRY_POINTS_ENUM_SOURCE = """\
121// GENERATED FILE - DO NOT EDIT.
122// Generated by {script_name} using data from {data_source_name}.
123//
124// Copyright 2020 The ANGLE Project Authors. All rights reserved.
125// Use of this source code is governed by a BSD-style license that can be
126// found in the LICENSE file.
127//
128// entry_points_enum_autogen.cpp:
129//   Helper methods for the {lib} entry points enumeration.
130
131#include "common/entry_points_enum_autogen.h"
132
133#include "common/debug.h"
134
135namespace angle
136{{
137const char *GetEntryPointName(EntryPoint ep)
138{{
139    switch (ep)
140    {{
141{entry_points_name_cases}
142        default:
143            UNREACHABLE();
144            return "error";
145    }}
146}}
147}}  // namespace angle
148"""
149
150TEMPLATE_LIB_ENTRY_POINT_SOURCE = """\
151// GENERATED FILE - DO NOT EDIT.
152// Generated by {script_name} using data from {data_source_name}.
153//
154// Copyright 2020 The ANGLE Project Authors. All rights reserved.
155// Use of this source code is governed by a BSD-style license that can be
156// found in the LICENSE file.
157//
158// {lib_name}_autogen.cpp: Implements the exported {lib_description} functions.
159
160{includes}
161extern "C" {{
162{entry_points}
163}} // extern "C"
164"""
165
166TEMPLATE_ENTRY_POINT_DECL = """{angle_export}{return_type} {export_def} {name}({params});"""
167
168TEMPLATE_GLES_ENTRY_POINT_NO_RETURN = """\
169void GL_APIENTRY GL_{name}({params})
170{{
171    Context *context = {context_getter};
172    {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
173
174    if ({valid_context_check})
175    {{{packed_gl_enum_conversions}
176        std::unique_lock<angle::GlobalMutex> shareContextLock = GetContextLock(context);
177        bool isCallValid = (context->skipValidation() || Validate{name}({validate_params}));
178        if (isCallValid)
179        {{
180            context->{name_lower_no_suffix}({internal_params});
181        }}
182        ANGLE_CAPTURE({name}, isCallValid, {capture_params});
183    }}
184    else
185    {{
186        {constext_lost_error_generator}
187    }}
188}}
189"""
190
191TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN = """\
192{return_type} GL_APIENTRY GL_{name}({params})
193{{
194    Context *context = {context_getter};
195    {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
196
197    {return_type} returnValue;
198    if ({valid_context_check})
199    {{{packed_gl_enum_conversions}
200        std::unique_lock<angle::GlobalMutex> shareContextLock = GetContextLock(context);
201        bool isCallValid = (context->skipValidation() || Validate{name}({validate_params}));
202        if (isCallValid)
203        {{
204            returnValue = context->{name_lower_no_suffix}({internal_params});
205        }}
206        else
207        {{
208            returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
209    }}
210        ANGLE_CAPTURE({name}, isCallValid, {capture_params}, returnValue);
211    }}
212    else
213    {{
214        {constext_lost_error_generator}
215        returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
216    }}
217    return returnValue;
218}}
219"""
220
221TEMPLATE_EGL_ENTRY_POINT_NO_RETURN = """\
222void EGLAPIENTRY EGL_{name}({params})
223{{
224    {preamble}
225    {entry_point_locks}
226    EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
227
228    Thread *thread = egl::GetCurrentThread();
229
230    {packed_gl_enum_conversions}
231
232    ANGLE_EGL_VALIDATE_VOID(thread, {name}, {labeled_object}, {internal_params});
233
234    {name}(thread{comma_if_needed}{internal_params});
235}}
236"""
237
238TEMPLATE_EGL_ENTRY_POINT_NO_RETURN_CUSTOM = """\
239void EGLAPIENTRY EGL_{name}({params})
240{{
241    {name}({internal_params});
242}}
243"""
244
245TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN = """\
246{return_type} EGLAPIENTRY EGL_{name}({params})
247{{
248    {preamble}
249    {entry_point_locks}
250    EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
251
252    Thread *thread = egl::GetCurrentThread();
253
254    {packed_gl_enum_conversions}
255
256    ANGLE_EGL_VALIDATE(thread, {name}, {labeled_object}, {return_type}{comma_if_needed}{internal_params});
257
258    return {name}(thread{comma_if_needed}{internal_params});
259}}
260"""
261
262TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN_CUSTOM = """\
263{return_type} EGLAPIENTRY EGL_{name}({params})
264{{
265    return {name}({internal_params});
266}}
267"""
268
269TEMPLATE_CL_ENTRY_POINT_NO_RETURN = """\
270void CL_API_CALL cl{name}({params})
271{{
272    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
273
274    {packed_gl_enum_conversions}
275
276    ANGLE_CL_VALIDATE_VOID({name}{comma_if_needed}{internal_params});
277
278    {name}({internal_params});
279}}
280"""
281
282TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR = """\
283cl_int CL_API_CALL cl{name}({params})
284{{{initialization}
285    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
286
287    {packed_gl_enum_conversions}
288
289    ANGLE_CL_VALIDATE_ERROR({name}{comma_if_needed}{internal_params});
290
291    return {name}({internal_params});
292}}
293"""
294
295TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET = """\
296{return_type} CL_API_CALL cl{name}({params})
297{{{initialization}
298    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
299
300    {packed_gl_enum_conversions}
301
302    ANGLE_CL_VALIDATE_ERRCODE_RET({name}{comma_if_needed}{internal_params});
303
304    cl_int errorCode = CL_SUCCESS;
305    {return_type} object = {name}({internal_params}, errorCode);
306
307    ASSERT((errorCode == CL_SUCCESS) == (object != nullptr));
308    if (errcode_ret != nullptr)
309    {{
310        *errcode_ret = errorCode;
311    }}
312    return object;
313}}
314"""
315
316TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER = """\
317{return_type} CL_API_CALL cl{name}({params})
318{{{initialization}
319    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
320
321    {packed_gl_enum_conversions}
322
323    ANGLE_CL_VALIDATE_POINTER({name}{comma_if_needed}{internal_params});
324
325    return {name}({internal_params});
326}}
327"""
328
329TEMPLATE_CL_STUBS_HEADER = """\
330// GENERATED FILE - DO NOT EDIT.
331// Generated by {script_name} using data from {data_source_name}.
332//
333// Copyright 2021 The ANGLE Project Authors. All rights reserved.
334// Use of this source code is governed by a BSD-style license that can be
335// found in the LICENSE file.
336//
337// {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
338
339#ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
340#define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
341
342#include "libANGLE/CLtypes.h"
343
344namespace cl
345{{
346{stubs}
347}}  // namespace cl
348#endif  // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
349"""
350
351TEMPLATE_EGL_STUBS_HEADER = """\
352// GENERATED FILE - DO NOT EDIT.
353// Generated by {script_name} using data from {data_source_name}.
354//
355// Copyright 2020 The ANGLE Project Authors. All rights reserved.
356// Use of this source code is governed by a BSD-style license that can be
357// found in the LICENSE file.
358//
359// {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
360
361#ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
362#define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
363
364#include <EGL/egl.h>
365#include <EGL/eglext.h>
366
367#include "common/PackedEGLEnums_autogen.h"
368
369namespace gl
370{{
371class Context;
372}}  // namespace gl
373
374namespace egl
375{{
376class AttributeMap;
377class Device;
378class Display;
379class Image;
380class Stream;
381class Surface;
382class Sync;
383class Thread;
384struct Config;
385
386{stubs}
387}}  // namespace egl
388#endif  // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
389"""
390
391CONTEXT_HEADER = """\
392// GENERATED FILE - DO NOT EDIT.
393// Generated by {script_name} using data from {data_source_name}.
394//
395// Copyright 2020 The ANGLE Project Authors. All rights reserved.
396// Use of this source code is governed by a BSD-style license that can be
397// found in the LICENSE file.
398//
399// Context_{annotation_lower}_autogen.h: Creates a macro for interfaces in Context.
400
401#ifndef ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
402#define ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
403
404#define ANGLE_{annotation_upper}_CONTEXT_API \\
405{interface}
406
407#endif // ANGLE_CONTEXT_API_{version}_AUTOGEN_H_
408"""
409
410CONTEXT_DECL_FORMAT = """    {return_type} {name_lower_no_suffix}({internal_params}){maybe_const}; \\"""
411
412TEMPLATE_CL_ENTRY_POINT_EXPORT = """\
413{return_type} CL_API_CALL cl{name}({params})
414{{
415    return cl::GetDispatch().cl{name}({internal_params});
416}}
417"""
418
419TEMPLATE_GL_ENTRY_POINT_EXPORT = """\
420{return_type} GL_APIENTRY gl{name}({params})
421{{
422    return GL_{name}({internal_params});
423}}
424"""
425
426TEMPLATE_EGL_ENTRY_POINT_EXPORT = """\
427{return_type} EGLAPIENTRY egl{name}({params})
428{{
429    EnsureEGLLoaded();
430    return EGL_{name}({internal_params});
431}}
432"""
433
434TEMPLATE_GLEXT_FUNCTION_POINTER = """typedef {return_type}(GL_APIENTRYP PFN{name_upper}PROC)({params});"""
435TEMPLATE_GLEXT_FUNCTION_PROTOTYPE = """{apicall} {return_type}GL_APIENTRY {name}({params});"""
436
437TEMPLATE_GL_VALIDATION_HEADER = """\
438// GENERATED FILE - DO NOT EDIT.
439// Generated by {script_name} using data from {data_source_name}.
440//
441// Copyright 2020 The ANGLE Project Authors. All rights reserved.
442// Use of this source code is governed by a BSD-style license that can be
443// found in the LICENSE file.
444//
445// validation{annotation}_autogen.h:
446//   Validation functions for the OpenGL {comment} entry points.
447
448#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
449#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
450
451#include "common/entry_points_enum_autogen.h"
452#include "common/PackedEnums.h"
453
454namespace gl
455{{
456class Context;
457
458{prototypes}
459}}  // namespace gl
460
461#endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
462"""
463
464TEMPLATE_CL_VALIDATION_HEADER = """\
465// GENERATED FILE - DO NOT EDIT.
466// Generated by {script_name} using data from {data_source_name}.
467//
468// Copyright 2021 The ANGLE Project Authors. All rights reserved.
469// Use of this source code is governed by a BSD-style license that can be
470// found in the LICENSE file.
471//
472// validation{annotation}_autogen.h:
473//   Validation functions for the {comment} entry points.
474
475#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
476#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
477
478#include "libANGLE/validationCL.h"
479
480namespace cl
481{{
482{prototypes}
483}}  // namespace cl
484
485#endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
486"""
487
488TEMPLATE_EGL_VALIDATION_HEADER = """\
489// GENERATED FILE - DO NOT EDIT.
490// Generated by {script_name} using data from {data_source_name}.
491//
492// Copyright 2020 The ANGLE Project Authors. All rights reserved.
493// Use of this source code is governed by a BSD-style license that can be
494// found in the LICENSE file.
495//
496// validation{annotation}_autogen.h:
497//   Validation functions for the {comment} entry points.
498
499#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
500#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
501
502#include "libANGLE/validationEGL.h"
503
504namespace egl
505{{
506{prototypes}
507}}  // namespace egl
508
509#endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
510"""
511
512TEMPLATE_CAPTURE_HEADER = """\
513// GENERATED FILE - DO NOT EDIT.
514// Generated by {script_name} using data from {data_source_name}.
515//
516// Copyright 2020 The ANGLE Project Authors. All rights reserved.
517// Use of this source code is governed by a BSD-style license that can be
518// found in the LICENSE file.
519//
520// capture_gles_{annotation_lower}_autogen.h:
521//   Capture functions for the OpenGL ES {comment} entry points.
522
523#ifndef LIBANGLE_CAPTURE_GLES_{annotation_upper}_AUTOGEN_H_
524#define LIBANGLE_CAPTURE_GLES_{annotation_upper}_AUTOGEN_H_
525
526#include "common/PackedEnums.h"
527#include "libANGLE/capture/FrameCapture.h"
528
529namespace gl
530{{
531{prototypes}
532}}  // namespace gl
533
534#endif  // LIBANGLE_CAPTURE_GLES_{annotation_upper}_AUTOGEN_H_
535"""
536
537TEMPLATE_CAPTURE_SOURCE = """\
538// GENERATED FILE - DO NOT EDIT.
539// Generated by {script_name} using data from {data_source_name}.
540//
541// Copyright 2020 The ANGLE Project Authors. All rights reserved.
542// Use of this source code is governed by a BSD-style license that can be
543// found in the LICENSE file.
544//
545// capture_gles_{annotation_with_dash}_autogen.cpp:
546//   Capture functions for the OpenGL ES {comment} entry points.
547
548#include "libANGLE/capture/capture_gles_{annotation_with_dash}_autogen.h"
549
550#include "libANGLE/Context.h"
551#include "libANGLE/capture/FrameCapture.h"
552#include "libANGLE/capture/gl_enum_utils.h"
553#include "libANGLE/validation{annotation_no_dash}.h"
554
555using namespace angle;
556
557namespace gl
558{{
559{capture_methods}
560}}  // namespace gl
561"""
562
563TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE = """
564CallCapture Capture{short_name}({params_with_type}, {return_value_type_original} returnValue)
565{{
566    ParamBuffer paramBuffer;
567
568    {parameter_captures}
569
570    ParamCapture returnValueCapture("returnValue", ParamType::T{return_value_type_custom});
571    InitParamValue(ParamType::T{return_value_type_custom}, returnValue, &returnValueCapture.value);
572    paramBuffer.addReturnValue(std::move(returnValueCapture));
573
574    return CallCapture(angle::EntryPoint::GL{short_name}, std::move(paramBuffer));
575}}
576"""
577
578TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE = """
579CallCapture Capture{short_name}({params_with_type})
580{{
581    ParamBuffer paramBuffer;
582
583    {parameter_captures}
584
585    return CallCapture(angle::EntryPoint::GL{short_name}, std::move(paramBuffer));
586}}
587"""
588
589TEMPLATE_PARAMETER_CAPTURE_VALUE = """paramBuffer.addValueParam("{name}", ParamType::T{type}, {name});"""
590
591TEMPLATE_PARAMETER_CAPTURE_GL_ENUM = """paramBuffer.addEnumParam("{name}", GLenumGroup::{group}, ParamType::T{type}, {name});"""
592
593TEMPLATE_PARAMETER_CAPTURE_POINTER = """
594    if (isCallValid)
595    {{
596        ParamCapture {name}Param("{name}", ParamType::T{type});
597        InitParamValue(ParamType::T{type}, {name}, &{name}Param.value);
598        {capture_name}({params}, &{name}Param);
599        paramBuffer.addParam(std::move({name}Param));
600    }}
601    else
602    {{
603        ParamCapture {name}Param("{name}", ParamType::T{type});
604        InitParamValue(ParamType::T{type}, static_cast<{cast_type}>(nullptr), &{name}Param.value);
605        paramBuffer.addParam(std::move({name}Param));
606    }}
607"""
608
609TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC = """void {name}({params});"""
610
611TEMPLATE_CAPTURE_REPLAY_SOURCE = """\
612// GENERATED FILE - DO NOT EDIT.
613// Generated by {script_name} using data from {data_source_name}.
614//
615// Copyright 2020 The ANGLE Project Authors. All rights reserved.
616// Use of this source code is governed by a BSD-style license that can be
617// found in the LICENSE file.
618//
619// frame_capture_replay_autogen.cpp:
620//   Util function to dispatch captured GL calls through Context and replay them.
621
622#include "angle_gl.h"
623
624#include "common/debug.h"
625#include "common/debug.h"
626#include "libANGLE/Context.h"
627#include "libANGLE/Context.inl.h"
628#include "libANGLE/capture/FrameCapture.h"
629
630using namespace gl;
631
632namespace angle
633{{
634
635void FrameCaptureShared::ReplayCall(gl::Context *context,
636                              ReplayContext *replayContext,
637                              const CallCapture &call)
638{{
639    const ParamBuffer &params = call.params;
640    switch (call.entryPoint)
641    {{
642        {call_replay_cases}
643        default:
644            UNREACHABLE();
645    }}
646}}
647
648}}  // namespace angle
649
650"""
651
652TEMPLATE_CAPTURE_REPLAY_CALL_CASE = """case angle::EntryPoint::GL{entry_point}:
653    context->{context_call}({param_value_access});break;"""
654
655POINTER_FORMAT = "0x%016\" PRIxPTR \""
656UNSIGNED_LONG_LONG_FORMAT = "%llu"
657HEX_LONG_LONG_FORMAT = "0x%llX"
658
659FORMAT_DICT = {
660    "GLbitfield": "%s",
661    "GLboolean": "%s",
662    "GLbyte": "%d",
663    "GLclampx": "0x%X",
664    "GLDEBUGPROC": POINTER_FORMAT,
665    "GLDEBUGPROCKHR": POINTER_FORMAT,
666    "GLdouble": "%f",
667    "GLeglClientBufferEXT": POINTER_FORMAT,
668    "GLeglImageOES": POINTER_FORMAT,
669    "GLenum": "%s",
670    "GLfixed": "0x%X",
671    "GLfloat": "%f",
672    "GLint": "%d",
673    "GLintptr": UNSIGNED_LONG_LONG_FORMAT,
674    "GLshort": "%d",
675    "GLsizei": "%d",
676    "GLsizeiptr": UNSIGNED_LONG_LONG_FORMAT,
677    "GLsync": POINTER_FORMAT,
678    "GLubyte": "%d",
679    "GLuint": "%u",
680    "GLuint64": UNSIGNED_LONG_LONG_FORMAT,
681    "GLushort": "%u",
682    "int": "%d",
683    # EGL-specific types
684    "EGLConfig": POINTER_FORMAT,
685    "EGLContext": POINTER_FORMAT,
686    "EGLDisplay": POINTER_FORMAT,
687    "EGLSurface": POINTER_FORMAT,
688    "EGLSync": POINTER_FORMAT,
689    "EGLNativeDisplayType": POINTER_FORMAT,
690    "EGLNativePixmapType": POINTER_FORMAT,
691    "EGLNativeWindowType": POINTER_FORMAT,
692    "EGLClientBuffer": POINTER_FORMAT,
693    "EGLenum": "0x%X",
694    "EGLint": "%d",
695    "EGLImage": POINTER_FORMAT,
696    "EGLTime": UNSIGNED_LONG_LONG_FORMAT,
697    "EGLGetBlobFuncANDROID": POINTER_FORMAT,
698    "EGLSetBlobFuncANDROID": POINTER_FORMAT,
699    "EGLuint64KHR": UNSIGNED_LONG_LONG_FORMAT,
700    "EGLSyncKHR": POINTER_FORMAT,
701    "EGLnsecsANDROID": UNSIGNED_LONG_LONG_FORMAT,
702    "EGLDeviceEXT": POINTER_FORMAT,
703    "EGLDEBUGPROCKHR": POINTER_FORMAT,
704    "EGLObjectKHR": POINTER_FORMAT,
705    "EGLLabelKHR": POINTER_FORMAT,
706    "EGLTimeKHR": UNSIGNED_LONG_LONG_FORMAT,
707    "EGLImageKHR": POINTER_FORMAT,
708    "EGLStreamKHR": POINTER_FORMAT,
709    "EGLFrameTokenANGLE": HEX_LONG_LONG_FORMAT,
710    # WGL-specific types
711    "BOOL": "%u",
712    "DWORD": POINTER_FORMAT,
713    "FLOAT": "%f",
714    "HDC": POINTER_FORMAT,
715    "HENHMETAFILE": POINTER_FORMAT,
716    "HGLRC": POINTER_FORMAT,
717    "LPCSTR": POINTER_FORMAT,
718    "LPGLYPHMETRICSFLOAT": POINTER_FORMAT,
719    "UINT": "%u",
720    # CL-specific types
721    "size_t": "%zu",
722    "cl_char": "%hhd",
723    "cl_uchar": "%hhu",
724    "cl_short": "%hd",
725    "cl_ushort": "%hu",
726    "cl_int": "%d",
727    "cl_uint": "%u",
728    "cl_long": "%lld",
729    "cl_ulong": "%llu",
730    "cl_half": "%hu",
731    "cl_float": "%f",
732    "cl_double": "%f",
733    "cl_platform_id": POINTER_FORMAT,
734    "cl_device_id": POINTER_FORMAT,
735    "cl_context": POINTER_FORMAT,
736    "cl_command_queue": POINTER_FORMAT,
737    "cl_mem": POINTER_FORMAT,
738    "cl_program": POINTER_FORMAT,
739    "cl_kernel": POINTER_FORMAT,
740    "cl_event": POINTER_FORMAT,
741    "cl_sampler": POINTER_FORMAT,
742    "cl_bool": "%u",
743    "cl_bitfield": "%llu",
744    "cl_properties": "%llu",
745    "cl_device_type": "%llu",
746    "cl_platform_info": "%u",
747    "cl_device_info": "%u",
748    "cl_device_fp_config": "%llu",
749    "cl_device_mem_cache_type": "%u",
750    "cl_device_local_mem_type": "%u",
751    "cl_device_exec_capabilities": "%llu",
752    "cl_device_svm_capabilities": "%llu",
753    "cl_command_queue_properties": "%llu",
754    "cl_device_partition_property": "%zu",
755    "cl_device_affinity_domain": "%llu",
756    "cl_context_properties": "%zu",
757    "cl_context_info": "%u",
758    "cl_queue_properties": "%llu",
759    "cl_command_queue_info": "%u",
760    "cl_channel_order": "%u",
761    "cl_channel_type": "%u",
762    "cl_mem_flags": "%llu",
763    "cl_svm_mem_flags": "%llu",
764    "cl_mem_object_type": "%u",
765    "cl_mem_info": "%u",
766    "cl_mem_migration_flags": "%llu",
767    "cl_mem_properties": "%llu",
768    "cl_image_info": "%u",
769    "cl_buffer_create_type": "%u",
770    "cl_addressing_mode": "%u",
771    "cl_filter_mode": "%u",
772    "cl_sampler_info": "%u",
773    "cl_map_flags": "%llu",
774    "cl_pipe_properties": "%zu",
775    "cl_pipe_info": "%u",
776    "cl_program_info": "%u",
777    "cl_program_build_info": "%u",
778    "cl_program_binary_type": "%u",
779    "cl_build_status": "%d",
780    "cl_kernel_info": "%u",
781    "cl_kernel_arg_info": "%u",
782    "cl_kernel_arg_address_qualifier": "%u",
783    "cl_kernel_arg_access_qualifier": "%u",
784    "cl_kernel_arg_type_qualifier": "%llu",
785    "cl_kernel_work_group_info": "%u",
786    "cl_kernel_sub_group_info": "%u",
787    "cl_event_info": "%u",
788    "cl_command_type": "%u",
789    "cl_profiling_info": "%u",
790    "cl_sampler_properties": "%llu",
791    "cl_kernel_exec_info": "%u",
792    "cl_device_atomic_capabilities": "%llu",
793    "cl_khronos_vendor_id": "%u",
794    "cl_version": "%u",
795    "cl_device_device_enqueue_capabilities": "%llu",
796}
797
798TEMPLATE_HEADER_INCLUDES = """\
799#include <GLES{major}/gl{major}{minor}.h>
800#include <export.h>"""
801
802TEMPLATE_SOURCES_INCLUDES = """\
803#include "libGLESv2/entry_points_{header_version}_autogen.h"
804
805#include "common/entry_points_enum_autogen.h"
806#include "libANGLE/Context.h"
807#include "libANGLE/Context.inl.h"
808#include "libANGLE/capture/capture_{header_version}_autogen.h"
809#include "libANGLE/capture/gl_enum_utils.h"
810#include "libANGLE/validation{validation_header_version}.h"
811#include "libANGLE/entry_points_utils.h"
812#include "libGLESv2/global_state.h"
813
814using namespace gl;
815"""
816
817GLES_EXT_HEADER_INCLUDES = TEMPLATE_HEADER_INCLUDES.format(
818    major="", minor="") + """
819#include <GLES/glext.h>
820#include <GLES2/gl2.h>
821#include <GLES2/gl2ext.h>
822#include <GLES3/gl32.h>
823"""
824
825GLES_EXT_SOURCE_INCLUDES = TEMPLATE_SOURCES_INCLUDES.format(
826    header_version="gles_ext", validation_header_version="ESEXT") + """
827#include "libANGLE/capture/capture_gles_1_0_autogen.h"
828#include "libANGLE/capture/capture_gles_2_0_autogen.h"
829#include "libANGLE/capture/capture_gles_3_0_autogen.h"
830#include "libANGLE/capture/capture_gles_3_1_autogen.h"
831#include "libANGLE/capture/capture_gles_3_2_autogen.h"
832#include "libANGLE/validationES1.h"
833#include "libANGLE/validationES2.h"
834#include "libANGLE/validationES3.h"
835#include "libANGLE/validationES31.h"
836#include "libANGLE/validationES32.h"
837
838using namespace gl;
839"""
840
841DESKTOP_GL_HEADER_INCLUDES = """\
842#include <export.h>
843#include "angle_gl.h"
844"""
845
846TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES = """\
847#include "libGL/entry_points_{}_autogen.h"
848
849#include "libANGLE/Context.h"
850#include "libANGLE/Context.inl.h"
851#include "libANGLE/capture/gl_enum_utils.h"
852#include "libANGLE/validationEGL.h"
853#include "libANGLE/validationES.h"
854#include "libANGLE/validationES1.h"
855#include "libANGLE/validationES2.h"
856#include "libANGLE/validationES3.h"
857#include "libANGLE/validationES31.h"
858#include "libANGLE/validationES32.h"
859#include "libANGLE/validationESEXT.h"
860#include "libANGLE/validationGL{}_autogen.h"
861#include "libANGLE/entry_points_utils.h"
862#include "libGLESv2/global_state.h"
863
864using namespace gl;
865"""
866
867EGL_HEADER_INCLUDES = """\
868#include <EGL/egl.h>
869#include <export.h>
870"""
871
872EGL_SOURCE_INCLUDES = """\
873#include "libGLESv2/entry_points_egl_autogen.h"
874
875#include "libANGLE/entry_points_utils.h"
876#include "libANGLE/validationEGL_autogen.h"
877#include "libGLESv2/egl_stubs_autogen.h"
878#include "libGLESv2/egl_ext_stubs_autogen.h"
879#include "libGLESv2/global_state.h"
880
881using namespace egl;
882"""
883
884EGL_EXT_HEADER_INCLUDES = """\
885#include <EGL/egl.h>
886#include <EGL/eglext.h>
887#include <export.h>
888"""
889
890EGL_EXT_SOURCE_INCLUDES = """\
891#include "libGLESv2/entry_points_egl_ext_autogen.h"
892
893#include "libANGLE/entry_points_utils.h"
894#include "libANGLE/validationEGL_autogen.h"
895#include "libGLESv2/egl_ext_stubs_autogen.h"
896#include "libGLESv2/global_state.h"
897
898using namespace egl;
899"""
900
901LIBCL_EXPORT_INCLUDES = """
902#include "libOpenCL/dispatch.h"
903"""
904
905LIBGLESV2_EXPORT_INCLUDES = """
906#include "angle_gl.h"
907
908#include "libGLESv2/entry_points_gles_1_0_autogen.h"
909#include "libGLESv2/entry_points_gles_2_0_autogen.h"
910#include "libGLESv2/entry_points_gles_3_0_autogen.h"
911#include "libGLESv2/entry_points_gles_3_1_autogen.h"
912#include "libGLESv2/entry_points_gles_3_2_autogen.h"
913#include "libGLESv2/entry_points_gles_ext_autogen.h"
914
915#include "common/event_tracer.h"
916"""
917
918LIBGL_EXPORT_INCLUDES = """
919#include "angle_gl.h"
920
921#include "libGL/entry_points_gl_1_autogen.h"
922#include "libGL/entry_points_gl_2_autogen.h"
923#include "libGL/entry_points_gl_3_autogen.h"
924#include "libGL/entry_points_gl_4_autogen.h"
925
926#include "common/event_tracer.h"
927"""
928
929LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE = """
930#include "anglebase/no_destructor.h"
931#include "common/system_utils.h"
932
933#include <memory>
934
935#if defined(ANGLE_USE_EGL_LOADER)
936#    include "libEGL/egl_loader_autogen.h"
937#else
938#    include "libGLESv2/entry_points_egl_autogen.h"
939#    include "libGLESv2/entry_points_egl_ext_autogen.h"
940#endif  // defined(ANGLE_USE_EGL_LOADER)
941
942namespace
943{
944#if defined(ANGLE_USE_EGL_LOADER)
945bool gLoaded = false;
946void *gEntryPointsLib = nullptr;
947
948angle::GenericProc KHRONOS_APIENTRY GlobalLoad(const char *symbol)
949{
950    return reinterpret_cast<angle::GenericProc>(angle::GetLibrarySymbol(gEntryPointsLib, symbol));
951}
952
953void EnsureEGLLoaded()
954{
955    if (gLoaded)
956    {
957        return;
958    }
959
960    std::string errorOut;
961    gEntryPointsLib = OpenSystemLibraryAndGetError(ANGLE_GLESV2_LIBRARY_NAME, angle::SearchType::ModuleDir, &errorOut);
962    if (gEntryPointsLib)
963    {
964        angle::LoadEGL_EGL(GlobalLoad);
965        gLoaded = true;
966    }
967    else
968    {
969        fprintf(stderr, "Error loading EGL entry points: %s\\n", errorOut.c_str());
970    }
971}
972#else
973void EnsureEGLLoaded() {}
974#endif  // defined(ANGLE_USE_EGL_LOADER)
975}  // anonymous namespace
976"""
977
978LIBCL_HEADER_INCLUDES = """\
979#include "angle_cl.h"
980"""
981
982LIBCL_SOURCE_INCLUDES = """\
983#include "libGLESv2/entry_points_cl_autogen.h"
984
985#include "libANGLE/validationCL_autogen.h"
986#include "libGLESv2/cl_stubs_autogen.h"
987#include "libGLESv2/entry_points_cl_utils.h"
988"""
989
990TEMPLATE_EVENT_COMMENT = """\
991    // Don't run the EVENT() macro on the EXT_debug_marker entry points.
992    // It can interfere with the debug events being set by the caller.
993    // """
994
995TEMPLATE_CAPTURE_PROTO = "angle::CallCapture Capture%s(%s);"
996
997TEMPLATE_VALIDATION_PROTO = "%s Validate%s(%s);"
998
999TEMPLATE_WINDOWS_DEF_FILE = """\
1000; GENERATED FILE - DO NOT EDIT.
1001; Generated by {script_name} using data from {data_source_name}.
1002;
1003; Copyright 2020 The ANGLE Project Authors. All rights reserved.
1004; Use of this source code is governed by a BSD-style license that can be
1005; found in the LICENSE file.
1006LIBRARY {lib}
1007EXPORTS
1008{exports}
1009"""
1010
1011TEMPLATE_FRAME_CAPTURE_UTILS_HEADER = """\
1012// GENERATED FILE - DO NOT EDIT.
1013// Generated by {script_name} using data from {data_source_name}.
1014//
1015// Copyright 2020 The ANGLE Project Authors. All rights reserved.
1016// Use of this source code is governed by a BSD-style license that can be
1017// found in the LICENSE file.
1018//
1019// frame_capture_utils_autogen.h:
1020//   ANGLE Frame capture types and helper functions.
1021
1022#ifndef LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
1023#define LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
1024
1025#include "common/PackedEnums.h"
1026
1027namespace angle
1028{{
1029enum class ParamType
1030{{
1031    {param_types}
1032}};
1033
1034constexpr uint32_t kParamTypeCount = {param_type_count};
1035
1036union ParamValue
1037{{
1038    {param_union_values}
1039}};
1040
1041template <ParamType PType, typename T>
1042T GetParamVal(const ParamValue &value);
1043
1044{get_param_val_specializations}
1045
1046template <ParamType PType, typename T>
1047T GetParamVal(const ParamValue &value)
1048{{
1049    UNREACHABLE();
1050    return T();
1051}}
1052
1053template <typename T>
1054T AccessParamValue(ParamType paramType, const ParamValue &value)
1055{{
1056    switch (paramType)
1057    {{
1058{access_param_value_cases}
1059    }}
1060    UNREACHABLE();
1061    return T();
1062}}
1063
1064template <ParamType PType, typename T>
1065void SetParamVal(T valueIn, ParamValue *valueOut);
1066
1067{set_param_val_specializations}
1068
1069template <ParamType PType, typename T>
1070void SetParamVal(T valueIn, ParamValue *valueOut)
1071{{
1072    UNREACHABLE();
1073}}
1074
1075template <typename T>
1076void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut)
1077{{
1078    switch (paramType)
1079    {{
1080{init_param_value_cases}
1081    }}
1082}}
1083
1084struct CallCapture;
1085struct ParamCapture;
1086
1087void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param);
1088const char *ParamTypeToString(ParamType paramType);
1089
1090enum class ResourceIDType
1091{{
1092    {resource_id_types}
1093}};
1094
1095ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType);
1096const char *GetResourceIDTypeName(ResourceIDType resourceIDType);
1097
1098template <typename ResourceType>
1099struct GetResourceIDTypeFromType;
1100
1101{type_to_resource_id_type_structs}
1102}}  // namespace angle
1103
1104#endif  // LIBANGLE_FRAME_CAPTURE_UTILS_AUTOGEN_H_
1105"""
1106
1107TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE = """\
1108// GENERATED FILE - DO NOT EDIT.
1109// Generated by {script_name} using data from {data_source_name}.
1110//
1111// Copyright 2020 The ANGLE Project Authors. All rights reserved.
1112// Use of this source code is governed by a BSD-style license that can be
1113// found in the LICENSE file.
1114//
1115// frame_capture_utils_autogen.cpp:
1116//   ANGLE Frame capture types and helper functions.
1117
1118#include "libANGLE/capture/frame_capture_utils_autogen.h"
1119
1120#include "libANGLE/capture/FrameCapture.h"
1121
1122namespace angle
1123{{
1124void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param)
1125{{
1126    switch (param.type)
1127    {{
1128{write_param_type_to_stream_cases}
1129        default:
1130            os << "unknown";
1131            break;
1132    }}
1133}}
1134
1135const char *ParamTypeToString(ParamType paramType)
1136{{
1137    switch (paramType)
1138    {{
1139{param_type_to_string_cases}
1140        default:
1141            UNREACHABLE();
1142            return "unknown";
1143    }}
1144}}
1145
1146ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType)
1147{{
1148    switch (paramType)
1149    {{
1150{param_type_resource_id_cases}
1151        default:
1152            return ResourceIDType::InvalidEnum;
1153    }}
1154}}
1155
1156const char *GetResourceIDTypeName(ResourceIDType resourceIDType)
1157{{
1158    switch (resourceIDType)
1159    {{
1160{resource_id_type_name_cases}
1161        default:
1162            UNREACHABLE();
1163            return "GetResourceIDTypeName error";
1164    }}
1165}}
1166}}  // namespace angle
1167"""
1168
1169TEMPLATE_GET_PARAM_VAL_SPECIALIZATION = """\
1170template <>
1171inline {type} GetParamVal<ParamType::T{enum}, {type}>(const ParamValue &value)
1172{{
1173    return value.{union_name};
1174}}"""
1175
1176TEMPLATE_ACCESS_PARAM_VALUE_CASE = """\
1177        case ParamType::T{enum}:
1178            return GetParamVal<ParamType::T{enum}, T>(value);"""
1179
1180TEMPLATE_SET_PARAM_VAL_SPECIALIZATION = """\
1181template <>
1182inline void SetParamVal<ParamType::T{enum}>({type} valueIn, ParamValue *valueOut)
1183{{
1184    valueOut->{union_name} = valueIn;
1185}}"""
1186
1187TEMPLATE_INIT_PARAM_VALUE_CASE = """\
1188        case ParamType::T{enum}:
1189            SetParamVal<ParamType::T{enum}>(valueIn, valueOut);
1190            break;"""
1191
1192TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE = """\
1193        case ParamType::T{enum_in}:
1194            WriteParamValueReplay<ParamType::T{enum_out}>(os, call, param.value.{union_name});
1195            break;"""
1196
1197TEMPLATE_PARAM_TYPE_TO_STRING_CASE = """\
1198        case ParamType::T{enum}:
1199            return "{type}";"""
1200
1201TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE = """\
1202        case ParamType::T{enum}:
1203            return ResourceIDType::{resource_id_type};"""
1204
1205TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE = """\
1206        case ResourceIDType::{resource_id_type}:
1207            return "{resource_id_type}";"""
1208
1209CL_PACKED_TYPES = {
1210    # Enums
1211    "cl_platform_info": "PlatformInfo",
1212    "cl_device_info": "DeviceInfo",
1213    "cl_context_info": "ContextInfo",
1214    "cl_command_queue_info": "CommandQueueInfo",
1215    "cl_mem_object_type": "MemObjectType",
1216    "cl_mem_info": "MemInfo",
1217    "cl_image_info": "ImageInfo",
1218    "cl_pipe_info": "PipeInfo",
1219    "cl_addressing_mode": "AddressingMode",
1220    "cl_filter_mode": "FilterMode",
1221    "cl_sampler_info": "SamplerInfo",
1222    "cl_program_info": "ProgramInfo",
1223    "cl_program_build_info": "ProgramBuildInfo",
1224    "cl_kernel_info": "KernelInfo",
1225    "cl_kernel_arg_info": "KernelArgInfo",
1226    "cl_kernel_work_group_info": "KernelWorkGroupInfo",
1227    "cl_kernel_sub_group_info": "KernelSubGroupInfo",
1228    "cl_kernel_exec_info": "KernelExecInfo",
1229    "cl_event_info": "EventInfo",
1230    "cl_profiling_info": "ProfilingInfo",
1231    # Bit fields
1232    "cl_device_type": "DeviceType",
1233    "cl_device_fp_config": "DeviceFpConfig",
1234    "cl_device_exec_capabilities": "DeviceExecCapabilities",
1235    "cl_device_svm_capabilities": "DeviceSvmCapabilities",
1236    "cl_command_queue_properties": "CommandQueueProperties",
1237    "cl_device_affinity_domain": "DeviceAffinityDomain",
1238    "cl_mem_flags": "MemFlags",
1239    "cl_svm_mem_flags": "SVM_MemFlags",
1240    "cl_mem_migration_flags": "MemMigrationFlags",
1241    "cl_map_flags": "MapFlags",
1242    "cl_kernel_arg_type_qualifier": "KernelArgTypeQualifier",
1243    "cl_device_atomic_capabilities": "DeviceAtomicCapabilities",
1244    "cl_device_device_enqueue_capabilities": "DeviceEnqueueCapabilities",
1245}
1246
1247EGL_PACKED_TYPES = {
1248    "EGLContext": "gl::Context *",
1249    "EGLConfig": "Config *",
1250    "EGLDeviceEXT": "Device *",
1251    # Needs an explicit namespace to avoid an X11 namespace collision.
1252    "EGLDisplay": "egl::Display *",
1253    "EGLImage": "Image *",
1254    "EGLImageKHR": "Image *",
1255    "EGLStreamKHR": "Stream *",
1256    "EGLSurface": "Surface *",
1257    "EGLSync": "Sync *",
1258    "EGLSyncKHR": "Sync *",
1259}
1260
1261
1262def is_aliasing_excepted(api, cmd_name):
1263    return api == apis.GLES and cmd_name in ALIASING_EXCEPTIONS
1264
1265
1266def entry_point_export(api):
1267    if api == apis.CL:
1268        return ""
1269    return "ANGLE_EXPORT "
1270
1271
1272def entry_point_prefix(api):
1273    if api == apis.CL:
1274        return "cl"
1275    if api == apis.GLES:
1276        return "GL_"
1277    return api + "_"
1278
1279
1280def get_api_entry_def(api):
1281    if api == apis.EGL:
1282        return "EGLAPIENTRY"
1283    elif api == apis.CL:
1284        return "CL_API_CALL"
1285    else:
1286        return "GL_APIENTRY"
1287
1288
1289def get_stubs_header_template(api):
1290    if api == apis.CL:
1291        return TEMPLATE_CL_STUBS_HEADER
1292    elif api == apis.EGL:
1293        return TEMPLATE_EGL_STUBS_HEADER
1294    else:
1295        return ""
1296
1297
1298def format_entry_point_decl(api, cmd_name, proto, params):
1299    comma_if_needed = ", " if len(params) > 0 else ""
1300    stripped = strip_api_prefix(cmd_name)
1301    return TEMPLATE_ENTRY_POINT_DECL.format(
1302        angle_export=entry_point_export(api),
1303        export_def=get_api_entry_def(api),
1304        name="%s%s" % (entry_point_prefix(api), stripped),
1305        return_type=proto[:-len(cmd_name)].strip(),
1306        params=", ".join(params),
1307        comma_if_needed=comma_if_needed)
1308
1309
1310# Returns index range of identifier in function parameter
1311def find_name_range(param):
1312
1313    def is_allowed_in_identifier(char):
1314        return char.isalpha() or char.isdigit() or char == "_"
1315
1316    # If type is a function declaration, only search in first parentheses
1317    left_paren = param.find("(")
1318    if left_paren >= 0:
1319        min = left_paren + 1
1320        end = param.index(")")
1321    else:
1322        min = 0
1323        end = len(param)
1324
1325    # Find last identifier in search range
1326    while end > min and not is_allowed_in_identifier(param[end - 1]):
1327        end -= 1
1328    if end == min:
1329        raise ValueError
1330    start = end - 1
1331    while start > min and is_allowed_in_identifier(param[start - 1]):
1332        start -= 1
1333    return start, end
1334
1335
1336def just_the_type(param):
1337    start, end = find_name_range(param)
1338    return param[:start].strip() + param[end:].strip()
1339
1340
1341def just_the_name(param):
1342    start, end = find_name_range(param)
1343    return param[start:end]
1344
1345
1346def make_param(param_type, param_name):
1347
1348    def insert_name(param_type, param_name, pos):
1349        return param_type[:pos] + " " + param_name + param_type[pos:]
1350
1351    # If type is a function declaration, insert identifier before first closing parentheses
1352    left_paren = param_type.find("(")
1353    if left_paren >= 0:
1354        right_paren = param_type.index(")")
1355        return insert_name(param_type, param_name, right_paren)
1356
1357    # If type is an array declaration, insert identifier before brackets
1358    brackets = param_type.find("[")
1359    if brackets >= 0:
1360        return insert_name(param_type, param_name, brackets)
1361
1362    # Otherwise just append identifier
1363    return param_type + " " + param_name
1364
1365
1366def just_the_type_packed(param, entry):
1367    name = just_the_name(param)
1368    if name in entry:
1369        return entry[name]
1370    else:
1371        return just_the_type(param)
1372
1373
1374def just_the_name_packed(param, reserved_set):
1375    name = just_the_name(param)
1376    if name in reserved_set:
1377        return name + 'Packed'
1378    else:
1379        return name
1380
1381
1382def is_unsigned_long_format(fmt):
1383    return fmt == UNSIGNED_LONG_LONG_FORMAT or fmt == HEX_LONG_LONG_FORMAT
1384
1385
1386def param_print_argument(command_node, param):
1387    name_only = just_the_name(param)
1388    type_only = just_the_type(param)
1389
1390    if "*" not in param and type_only not in FORMAT_DICT:
1391        print(" ".join(param))
1392        raise Exception("Missing '%s %s' from '%s' entry point" %
1393                        (type_only, name_only, registry_xml.get_cmd_name(command_node)))
1394
1395    if "*" in param or FORMAT_DICT[type_only] == POINTER_FORMAT:
1396        return "(uintptr_t)%s" % name_only
1397
1398    if is_unsigned_long_format(FORMAT_DICT[type_only]):
1399        return "static_cast<unsigned long long>(%s)" % name_only
1400
1401    if type_only == "GLboolean":
1402        return "GLbooleanToString(%s)" % name_only
1403
1404    if type_only == "GLbitfield":
1405        group_name = find_gl_enum_group_in_command(command_node, name_only)
1406        return "GLbitfieldToString(GLenumGroup::%s, %s).c_str()" % (group_name, name_only)
1407
1408    if type_only == "GLenum":
1409        group_name = find_gl_enum_group_in_command(command_node, name_only)
1410        return "GLenumToString(GLenumGroup::%s, %s)" % (group_name, name_only)
1411
1412    return name_only
1413
1414
1415def param_format_string(param):
1416    if "*" in param:
1417        return just_the_name(param) + " = 0x%016\" PRIxPTR \""
1418    else:
1419        type_only = just_the_type(param)
1420        if type_only not in FORMAT_DICT:
1421            raise Exception(type_only + " is not a known type in 'FORMAT_DICT'")
1422
1423        return just_the_name(param) + " = " + FORMAT_DICT[type_only]
1424
1425
1426def is_context_lost_acceptable_cmd(cmd_name):
1427    lost_context_acceptable_cmds = [
1428        "glGetError",
1429        "glGetSync",
1430        "glGetQueryObjecti",
1431        "glGetProgramiv",
1432        "glGetGraphicsResetStatus",
1433        "glGetShaderiv",
1434    ]
1435
1436    for context_lost_entry_pont in lost_context_acceptable_cmds:
1437        if cmd_name.startswith(context_lost_entry_pont):
1438            return True
1439    return False
1440
1441
1442def get_context_getter_function(cmd_name):
1443    if is_context_lost_acceptable_cmd(cmd_name):
1444        return "GetGlobalContext()"
1445
1446    return "GetValidGlobalContext()"
1447
1448
1449def get_valid_context_check(cmd_name):
1450    return "context"
1451
1452
1453def get_constext_lost_error_generator(cmd_name):
1454    # Don't generate context lost errors on commands that accept lost contexts
1455    if is_context_lost_acceptable_cmd(cmd_name):
1456        return ""
1457
1458    return "GenerateContextLostErrorOnCurrentGlobalContext();"
1459
1460
1461def strip_suffix(api, name):
1462    # For commands where aliasing is excepted, keep the suffix
1463    if is_aliasing_excepted(api, name):
1464        return name
1465
1466    for suffix in registry_xml.strip_suffixes:
1467        if name.endswith(suffix):
1468            name = name[0:-len(suffix)]
1469    return name
1470
1471
1472def find_gl_enum_group_in_command(command_node, param_name):
1473    group_name = None
1474    for param_node in command_node.findall('./param'):
1475        if param_node.find('./name').text == param_name:
1476            group_name = param_node.attrib.get('group', None)
1477            break
1478
1479    if group_name is None or group_name in registry_xml.unsupported_enum_group_names:
1480        group_name = registry_xml.default_enum_group_name
1481
1482    return group_name
1483
1484
1485def get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types, params):
1486    # Always strip the suffix when querying packed enums.
1487    result = cmd_packed_gl_enums.get(strip_suffix(api, cmd_name), {})
1488    for param in params:
1489        param_type = just_the_type(param)
1490        if param_type in packed_param_types:
1491            result[just_the_name(param)] = packed_param_types[param_type]
1492    return result
1493
1494
1495CUSTOM_EGL_ENTRY_POINTS = ["eglPrepareSwapBuffersANGLE"]
1496
1497
1498def get_def_template(api, cmd_name, return_type, has_errcode_ret):
1499    if return_type == "void":
1500        if api == apis.EGL:
1501            if cmd_name in CUSTOM_EGL_ENTRY_POINTS:
1502                return TEMPLATE_EGL_ENTRY_POINT_NO_RETURN_CUSTOM
1503            return TEMPLATE_EGL_ENTRY_POINT_NO_RETURN
1504        elif api == apis.CL:
1505            return TEMPLATE_CL_ENTRY_POINT_NO_RETURN
1506        else:
1507            return TEMPLATE_GLES_ENTRY_POINT_NO_RETURN
1508    elif return_type == "cl_int":
1509        return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR
1510    else:
1511        if api == apis.EGL:
1512            if cmd_name in CUSTOM_EGL_ENTRY_POINTS:
1513                return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN_CUSTOM
1514            return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN
1515        elif api == apis.CL:
1516            if has_errcode_ret:
1517                return TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET
1518            else:
1519                return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER
1520        else:
1521            return TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN
1522
1523
1524def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packed_enums,
1525                           packed_param_types, ep_to_object):
1526    packed_enums = get_packed_enums(api, cmd_packed_enums, cmd_name, packed_param_types, params)
1527    if cmd_name in CUSTOM_EGL_ENTRY_POINTS:
1528        internal_params = [just_the_name(param) for param in params]
1529    else:
1530        internal_params = [just_the_name_packed(param, packed_enums) for param in params]
1531    if internal_params and internal_params[-1] == "errcode_ret":
1532        internal_params.pop()
1533        has_errcode_ret = True
1534    else:
1535        has_errcode_ret = False
1536
1537    packed_gl_enum_conversions = []
1538
1539    for param in params:
1540        name = just_the_name(param)
1541
1542        if name in packed_enums:
1543            internal_name = name + "Packed"
1544            internal_type = packed_enums[name]
1545            packed_gl_enum_conversions += [
1546                "\n        " + internal_type + " " + internal_name + " = PackParam<" +
1547                internal_type + ">(" + name + ");"
1548            ]
1549
1550    pass_params = [param_print_argument(command_node, param) for param in params]
1551    format_params = [param_format_string(param) for param in params]
1552    return_type = proto[:-len(cmd_name)].strip()
1553    initialization = "InitBackEnds(%s);\n" % INIT_DICT[cmd_name] if cmd_name in INIT_DICT else ""
1554    event_comment = TEMPLATE_EVENT_COMMENT if cmd_name in NO_EVENT_MARKER_EXCEPTIONS_LIST else ""
1555    name_lower_no_suffix = strip_suffix(api, cmd_name[2:3].lower() + cmd_name[3:])
1556    entry_point_name = "angle::EntryPoint::GL" + strip_api_prefix(cmd_name)
1557
1558    format_params = {
1559        "name":
1560            strip_api_prefix(cmd_name),
1561        "name_lower_no_suffix":
1562            name_lower_no_suffix,
1563        "return_type":
1564            return_type,
1565        "params":
1566            ", ".join(params),
1567        "internal_params":
1568            ", ".join(internal_params),
1569        "initialization":
1570            initialization,
1571        "packed_gl_enum_conversions":
1572            "".join(packed_gl_enum_conversions),
1573        "pass_params":
1574            ", ".join(pass_params),
1575        "comma_if_needed":
1576            ", " if len(params) > 0 else "",
1577        "capture_params":
1578            ", ".join(["context"] + internal_params),
1579        "validate_params":
1580            ", ".join(["context"] + [entry_point_name] + internal_params),
1581        "format_params":
1582            ", ".join(format_params),
1583        "context_getter":
1584            get_context_getter_function(cmd_name),
1585        "valid_context_check":
1586            get_valid_context_check(cmd_name),
1587        "constext_lost_error_generator":
1588            get_constext_lost_error_generator(cmd_name),
1589        "event_comment":
1590            event_comment,
1591        "labeled_object":
1592            get_egl_entry_point_labeled_object(ep_to_object, cmd_name, params, packed_enums),
1593        "entry_point_locks":
1594            get_locks(api, cmd_name, params),
1595        "preamble":
1596            get_preamble(api, cmd_name, params)
1597    }
1598
1599    template = get_def_template(api, cmd_name, return_type, has_errcode_ret)
1600    return template.format(**format_params)
1601
1602
1603def get_capture_param_type_name(param_type):
1604    pointer_count = param_type.count("*")
1605    is_const = "const" in param_type.split()
1606
1607    # EGL types are special
1608    for egl_type, angle_type in EGL_PACKED_TYPES.items():
1609        if angle_type == param_type:
1610            return egl_type
1611
1612    param_type = param_type.replace("*", "")
1613    param_type = param_type.replace("&", "")
1614    param_type = param_type.replace("const", "")
1615    param_type = param_type.replace("struct", "")
1616    param_type = param_type.strip()
1617
1618    if "EGL" not in param_type:
1619        if is_const and param_type != 'AttributeMap':
1620            param_type += "Const"
1621        for x in range(pointer_count):
1622            param_type += "Pointer"
1623
1624    return param_type
1625
1626
1627def format_capture_method(api, command, cmd_name, proto, params, all_param_types,
1628                          capture_pointer_funcs, cmd_packed_gl_enums, packed_param_types):
1629
1630    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
1631                                       params)
1632
1633    params_with_type = get_internal_params(api, cmd_name,
1634                                           ["const State &glState", "bool isCallValid"] + params,
1635                                           cmd_packed_gl_enums, packed_param_types)
1636    params_just_name = ", ".join(
1637        ["glState", "isCallValid"] +
1638        [just_the_name_packed(param, packed_gl_enums) for param in params])
1639
1640    parameter_captures = []
1641    for param in params:
1642
1643        param_name = just_the_name_packed(param, packed_gl_enums)
1644        param_type = just_the_type_packed(param, packed_gl_enums).strip()
1645
1646        # TODO(http://anglebug.com/4035: Add support for egl::AttributeMap.
1647        if 'AttributeMap' in param_type:
1648            # egl::AttributeMap is too complex for ParamCapture to handle it.
1649            continue
1650
1651        pointer_count = param_type.count("*")
1652        capture_param_type = get_capture_param_type_name(param_type)
1653
1654        if pointer_count > 0:
1655            params = params_just_name
1656            capture_name = "Capture%s_%s" % (strip_api_prefix(cmd_name), param_name)
1657            capture = TEMPLATE_PARAMETER_CAPTURE_POINTER.format(
1658                name=param_name,
1659                type=capture_param_type,
1660                capture_name=capture_name,
1661                params=params,
1662                cast_type=param_type)
1663
1664            capture_pointer_func = TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC.format(
1665                name=capture_name, params=params_with_type + ", angle::ParamCapture *paramCapture")
1666            capture_pointer_funcs += [capture_pointer_func]
1667        elif capture_param_type in ('GLenum', 'GLbitfield'):
1668            gl_enum_group = find_gl_enum_group_in_command(command, param_name)
1669            capture = TEMPLATE_PARAMETER_CAPTURE_GL_ENUM.format(
1670                name=param_name, type=capture_param_type, group=gl_enum_group)
1671        else:
1672            capture = TEMPLATE_PARAMETER_CAPTURE_VALUE.format(
1673                name=param_name, type=capture_param_type)
1674
1675        all_param_types.add(capture_param_type)
1676
1677        parameter_captures += [capture]
1678
1679    return_type = proto[:-len(cmd_name)].strip()
1680
1681    format_args = {
1682        "full_name": cmd_name,
1683        "short_name": strip_api_prefix(cmd_name),
1684        "params_with_type": params_with_type,
1685        "params_just_name": params_just_name,
1686        "parameter_captures": "\n    ".join(parameter_captures),
1687        "return_value_type_original": return_type,
1688        "return_value_type_custom": get_capture_param_type_name(return_type)
1689    }
1690
1691    if return_type == "void":
1692        return TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE.format(**format_args)
1693    else:
1694        return TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE.format(**format_args)
1695
1696
1697def const_pointer_type(param, packed_gl_enums):
1698    type = just_the_type_packed(param, packed_gl_enums)
1699    if just_the_name(param) == "errcode_ret" or "(" in type:
1700        return type
1701    elif "**" in type and "const" not in type:
1702        return type.replace("**", "* const *")
1703    elif "*" in type and "const" not in type:
1704        return type.replace("*", "*const ") if "[]" in type else "const " + type
1705    else:
1706        return type
1707
1708
1709def get_internal_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
1710    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
1711                                       params)
1712    return ", ".join([
1713        make_param(
1714            just_the_type_packed(param, packed_gl_enums),
1715            just_the_name_packed(param, packed_gl_enums)) for param in params
1716    ])
1717
1718
1719def get_validation_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
1720    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
1721                                       params)
1722    last = -1 if params and just_the_name(params[-1]) == "errcode_ret" else None
1723    return ", ".join([
1724        make_param(
1725            const_pointer_type(param, packed_gl_enums),
1726            just_the_name_packed(param, packed_gl_enums)) for param in params[:last]
1727    ])
1728
1729
1730def format_context_decl(api, cmd_name, proto, params, template, cmd_packed_gl_enums,
1731                        packed_param_types):
1732    internal_params = get_internal_params(api, cmd_name, params, cmd_packed_gl_enums,
1733                                          packed_param_types)
1734
1735    return_type = proto[:-len(cmd_name)].strip()
1736    name_lower_no_suffix = cmd_name[2:3].lower() + cmd_name[3:]
1737    name_lower_no_suffix = strip_suffix(api, name_lower_no_suffix)
1738    maybe_const = " const" if name_lower_no_suffix.startswith(
1739        "is") and name_lower_no_suffix[2].isupper() else ""
1740
1741    return template.format(
1742        return_type=return_type,
1743        name_lower_no_suffix=name_lower_no_suffix,
1744        internal_params=internal_params,
1745        maybe_const=maybe_const)
1746
1747
1748def format_entry_point_export(cmd_name, proto, params, template):
1749    internal_params = [just_the_name(param) for param in params]
1750    return_type = proto[:-len(cmd_name)].strip()
1751
1752    return template.format(
1753        name=strip_api_prefix(cmd_name),
1754        return_type=return_type,
1755        params=", ".join(params),
1756        internal_params=", ".join(internal_params))
1757
1758
1759def format_validation_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
1760    if api == apis.CL:
1761        return_type = "cl_int"
1762    else:
1763        return_type = "bool"
1764    if api in [apis.GL, apis.GLES]:
1765        with_extra_params = ["Context *context"] + ["angle::EntryPoint entryPoint"] + params
1766    elif api == apis.EGL:
1767        with_extra_params = ["ValidationContext *val"] + params
1768    else:
1769        with_extra_params = params
1770    internal_params = get_validation_params(api, cmd_name, with_extra_params, cmd_packed_gl_enums,
1771                                            packed_param_types)
1772    return TEMPLATE_VALIDATION_PROTO % (return_type, strip_api_prefix(cmd_name), internal_params)
1773
1774
1775def format_capture_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
1776    internal_params = get_internal_params(api, cmd_name,
1777                                          ["const State &glState", "bool isCallValid"] + params,
1778                                          cmd_packed_gl_enums, packed_param_types)
1779    return_type = proto[:-len(cmd_name)].strip()
1780    if return_type != "void":
1781        internal_params += ", %s returnValue" % return_type
1782    return TEMPLATE_CAPTURE_PROTO % (strip_api_prefix(cmd_name), internal_params)
1783
1784
1785def path_to(folder, file):
1786    return os.path.join(script_relative(".."), "src", folder, file)
1787
1788
1789class ANGLEEntryPoints(registry_xml.EntryPoints):
1790
1791    def __init__(self,
1792                 api,
1793                 xml,
1794                 commands,
1795                 all_param_types,
1796                 cmd_packed_enums,
1797                 export_template=TEMPLATE_GL_ENTRY_POINT_EXPORT,
1798                 packed_param_types=[],
1799                 ep_to_object={}):
1800        super().__init__(api, xml, commands)
1801
1802        self.decls = []
1803        self.defs = []
1804        self.export_defs = []
1805        self.validation_protos = []
1806        self.capture_protos = []
1807        self.capture_methods = []
1808        self.capture_pointer_funcs = []
1809
1810        for (cmd_name, command_node, param_text, proto_text) in self.get_infos():
1811            self.decls.append(format_entry_point_decl(self.api, cmd_name, proto_text, param_text))
1812            self.defs.append(
1813                format_entry_point_def(self.api, command_node, cmd_name, proto_text, param_text,
1814                                       cmd_packed_enums, packed_param_types, ep_to_object))
1815
1816            self.export_defs.append(
1817                format_entry_point_export(cmd_name, proto_text, param_text, export_template))
1818
1819            self.validation_protos.append(
1820                format_validation_proto(self.api, cmd_name, proto_text, param_text,
1821                                        cmd_packed_enums, packed_param_types))
1822            self.capture_protos.append(
1823                format_capture_proto(self.api, cmd_name, proto_text, param_text, cmd_packed_enums,
1824                                     packed_param_types))
1825            self.capture_methods.append(
1826                format_capture_method(self.api, command_node, cmd_name, proto_text, param_text,
1827                                      all_param_types, self.capture_pointer_funcs,
1828                                      cmd_packed_enums, packed_param_types))
1829
1830
1831class GLEntryPoints(ANGLEEntryPoints):
1832
1833    all_param_types = set()
1834
1835    def __init__(self, api, xml, commands):
1836        super().__init__(api, xml, commands, GLEntryPoints.all_param_types,
1837                         GLEntryPoints.get_packed_enums())
1838
1839    _packed_enums = None
1840
1841    @classmethod
1842    def get_packed_enums(cls):
1843        if not cls._packed_enums:
1844            with open(script_relative('entry_point_packed_gl_enums.json')) as f:
1845                cls._packed_enums = json.loads(f.read())
1846        return cls._packed_enums
1847
1848
1849class EGLEntryPoints(ANGLEEntryPoints):
1850
1851    all_param_types = set()
1852
1853    def __init__(self, xml, commands):
1854        super().__init__(
1855            apis.EGL,
1856            xml,
1857            commands,
1858            EGLEntryPoints.all_param_types,
1859            EGLEntryPoints.get_packed_enums(),
1860            export_template=TEMPLATE_EGL_ENTRY_POINT_EXPORT,
1861            packed_param_types=EGL_PACKED_TYPES,
1862            ep_to_object=EGLEntryPoints._get_ep_to_object())
1863
1864    _ep_to_object = None
1865
1866    @classmethod
1867    def _get_ep_to_object(cls):
1868
1869        if cls._ep_to_object:
1870            return cls._ep_to_object
1871
1872        with open(EGL_GET_LABELED_OBJECT_DATA_PATH) as f:
1873            try:
1874                spec_json = json.loads(f.read())
1875            except ValueError:
1876                raise Exception("Could not decode JSON from %s" % EGL_GET_LABELED_OBJECT_DATA_PATH)
1877
1878        # Construct a mapping from EP to type. Fill in the gaps with Display/None.
1879        cls._ep_to_object = {}
1880
1881        for category, eps in spec_json.items():
1882            if category == 'description':
1883                continue
1884            for ep in eps:
1885                cls._ep_to_object[ep] = category
1886
1887        return cls._ep_to_object
1888
1889    _packed_enums = None
1890
1891    @classmethod
1892    def get_packed_enums(cls):
1893        if not cls._packed_enums:
1894            with open(script_relative('entry_point_packed_egl_enums.json')) as f:
1895                cls._packed_enums = json.loads(f.read())
1896        return cls._packed_enums
1897
1898
1899class CLEntryPoints(ANGLEEntryPoints):
1900
1901    all_param_types = set()
1902
1903    def __init__(self, xml, commands):
1904        super().__init__(
1905            apis.CL,
1906            xml,
1907            commands,
1908            CLEntryPoints.all_param_types,
1909            CLEntryPoints.get_packed_enums(),
1910            export_template=TEMPLATE_CL_ENTRY_POINT_EXPORT,
1911            packed_param_types=CL_PACKED_TYPES)
1912
1913    @classmethod
1914    def get_packed_enums(cls):
1915        return {}
1916
1917
1918def get_decls(api,
1919              formatter,
1920              all_commands,
1921              gles_commands,
1922              already_included,
1923              cmd_packed_gl_enums,
1924              packed_param_types=[]):
1925    decls = []
1926    for command in all_commands:
1927        proto = command.find('proto')
1928        cmd_name = proto.find('name').text
1929
1930        if cmd_name not in gles_commands:
1931            continue
1932
1933        name_no_suffix = strip_suffix(api, cmd_name)
1934        if name_no_suffix in already_included:
1935            continue
1936
1937        param_text = ["".join(param.itertext()) for param in command.findall('param')]
1938        proto_text = "".join(proto.itertext())
1939        decls.append(
1940            format_context_decl(api, cmd_name, proto_text, param_text, formatter,
1941                                cmd_packed_gl_enums, packed_param_types))
1942
1943    return decls
1944
1945
1946def get_glext_decls(all_commands, gles_commands, version):
1947    glext_ptrs = []
1948    glext_protos = []
1949    is_gles1 = False
1950
1951    if (version == ""):
1952        is_gles1 = True
1953
1954    for command in all_commands:
1955        proto = command.find('proto')
1956        cmd_name = proto.find('name').text
1957
1958        if cmd_name not in gles_commands:
1959            continue
1960
1961        param_text = ["".join(param.itertext()) for param in command.findall('param')]
1962        proto_text = "".join(proto.itertext())
1963
1964        return_type = proto_text[:-len(cmd_name)]
1965        params = ", ".join(param_text)
1966
1967        format_params = {
1968            "apicall": "GL_API" if is_gles1 else "GL_APICALL",
1969            "name": cmd_name,
1970            "name_upper": cmd_name.upper(),
1971            "return_type": return_type,
1972            "params": params,
1973        }
1974
1975        glext_ptrs.append(TEMPLATE_GLEXT_FUNCTION_POINTER.format(**format_params))
1976        glext_protos.append(TEMPLATE_GLEXT_FUNCTION_PROTOTYPE.format(**format_params))
1977
1978    return glext_ptrs, glext_protos
1979
1980
1981def write_file(annotation, comment, template, entry_points, suffix, includes, lib, file):
1982
1983    content = template.format(
1984        script_name=os.path.basename(sys.argv[0]),
1985        data_source_name=file,
1986        annotation_lower=annotation.lower(),
1987        annotation_upper=annotation.upper(),
1988        comment=comment,
1989        lib=lib.upper(),
1990        includes=includes,
1991        entry_points=entry_points)
1992
1993    path = path_to(lib, "entry_points_{}_autogen.{}".format(annotation.lower(), suffix))
1994
1995    with open(path, "w") as out:
1996        out.write(content)
1997        out.close()
1998
1999
2000def write_export_files(entry_points, includes, source, lib_name, lib_description):
2001    content = TEMPLATE_LIB_ENTRY_POINT_SOURCE.format(
2002        script_name=os.path.basename(sys.argv[0]),
2003        data_source_name=source,
2004        lib_name=lib_name,
2005        lib_description=lib_description,
2006        includes=includes,
2007        entry_points=entry_points)
2008
2009    path = path_to(lib_name, "{}_autogen.cpp".format(lib_name))
2010
2011    with open(path, "w") as out:
2012        out.write(content)
2013        out.close()
2014
2015
2016def write_context_api_decls(decls, api):
2017    for (major, minor), version_decls in sorted(decls['core'].items()):
2018        if minor == "X":
2019            annotation = '{}_{}'.format(api, major)
2020            version = str(major)
2021        else:
2022            annotation = '{}_{}_{}'.format(api, major, minor)
2023            version = '{}_{}'.format(major, minor)
2024        content = CONTEXT_HEADER.format(
2025            annotation_lower=annotation.lower(),
2026            annotation_upper=annotation.upper(),
2027            script_name=os.path.basename(sys.argv[0]),
2028            data_source_name="gl.xml",
2029            version=version,
2030            interface="\n".join(version_decls))
2031
2032        path = path_to("libANGLE", "Context_%s_autogen.h" % annotation.lower())
2033
2034        with open(path, "w") as out:
2035            out.write(content)
2036            out.close()
2037
2038    if 'exts' in decls.keys():
2039        interface_lines = []
2040        for annotation in decls['exts'].keys():
2041            interface_lines.append("\\\n    /* " + annotation + " */ \\\n\\")
2042
2043            for extname in sorted(decls['exts'][annotation].keys()):
2044                interface_lines.append("    /* " + extname + " */ \\")
2045                interface_lines.extend(decls['exts'][annotation][extname])
2046
2047        content = CONTEXT_HEADER.format(
2048            annotation_lower='gles_ext',
2049            annotation_upper='GLES_EXT',
2050            script_name=os.path.basename(sys.argv[0]),
2051            data_source_name="gl.xml",
2052            version='EXT',
2053            interface="\n".join(interface_lines))
2054
2055        path = path_to("libANGLE", "Context_gles_ext_autogen.h")
2056
2057        with open(path, "w") as out:
2058            out.write(content)
2059            out.close()
2060
2061
2062def write_validation_header(annotation, comment, protos, source, template):
2063    content = template.format(
2064        script_name=os.path.basename(sys.argv[0]),
2065        data_source_name=source,
2066        annotation=annotation,
2067        comment=comment,
2068        prototypes="\n".join(protos))
2069
2070    path = path_to("libANGLE", "validation%s_autogen.h" % annotation)
2071
2072    with open(path, "w") as out:
2073        out.write(content)
2074        out.close()
2075
2076
2077def write_gl_validation_header(annotation, comment, protos, source):
2078    return write_validation_header(annotation, comment, protos, source,
2079                                   TEMPLATE_GL_VALIDATION_HEADER)
2080
2081
2082def write_capture_header(annotation, comment, protos, capture_pointer_funcs):
2083    content = TEMPLATE_CAPTURE_HEADER.format(
2084        script_name=os.path.basename(sys.argv[0]),
2085        data_source_name="gl.xml and gl_angle_ext.xml",
2086        annotation_lower=annotation.lower(),
2087        annotation_upper=annotation.upper(),
2088        comment=comment,
2089        prototypes="\n".join(["\n// Method Captures\n"] + protos + ["\n// Parameter Captures\n"] +
2090                             capture_pointer_funcs))
2091
2092    path = path_to(os.path.join("libANGLE", "capture"), "capture_gles_%s_autogen.h" % annotation)
2093
2094    with open(path, "w") as out:
2095        out.write(content)
2096        out.close()
2097
2098
2099def write_capture_source(annotation_with_dash, annotation_no_dash, comment, capture_methods):
2100    content = TEMPLATE_CAPTURE_SOURCE.format(
2101        script_name=os.path.basename(sys.argv[0]),
2102        data_source_name="gl.xml and gl_angle_ext.xml",
2103        annotation_with_dash=annotation_with_dash,
2104        annotation_no_dash=annotation_no_dash,
2105        comment=comment,
2106        capture_methods="\n".join(capture_methods))
2107
2108    path = path_to(
2109        os.path.join("libANGLE", "capture"), "capture_gles_%s_autogen.cpp" % annotation_with_dash)
2110
2111    with open(path, "w") as out:
2112        out.write(content)
2113        out.close()
2114
2115
2116def is_packed_enum_param_type(param_type):
2117    return param_type[0:2] != "GL" and "void" not in param_type
2118
2119
2120def add_namespace(param_type):
2121    param_type = param_type.strip()
2122
2123    if param_type == 'AHardwareBufferConstPointer' or param_type == 'charConstPointer':
2124        return param_type
2125
2126    if param_type[0:2] == "GL" or param_type[0:3] == "EGL" or "void" in param_type:
2127        return param_type
2128
2129    # ANGLE namespaced EGL types
2130    egl_namespace = [
2131        'CompositorTiming',
2132        'DevicePointer',
2133        'ObjectType',
2134        'StreamPointer',
2135        'Timestamp',
2136    ]
2137
2138    if param_type in egl_namespace:
2139        return "egl::" + param_type
2140    else:
2141        return "gl::" + param_type
2142
2143
2144def get_gl_pointer_type(param_type):
2145
2146    if "ConstPointerPointer" in param_type:
2147        return "const " + param_type.replace("ConstPointerPointer", "") + " * const *"
2148
2149    if "ConstPointer" in param_type:
2150        return "const " + param_type.replace("ConstPointer", "") + " *"
2151
2152    if "PointerPointer" in param_type:
2153        return param_type.replace("PointerPointer", "") + " **"
2154
2155    if "Pointer" in param_type:
2156        return param_type.replace("Pointer", "") + " *"
2157
2158    return param_type
2159
2160
2161def get_param_type_type(param_type):
2162    param_type = add_namespace(param_type)
2163    return get_gl_pointer_type(param_type)
2164
2165
2166def get_gl_param_type_type(param_type):
2167    if not is_packed_enum_param_type(param_type):
2168        return get_gl_pointer_type(param_type)
2169    else:
2170        base_type = param_type.replace("Pointer", "").replace("Const", "")
2171        if base_type[-2:] == "ID":
2172            replace_type = "GLuint"
2173        else:
2174            replace_type = "GLenum"
2175        param_type = param_type.replace(base_type, replace_type)
2176        return get_gl_pointer_type(param_type)
2177
2178
2179def get_param_type_union_name(param_type):
2180    return param_type + "Val"
2181
2182
2183def format_param_type_union_type(param_type):
2184    return "%s %s;" % (get_param_type_type(param_type), get_param_type_union_name(param_type))
2185
2186
2187def format_get_param_val_specialization(param_type):
2188    return TEMPLATE_GET_PARAM_VAL_SPECIALIZATION.format(
2189        enum=param_type,
2190        type=get_param_type_type(param_type),
2191        union_name=get_param_type_union_name(param_type))
2192
2193
2194def format_access_param_value_case(param_type):
2195    return TEMPLATE_ACCESS_PARAM_VALUE_CASE.format(enum=param_type)
2196
2197
2198def format_set_param_val_specialization(param_type):
2199    return TEMPLATE_SET_PARAM_VAL_SPECIALIZATION.format(
2200        enum=param_type,
2201        type=get_param_type_type(param_type),
2202        union_name=get_param_type_union_name(param_type))
2203
2204
2205def format_init_param_value_case(param_type):
2206    return TEMPLATE_INIT_PARAM_VALUE_CASE.format(enum=param_type)
2207
2208
2209def format_write_param_type_to_stream_case(param_type):
2210    return TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE.format(
2211        enum_in=param_type, enum_out=param_type, union_name=get_param_type_union_name(param_type))
2212
2213
2214def get_resource_id_types(all_param_types):
2215    return [
2216        t[:-2]
2217        for t in filter(lambda t: t.endswith("ID") and not t.endswith("ANDROID"), all_param_types)
2218    ]
2219
2220
2221def format_resource_id_types(all_param_types):
2222    resource_id_types = get_resource_id_types(all_param_types)
2223    resource_id_types += ["EnumCount", "InvalidEnum = EnumCount"]
2224    resource_id_types = ",\n    ".join(resource_id_types)
2225    return resource_id_types
2226
2227
2228def format_resource_id_convert_structs(all_param_types):
2229    templ = """\
2230template <>
2231struct GetResourceIDTypeFromType<gl::%sID>
2232{
2233    static constexpr ResourceIDType IDType = ResourceIDType::%s;
2234};
2235"""
2236    resource_id_types = get_resource_id_types(all_param_types)
2237    convert_struct_strings = [templ % (id, id) for id in resource_id_types]
2238    return "\n".join(convert_struct_strings)
2239
2240
2241def write_capture_helper_header(all_param_types):
2242
2243    param_types = "\n    ".join(["T%s," % t for t in all_param_types])
2244    param_union_values = "\n    ".join([format_param_type_union_type(t) for t in all_param_types])
2245    get_param_val_specializations = "\n\n".join(
2246        [format_get_param_val_specialization(t) for t in all_param_types])
2247    access_param_value_cases = "\n".join(
2248        [format_access_param_value_case(t) for t in all_param_types])
2249    set_param_val_specializations = "\n\n".join(
2250        [format_set_param_val_specialization(t) for t in all_param_types])
2251    init_param_value_cases = "\n".join([format_init_param_value_case(t) for t in all_param_types])
2252    resource_id_types = format_resource_id_types(all_param_types)
2253    convert_structs = format_resource_id_convert_structs(all_param_types)
2254
2255    content = TEMPLATE_FRAME_CAPTURE_UTILS_HEADER.format(
2256        script_name=os.path.basename(sys.argv[0]),
2257        data_source_name="gl.xml and gl_angle_ext.xml",
2258        param_types=param_types,
2259        param_type_count=len(all_param_types),
2260        param_union_values=param_union_values,
2261        get_param_val_specializations=get_param_val_specializations,
2262        access_param_value_cases=access_param_value_cases,
2263        set_param_val_specializations=set_param_val_specializations,
2264        init_param_value_cases=init_param_value_cases,
2265        resource_id_types=resource_id_types,
2266        type_to_resource_id_type_structs=convert_structs)
2267
2268    path = path_to(os.path.join("libANGLE", "capture"), "frame_capture_utils_autogen.h")
2269
2270    with open(path, "w") as out:
2271        out.write(content)
2272        out.close()
2273
2274
2275def format_param_type_to_string_case(param_type):
2276    return TEMPLATE_PARAM_TYPE_TO_STRING_CASE.format(
2277        enum=param_type, type=get_gl_param_type_type(param_type))
2278
2279
2280def get_resource_id_type_from_param_type(param_type):
2281    if param_type.endswith("ConstPointer"):
2282        return param_type.replace("ConstPointer", "")[:-2]
2283    if param_type.endswith("Pointer"):
2284        return param_type.replace("Pointer", "")[:-2]
2285    return param_type[:-2]
2286
2287
2288def format_param_type_to_resource_id_type_case(param_type):
2289    return TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE.format(
2290        enum=param_type, resource_id_type=get_resource_id_type_from_param_type(param_type))
2291
2292
2293def format_param_type_resource_id_cases(all_param_types):
2294    id_types = filter(
2295        lambda t: (t.endswith("ID") and not t.endswith("ANDROID")) or t.endswith("IDConstPointer")
2296        or t.endswith("IDPointer"), all_param_types)
2297    return "\n".join([format_param_type_to_resource_id_type_case(t) for t in id_types])
2298
2299
2300def format_resource_id_type_name_case(resource_id_type):
2301    return TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE.format(resource_id_type=resource_id_type)
2302
2303
2304def write_capture_helper_source(all_param_types):
2305
2306    write_param_type_to_stream_cases = "\n".join(
2307        [format_write_param_type_to_stream_case(t) for t in all_param_types])
2308    param_type_to_string_cases = "\n".join(
2309        [format_param_type_to_string_case(t) for t in all_param_types])
2310
2311    param_type_resource_id_cases = format_param_type_resource_id_cases(all_param_types)
2312
2313    resource_id_types = get_resource_id_types(all_param_types)
2314    resource_id_type_name_cases = "\n".join(
2315        [format_resource_id_type_name_case(t) for t in resource_id_types])
2316
2317    content = TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE.format(
2318        script_name=os.path.basename(sys.argv[0]),
2319        data_source_name="gl.xml and gl_angle_ext.xml",
2320        write_param_type_to_stream_cases=write_param_type_to_stream_cases,
2321        param_type_to_string_cases=param_type_to_string_cases,
2322        param_type_resource_id_cases=param_type_resource_id_cases,
2323        resource_id_type_name_cases=resource_id_type_name_cases)
2324
2325    path = path_to(os.path.join("libANGLE", "capture"), "frame_capture_utils_autogen.cpp")
2326
2327    with open(path, "w") as out:
2328        out.write(content)
2329        out.close()
2330
2331
2332def get_command_params_text(command_node, cmd_name):
2333    param_text_list = list()
2334    for param_node in command_node.findall('param'):
2335        param_text_list.append("".join(param_node.itertext()))
2336    return param_text_list
2337
2338
2339def is_get_pointer_command(command_name):
2340    return command_name.endswith('Pointerv') and command_name.startswith('glGet')
2341
2342
2343def format_capture_replay_param_access(api, command_name, param_text_list, cmd_packed_gl_enums,
2344                                       packed_param_types):
2345    param_access_strs = list()
2346    cmd_packed_enums = get_packed_enums(api, cmd_packed_gl_enums, command_name, packed_param_types,
2347                                        param_text_list)
2348    for i, param_text in enumerate(param_text_list):
2349        param_type = just_the_type_packed(param_text, cmd_packed_enums)
2350        param_name = just_the_name_packed(param_text, cmd_packed_enums)
2351
2352        pointer_count = param_type.count('*')
2353        is_const = 'const' in param_type
2354        if pointer_count == 0:
2355            param_template = 'params.getParam("{name}", ParamType::T{enum_type}, {index}).value.{enum_type}Val'
2356        elif pointer_count == 1 and is_const:
2357            param_template = 'replayContext->getAsConstPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
2358        elif pointer_count == 2 and is_const:
2359            param_template = 'replayContext->getAsPointerConstPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
2360        elif pointer_count == 1 or (pointer_count == 2 and is_get_pointer_command(command_name)):
2361            param_template = 'replayContext->getReadBufferPointer<{type}>(params.getParam("{name}", ParamType::T{enum_type}, {index}))'
2362        else:
2363            assert False, "Not supported param type %s" % param_type
2364
2365        param_access_strs.append(
2366            param_template.format(
2367                index=i,
2368                name=param_name,
2369                type=param_type,
2370                enum_type=get_capture_param_type_name(param_type)))
2371    return ",".join(param_access_strs)
2372
2373
2374def format_capture_replay_call_case(api, command_to_param_types_mapping, cmd_packed_gl_enums,
2375                                    packed_param_types):
2376    call_str_list = list()
2377    for command_name, cmd_param_texts in sorted(command_to_param_types_mapping.items()):
2378        entry_point_name = strip_api_prefix(command_name)
2379
2380        call_str_list.append(
2381            TEMPLATE_CAPTURE_REPLAY_CALL_CASE.format(
2382                entry_point=entry_point_name,
2383                param_value_access=format_capture_replay_param_access(
2384                    api, command_name, cmd_param_texts, cmd_packed_gl_enums, packed_param_types),
2385                context_call=entry_point_name[0].lower() + entry_point_name[1:],
2386            ))
2387
2388    return '\n'.join(call_str_list)
2389
2390
2391def write_capture_replay_source(api, all_commands_nodes, gles_command_names, cmd_packed_gl_enums,
2392                                packed_param_types):
2393    all_commands_names = set(gles_command_names)
2394
2395    command_to_param_types_mapping = dict()
2396    for command_node in all_commands_nodes:
2397        command_name = command_node.find('proto').find('name').text
2398        if command_name not in all_commands_names:
2399            continue
2400
2401        command_to_param_types_mapping[command_name] = get_command_params_text(
2402            command_node, command_name)
2403
2404    call_replay_cases = format_capture_replay_call_case(api, command_to_param_types_mapping,
2405                                                        cmd_packed_gl_enums, packed_param_types)
2406
2407    source_content = TEMPLATE_CAPTURE_REPLAY_SOURCE.format(
2408        script_name=os.path.basename(sys.argv[0]),
2409        data_source_name="gl.xml and gl_angle_ext.xml",
2410        call_replay_cases=call_replay_cases,
2411    )
2412    source_file_path = registry_xml.script_relative(
2413        "../src/libANGLE/capture/frame_capture_replay_autogen.cpp")
2414    with open(source_file_path, 'w') as f:
2415        f.write(source_content)
2416
2417
2418def write_windows_def_file(data_source_name, lib, libexport, folder, exports):
2419
2420    content = TEMPLATE_WINDOWS_DEF_FILE.format(
2421        script_name=os.path.basename(sys.argv[0]),
2422        data_source_name=data_source_name,
2423        exports="\n".join(exports),
2424        lib=libexport)
2425
2426    path = path_to(folder, "%s_autogen.def" % lib)
2427
2428    with open(path, "w") as out:
2429        out.write(content)
2430        out.close()
2431
2432
2433def get_exports(commands, fmt=None):
2434    if fmt:
2435        return ["    %s" % fmt(cmd) for cmd in sorted(commands)]
2436    else:
2437        return ["    %s" % cmd for cmd in sorted(commands)]
2438
2439
2440# Get EGL exports
2441def get_egl_exports():
2442
2443    egl = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
2444    exports = []
2445
2446    capser = lambda fn: "EGL_" + fn[3:]
2447
2448    for major, minor in registry_xml.EGL_VERSIONS:
2449        annotation = "{}_{}".format(major, minor)
2450        name_prefix = "EGL_VERSION_"
2451
2452        feature_name = "{}{}".format(name_prefix, annotation)
2453
2454        egl.AddCommands(feature_name, annotation)
2455
2456        commands = egl.commands[annotation]
2457
2458        if len(commands) == 0:
2459            continue
2460
2461        exports.append("\n    ; EGL %d.%d" % (major, minor))
2462        exports += get_exports(commands, capser)
2463
2464    egl.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
2465
2466    for extension_name, ext_cmd_names in sorted(egl.ext_data.items()):
2467
2468        if len(ext_cmd_names) == 0:
2469            continue
2470
2471        exports.append("\n    ; %s" % extension_name)
2472        exports += get_exports(ext_cmd_names, capser)
2473
2474    return exports
2475
2476
2477# Construct a mapping from an EGL EP to object function
2478def get_egl_entry_point_labeled_object(ep_to_object, cmd_stripped, params, packed_enums):
2479
2480    if not ep_to_object:
2481        return ""
2482
2483    # Finds a packed parameter name in a list of params
2484    def find_param(params, type_name, packed_enums):
2485        for param in params:
2486            if just_the_type_packed(param, packed_enums).split(' ')[0] == type_name:
2487                return just_the_name_packed(param, packed_enums)
2488        return None
2489
2490    display_param = find_param(params, "egl::Display", packed_enums)
2491
2492    # For entry points not listed in the JSON file, they default to an EGLDisplay or nothing.
2493    if cmd_stripped not in ep_to_object:
2494        if display_param:
2495            return "GetDisplayIfValid(%s)" % display_param
2496        return "nullptr"
2497
2498    # We first handle a few special cases for certain type categories.
2499    category = ep_to_object[cmd_stripped]
2500    if category == "Thread":
2501        return "GetThreadIfValid(thread)"
2502    found_param = find_param(params, category, packed_enums)
2503    if category == "Context" and not found_param:
2504        return "GetContextIfValid(thread->getDisplay(), thread->getContext())"
2505    assert found_param, "Did not find %s for %s: %s" % (category, cmd_stripped, str(params))
2506    if category == "Device":
2507        return "GetDeviceIfValid(%s)" % found_param
2508    if category == "LabeledObject":
2509        object_type_param = find_param(params, "ObjectType", packed_enums)
2510        return "GetLabeledObjectIfValid(thread, %s, %s, %s)" % (display_param, object_type_param,
2511                                                                found_param)
2512
2513    # We then handle the general case which handles the rest of the type categories.
2514    return "Get%sIfValid(%s, %s)" % (category, display_param, found_param)
2515
2516
2517LOCK_GLOBAL_SURFACE = "ANGLE_SCOPED_GLOBAL_SURFACE_LOCK();"
2518LOCK_GLOBAL = "ANGLE_SCOPED_GLOBAL_LOCK();"
2519
2520LOCK_ORDERING = {
2521    LOCK_GLOBAL_SURFACE: 0,
2522    LOCK_GLOBAL: 1,
2523}
2524
2525
2526def ordered_lock_statements(*locks):
2527    return "".join(sorted(locks, key=lambda lock: LOCK_ORDERING[lock]))
2528
2529
2530def get_locks(api, cmd_name, params):
2531
2532    if api != apis.EGL:
2533        return ordered_lock_statements(LOCK_GLOBAL)
2534
2535    has_surface = False
2536
2537    for param in params:
2538        param_type = just_the_type(param)
2539        if param_type == "EGLSurface":
2540            has_surface = True
2541
2542    if has_surface:
2543        return ordered_lock_statements(LOCK_GLOBAL_SURFACE, LOCK_GLOBAL)
2544
2545    return ordered_lock_statements(LOCK_GLOBAL)
2546
2547
2548def get_prepare_swap_buffers_call(api, cmd_name, params):
2549    if cmd_name not in [
2550            "eglSwapBuffers", "eglSwapBuffersWithDamageKHR", "eglSwapBuffersWithFrameTokenANGLE"
2551    ]:
2552        return ""
2553
2554    passed_params = [None, None]
2555
2556    for param in params:
2557        param_type = just_the_type(param)
2558        if param_type == "EGLDisplay":
2559            passed_params[0] = param
2560        if param_type == "EGLSurface":
2561            passed_params[1] = param
2562
2563    return "ANGLE_EGLBOOLEAN_TRY(PrepareSwapBuffersANGLE(%s));" % (", ".join(
2564        [just_the_name(param) for param in passed_params]))
2565
2566
2567def get_preamble(api, cmd_name, params):
2568    preamble = ""
2569    preamble += get_prepare_swap_buffers_call(api, cmd_name, params)
2570    # TODO: others?
2571    return preamble
2572
2573
2574def write_stubs_header(api, annotation, title, data_source, out_file, all_commands, commands,
2575                       cmd_packed_egl_enums, packed_param_types):
2576
2577    stubs = []
2578
2579    for command in all_commands:
2580        proto = command.find('proto')
2581        cmd_name = proto.find('name').text
2582
2583        if cmd_name not in commands:
2584            continue
2585
2586        proto_text = "".join(proto.itertext())
2587
2588        if cmd_name in CUSTOM_EGL_ENTRY_POINTS:
2589            params = []
2590        else:
2591            params = [] if api == apis.CL else ["Thread *thread"]
2592
2593        params += ["".join(param.itertext()) for param in command.findall('param')]
2594        if params and just_the_name(params[-1]) == "errcode_ret":
2595            params[-1] = "cl_int &errorCode"
2596        return_type = proto_text[:-len(cmd_name)].strip()
2597
2598        if cmd_name in CUSTOM_EGL_ENTRY_POINTS:
2599            stubs.append("%s %s(%s);" %
2600                         (return_type, strip_api_prefix(cmd_name), ", ".join(params)))
2601        else:
2602            internal_params = get_internal_params(api, cmd_name, params, cmd_packed_egl_enums,
2603                                                  packed_param_types)
2604            stubs.append("%s %s(%s);" % (return_type, strip_api_prefix(cmd_name), internal_params))
2605
2606    args = {
2607        "annotation_lower": annotation.lower(),
2608        "annotation_upper": annotation.upper(),
2609        "data_source_name": data_source,
2610        "script_name": os.path.basename(sys.argv[0]),
2611        "stubs": "\n".join(stubs),
2612        "title": title,
2613    }
2614
2615    output = get_stubs_header_template(api).format(**args)
2616
2617    with open(out_file, "w") as f:
2618        f.write(output)
2619
2620
2621def main():
2622
2623    # auto_script parameters.
2624    if len(sys.argv) > 1:
2625        inputs = [
2626            'entry_point_packed_egl_enums.json', 'entry_point_packed_gl_enums.json',
2627            EGL_GET_LABELED_OBJECT_DATA_PATH
2628        ] + registry_xml.xml_inputs
2629        outputs = [
2630            CL_STUBS_HEADER_PATH,
2631            EGL_STUBS_HEADER_PATH,
2632            EGL_EXT_STUBS_HEADER_PATH,
2633            '../src/libOpenCL/libOpenCL_autogen.cpp',
2634            '../src/common/entry_points_enum_autogen.cpp',
2635            '../src/common/entry_points_enum_autogen.h',
2636            '../src/libANGLE/Context_gl_1_autogen.h',
2637            '../src/libANGLE/Context_gl_2_autogen.h',
2638            '../src/libANGLE/Context_gl_3_autogen.h',
2639            '../src/libANGLE/Context_gl_4_autogen.h',
2640            '../src/libANGLE/Context_gles_1_0_autogen.h',
2641            '../src/libANGLE/Context_gles_2_0_autogen.h',
2642            '../src/libANGLE/Context_gles_3_0_autogen.h',
2643            '../src/libANGLE/Context_gles_3_1_autogen.h',
2644            '../src/libANGLE/Context_gles_3_2_autogen.h',
2645            '../src/libANGLE/Context_gles_ext_autogen.h',
2646            '../src/libANGLE/capture/capture_gles_1_0_autogen.cpp',
2647            '../src/libANGLE/capture/capture_gles_1_0_autogen.h',
2648            '../src/libANGLE/capture/capture_gles_2_0_autogen.cpp',
2649            '../src/libANGLE/capture/capture_gles_2_0_autogen.h',
2650            '../src/libANGLE/capture/capture_gles_3_0_autogen.cpp',
2651            '../src/libANGLE/capture/capture_gles_3_0_autogen.h',
2652            '../src/libANGLE/capture/capture_gles_3_1_autogen.cpp',
2653            '../src/libANGLE/capture/capture_gles_3_1_autogen.h',
2654            '../src/libANGLE/capture/capture_gles_3_2_autogen.cpp',
2655            '../src/libANGLE/capture/capture_gles_3_2_autogen.h',
2656            '../src/libANGLE/capture/capture_gles_ext_autogen.cpp',
2657            '../src/libANGLE/capture/capture_gles_ext_autogen.h',
2658            '../src/libANGLE/capture/frame_capture_replay_autogen.cpp',
2659            '../src/libANGLE/capture/frame_capture_utils_autogen.cpp',
2660            '../src/libANGLE/capture/frame_capture_utils_autogen.h',
2661            '../src/libANGLE/validationCL_autogen.h',
2662            '../src/libANGLE/validationEGL_autogen.h',
2663            '../src/libANGLE/validationES1_autogen.h',
2664            '../src/libANGLE/validationES2_autogen.h',
2665            '../src/libANGLE/validationES31_autogen.h',
2666            '../src/libANGLE/validationES32_autogen.h',
2667            '../src/libANGLE/validationES3_autogen.h',
2668            '../src/libANGLE/validationESEXT_autogen.h',
2669            '../src/libANGLE/validationGL1_autogen.h',
2670            '../src/libANGLE/validationGL2_autogen.h',
2671            '../src/libANGLE/validationGL3_autogen.h',
2672            '../src/libANGLE/validationGL4_autogen.h',
2673            '../src/libEGL/libEGL_autogen.cpp',
2674            '../src/libEGL/libEGL_autogen.def',
2675            '../src/libGLESv2/entry_points_cl_autogen.cpp',
2676            '../src/libGLESv2/entry_points_cl_autogen.h',
2677            '../src/libGLESv2/entry_points_egl_autogen.cpp',
2678            '../src/libGLESv2/entry_points_egl_autogen.h',
2679            '../src/libGLESv2/entry_points_egl_ext_autogen.cpp',
2680            '../src/libGLESv2/entry_points_egl_ext_autogen.h',
2681            '../src/libGLESv2/entry_points_gles_1_0_autogen.cpp',
2682            '../src/libGLESv2/entry_points_gles_1_0_autogen.h',
2683            '../src/libGLESv2/entry_points_gles_2_0_autogen.cpp',
2684            '../src/libGLESv2/entry_points_gles_2_0_autogen.h',
2685            '../src/libGLESv2/entry_points_gles_3_0_autogen.cpp',
2686            '../src/libGLESv2/entry_points_gles_3_0_autogen.h',
2687            '../src/libGLESv2/entry_points_gles_3_1_autogen.cpp',
2688            '../src/libGLESv2/entry_points_gles_3_1_autogen.h',
2689            '../src/libGLESv2/entry_points_gles_3_2_autogen.cpp',
2690            '../src/libGLESv2/entry_points_gles_3_2_autogen.h',
2691            '../src/libGLESv2/entry_points_gles_ext_autogen.cpp',
2692            '../src/libGLESv2/entry_points_gles_ext_autogen.h',
2693            '../src/libGLESv2/libGLESv2_autogen.cpp',
2694            '../src/libGLESv2/libGLESv2_autogen.def',
2695            '../src/libGLESv2/libGLESv2_no_capture_autogen.def',
2696            '../src/libGLESv2/libGLESv2_with_capture_autogen.def',
2697            '../src/libGL/entry_points_gl_1_autogen.cpp',
2698            '../src/libGL/entry_points_gl_1_autogen.h',
2699            '../src/libGL/entry_points_gl_2_autogen.cpp',
2700            '../src/libGL/entry_points_gl_2_autogen.h',
2701            '../src/libGL/entry_points_gl_3_autogen.cpp',
2702            '../src/libGL/entry_points_gl_3_autogen.h',
2703            '../src/libGL/entry_points_gl_4_autogen.cpp',
2704            '../src/libGL/entry_points_gl_4_autogen.h',
2705            '../src/libGL/libGL_autogen.cpp',
2706            '../src/libGL/libGL_autogen.def',
2707        ]
2708
2709        if sys.argv[1] == 'inputs':
2710            print(','.join(inputs))
2711        elif sys.argv[1] == 'outputs':
2712            print(','.join(outputs))
2713        else:
2714            print('Invalid script parameters')
2715            return 1
2716        return 0
2717
2718    glesdecls = {}
2719    glesdecls['core'] = {}
2720    glesdecls['exts'] = {}
2721    for ver in registry_xml.GLES_VERSIONS:
2722        glesdecls['core'][ver] = []
2723    for ver in ['GLES1 Extensions', 'GLES2+ Extensions', 'ANGLE Extensions']:
2724        glesdecls['exts'][ver] = {}
2725
2726    libgles_ep_defs = []
2727    libgles_ep_exports = []
2728
2729    xml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')
2730
2731    # Stores core commands to keep track of duplicates
2732    all_commands_no_suffix = []
2733    all_commands_with_suffix = []
2734
2735    # First run through the main GLES entry points.  Since ES2+ is the primary use
2736    # case, we go through those first and then add ES1-only APIs at the end.
2737    for major_version, minor_version in registry_xml.GLES_VERSIONS:
2738        version = "{}_{}".format(major_version, minor_version)
2739        annotation = "GLES_{}".format(version)
2740        name_prefix = "GL_ES_VERSION_"
2741
2742        if major_version == 1:
2743            name_prefix = "GL_VERSION_ES_CM_"
2744
2745        comment = version.replace("_", ".")
2746        feature_name = "{}{}".format(name_prefix, version)
2747
2748        xml.AddCommands(feature_name, version)
2749
2750        version_commands = xml.commands[version]
2751        all_commands_no_suffix.extend(xml.commands[version])
2752        all_commands_with_suffix.extend(xml.commands[version])
2753
2754        eps = GLEntryPoints(apis.GLES, xml, version_commands)
2755        eps.decls.insert(0, "extern \"C\" {")
2756        eps.decls.append("} // extern \"C\"")
2757        eps.defs.insert(0, "extern \"C\" {")
2758        eps.defs.append("} // extern \"C\"")
2759
2760        # Write the version as a comment before the first EP.
2761        libgles_ep_exports.append("\n    ; OpenGL ES %s" % comment)
2762
2763        libgles_ep_defs += ["\n// OpenGL ES %s" % comment] + eps.export_defs
2764        libgles_ep_exports += get_exports(version_commands)
2765
2766        major_if_not_one = major_version if major_version != 1 else ""
2767        minor_if_not_zero = minor_version if minor_version != 0 else ""
2768
2769        header_includes = TEMPLATE_HEADER_INCLUDES.format(
2770            major=major_if_not_one, minor=minor_if_not_zero)
2771
2772        # We include the platform.h header since it undefines the conflicting MemoryBarrier macro.
2773        if major_version == 3 and minor_version == 1:
2774            header_includes += "\n#include \"common/platform.h\"\n"
2775
2776        version_annotation = "%s%s" % (major_version, minor_if_not_zero)
2777        source_includes = TEMPLATE_SOURCES_INCLUDES.format(
2778            header_version=annotation.lower(), validation_header_version="ES" + version_annotation)
2779
2780        write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_HEADER,
2781                   "\n".join(eps.decls), "h", header_includes, "libGLESv2", "gl.xml")
2782        write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(eps.defs),
2783                   "cpp", source_includes, "libGLESv2", "gl.xml")
2784
2785        glesdecls['core'][(major_version,
2786                           minor_version)] = get_decls(apis.GLES, CONTEXT_DECL_FORMAT,
2787                                                       xml.all_commands, version_commands, [],
2788                                                       GLEntryPoints.get_packed_enums())
2789
2790        validation_annotation = "ES%s%s" % (major_version, minor_if_not_zero)
2791        write_gl_validation_header(validation_annotation, "ES %s" % comment, eps.validation_protos,
2792                                   "gl.xml and gl_angle_ext.xml")
2793
2794        write_capture_header(version, comment, eps.capture_protos, eps.capture_pointer_funcs)
2795        write_capture_source(version, validation_annotation, comment, eps.capture_methods)
2796
2797    # After we finish with the main entry points, we process the extensions.
2798    extension_decls = ["extern \"C\" {"]
2799    extension_defs = ["extern \"C\" {"]
2800    extension_commands = []
2801
2802    # Accumulated validation prototypes.
2803    ext_validation_protos = []
2804    ext_capture_protos = []
2805    ext_capture_methods = []
2806    ext_capture_pointer_funcs = []
2807
2808    for gles1ext in registry_xml.gles1_extensions:
2809        glesdecls['exts']['GLES1 Extensions'][gles1ext] = []
2810    for glesext in registry_xml.gles_extensions:
2811        glesdecls['exts']['GLES2+ Extensions'][glesext] = []
2812    for angle_ext in registry_xml.angle_extensions:
2813        glesdecls['exts']['ANGLE Extensions'][angle_ext] = []
2814
2815    xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
2816
2817    for extension_name, ext_cmd_names in sorted(xml.ext_data.items()):
2818        extension_commands.extend(xml.ext_data[extension_name])
2819
2820        # Detect and filter duplicate extensions.
2821        eps = GLEntryPoints(apis.GLES, xml, ext_cmd_names)
2822
2823        # Write the extension name as a comment before the first EP.
2824        comment = "\n// {}".format(extension_name)
2825        libgles_ep_exports.append("\n    ; %s" % extension_name)
2826
2827        extension_defs += [comment] + eps.defs
2828        extension_decls += [comment] + eps.decls
2829
2830        # Avoid writing out entry points defined by a prior extension.
2831        for dupe in xml.ext_dupes[extension_name]:
2832            msg = "// {} is already defined.\n".format(strip_api_prefix(dupe))
2833            extension_defs.append(msg)
2834
2835        ext_validation_protos += [comment] + eps.validation_protos
2836        ext_capture_protos += [comment] + eps.capture_protos
2837        ext_capture_methods += eps.capture_methods
2838        ext_capture_pointer_funcs += eps.capture_pointer_funcs
2839
2840        libgles_ep_defs += [comment] + eps.export_defs
2841        libgles_ep_exports += get_exports(ext_cmd_names)
2842
2843        if (extension_name in registry_xml.gles1_extensions and
2844                extension_name not in GLES1_NO_CONTEXT_DECL_EXTENSIONS):
2845            glesdecls['exts']['GLES1 Extensions'][extension_name] = get_decls(
2846                apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
2847                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
2848        if extension_name in registry_xml.gles_extensions:
2849            glesdecls['exts']['GLES2+ Extensions'][extension_name] = get_decls(
2850                apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
2851                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
2852        if extension_name in registry_xml.angle_extensions:
2853            glesdecls['exts']['ANGLE Extensions'][extension_name] = get_decls(
2854                apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
2855                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
2856
2857    for name in extension_commands:
2858        all_commands_with_suffix.append(name)
2859        all_commands_no_suffix.append(strip_suffix(apis.GLES, name))
2860
2861    # Now we generate entry points for the desktop implementation
2862    desktop_gl_decls = {}
2863    desktop_gl_decls['core'] = {}
2864    for major, _ in registry_xml.DESKTOP_GL_VERSIONS:
2865        desktop_gl_decls['core'][(major, "X")] = []
2866
2867    libgl_ep_defs = []
2868    libgl_ep_exports = []
2869
2870    glxml = registry_xml.RegistryXML('gl.xml')
2871
2872    for major_version in sorted(
2873            set([major for (major, minor) in registry_xml.DESKTOP_GL_VERSIONS])):
2874        is_major = lambda ver: ver[0] == major_version
2875
2876        ver_decls = ["extern \"C\" {"]
2877        ver_defs = ["extern \"C\" {"]
2878        validation_protos = []
2879
2880        for _, minor_version in filter(is_major, registry_xml.DESKTOP_GL_VERSIONS):
2881            version = "{}_{}".format(major_version, minor_version)
2882            annotation = "GL_{}".format(version)
2883            name_prefix = "GL_VERSION_"
2884
2885            comment = version.replace("_", ".")
2886            feature_name = "{}{}".format(name_prefix, version)
2887
2888            glxml.AddCommands(feature_name, version)
2889
2890            all_libgl_commands = glxml.commands[version]
2891
2892            just_libgl_commands = [
2893                cmd for cmd in all_libgl_commands if cmd not in all_commands_no_suffix
2894            ]
2895            just_libgl_commands_suffix = [
2896                cmd for cmd in all_libgl_commands if cmd not in all_commands_with_suffix
2897            ]
2898
2899            # Validation duplicates handled with suffix
2900            eps_suffix = GLEntryPoints(apis.GL, glxml, just_libgl_commands_suffix)
2901            eps = GLEntryPoints(apis.GL, glxml, all_libgl_commands)
2902
2903            desktop_gl_decls['core'][(major_version,
2904                                      "X")] += get_decls(apis.GL, CONTEXT_DECL_FORMAT,
2905                                                         glxml.all_commands, just_libgl_commands,
2906                                                         all_commands_no_suffix,
2907                                                         GLEntryPoints.get_packed_enums())
2908
2909            # Write the version as a comment before the first EP.
2910            cpp_comment = "\n// GL %s" % comment
2911            def_comment = "\n    ; GL %s" % comment
2912
2913            libgl_ep_defs += [cpp_comment] + eps.export_defs
2914            libgl_ep_exports += [def_comment] + get_exports(all_libgl_commands)
2915            validation_protos += [cpp_comment] + eps_suffix.validation_protos
2916            ver_decls += [cpp_comment] + eps.decls
2917            ver_defs += [cpp_comment] + eps.defs
2918
2919        ver_decls.append("} // extern \"C\"")
2920        ver_defs.append("} // extern \"C\"")
2921        annotation = "GL_%d" % major_version
2922        name = "Desktop GL %s.x" % major_version
2923
2924        source_includes = TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES.format(annotation.lower(),
2925                                                                     major_version)
2926
2927        # Entry point files
2928        write_file(annotation, name, TEMPLATE_ENTRY_POINT_HEADER, "\n".join(ver_decls), "h",
2929                   DESKTOP_GL_HEADER_INCLUDES, "libGL", "gl.xml")
2930        write_file(annotation, name, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(ver_defs), "cpp",
2931                   source_includes, "libGL", "gl.xml")
2932
2933        # Validation files
2934        write_gl_validation_header("GL%s" % major_version, name, validation_protos, "gl.xml")
2935
2936    # OpenCL
2937    clxml = registry_xml.RegistryXML('cl.xml')
2938
2939    cl_validation_protos = []
2940    cl_decls = ["namespace cl\n{"]
2941    cl_defs = ["namespace cl\n{"]
2942    libcl_ep_defs = []
2943    libcl_windows_def_exports = []
2944    cl_commands = []
2945
2946    for major_version, minor_version in registry_xml.CL_VERSIONS:
2947        version = "%d_%d" % (major_version, minor_version)
2948        annotation = "CL_%s" % version
2949        name_prefix = "CL_VERSION_"
2950
2951        comment = version.replace("_", ".")
2952        feature_name = "%s%s" % (name_prefix, version)
2953
2954        clxml.AddCommands(feature_name, version)
2955
2956        cl_version_commands = clxml.commands[version]
2957        cl_commands += cl_version_commands
2958
2959        # Spec revs may have no new commands.
2960        if not cl_version_commands:
2961            continue
2962
2963        eps = CLEntryPoints(clxml, cl_version_commands)
2964
2965        comment = "\n// CL %d.%d" % (major_version, minor_version)
2966        win_def_comment = "\n    ; CL %d.%d" % (major_version, minor_version)
2967
2968        cl_decls += [comment] + eps.decls
2969        cl_defs += [comment] + eps.defs
2970        libcl_ep_defs += [comment] + eps.export_defs
2971        cl_validation_protos += [comment] + eps.validation_protos
2972        libcl_windows_def_exports += [win_def_comment] + get_exports(clxml.commands[version])
2973
2974    clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl'])
2975    for extension_name, ext_cmd_names in sorted(clxml.ext_data.items()):
2976
2977        # Extensions may have no new commands.
2978        if not ext_cmd_names:
2979            continue
2980
2981        # Detect and filter duplicate extensions.
2982        eps = CLEntryPoints(clxml, ext_cmd_names)
2983
2984        comment = "\n// %s" % extension_name
2985        win_def_comment = "\n    ; %s" % (extension_name)
2986
2987        cl_commands += ext_cmd_names
2988
2989        cl_decls += [comment] + eps.decls
2990        cl_defs += [comment] + eps.defs
2991        libcl_ep_defs += [comment] + eps.export_defs
2992        cl_validation_protos += [comment] + eps.validation_protos
2993        libcl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
2994
2995        # Avoid writing out entry points defined by a prior extension.
2996        for dupe in clxml.ext_dupes[extension_name]:
2997            msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
2998            cl_defs.append(msg)
2999
3000    cl_decls.append("}  // namespace cl")
3001    cl_defs.append("}  // namespace cl")
3002
3003    write_file("cl", "CL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(cl_decls), "h",
3004               LIBCL_HEADER_INCLUDES, "libGLESv2", "cl.xml")
3005    write_file("cl", "CL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(cl_defs), "cpp",
3006               LIBCL_SOURCE_INCLUDES, "libGLESv2", "cl.xml")
3007    write_validation_header("CL", "CL", cl_validation_protos, "cl.xml",
3008                            TEMPLATE_CL_VALIDATION_HEADER)
3009    write_stubs_header("CL", "cl", "CL", "cl.xml", CL_STUBS_HEADER_PATH, clxml.all_commands,
3010                       cl_commands, CLEntryPoints.get_packed_enums(), CL_PACKED_TYPES)
3011
3012    # EGL
3013    eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
3014
3015    egl_validation_protos = []
3016    egl_decls = ["extern \"C\" {"]
3017    egl_defs = ["extern \"C\" {"]
3018    libegl_ep_defs = []
3019    libegl_windows_def_exports = []
3020    egl_commands = []
3021
3022    for major_version, minor_version in registry_xml.EGL_VERSIONS:
3023        version = "%d_%d" % (major_version, minor_version)
3024        annotation = "EGL_%s" % version
3025        name_prefix = "EGL_VERSION_"
3026
3027        comment = version.replace("_", ".")
3028        feature_name = "%s%s" % (name_prefix, version)
3029
3030        eglxml.AddCommands(feature_name, version)
3031
3032        egl_version_commands = eglxml.commands[version]
3033        egl_commands += egl_version_commands
3034
3035        # Spec revs may have no new commands.
3036        if not egl_version_commands:
3037            continue
3038
3039        eps = EGLEntryPoints(eglxml, egl_version_commands)
3040
3041        comment = "\n// EGL %d.%d" % (major_version, minor_version)
3042        win_def_comment = "\n    ; EGL %d.%d" % (major_version, minor_version)
3043
3044        egl_decls += [comment] + eps.decls
3045        egl_defs += [comment] + eps.defs
3046        libegl_ep_defs += [comment] + eps.export_defs
3047        egl_validation_protos += [comment] + eps.validation_protos
3048        libegl_windows_def_exports += [win_def_comment] + get_exports(eglxml.commands[version])
3049
3050    egl_decls.append("} // extern \"C\"")
3051    egl_defs.append("} // extern \"C\"")
3052
3053    write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_decls), "h",
3054               EGL_HEADER_INCLUDES, "libGLESv2", "egl.xml")
3055    write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_defs), "cpp",
3056               EGL_SOURCE_INCLUDES, "libGLESv2", "egl.xml")
3057    write_stubs_header("EGL", "egl", "EGL", "egl.xml", EGL_STUBS_HEADER_PATH, eglxml.all_commands,
3058                       egl_commands, EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
3059
3060    eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
3061    egl_ext_decls = ["extern \"C\" {"]
3062    egl_ext_defs = ["extern \"C\" {"]
3063    egl_ext_commands = []
3064
3065    for extension_name, ext_cmd_names in sorted(eglxml.ext_data.items()):
3066
3067        # Extensions may have no new commands.
3068        if not ext_cmd_names:
3069            continue
3070
3071        # Detect and filter duplicate extensions.
3072        eps = EGLEntryPoints(eglxml, ext_cmd_names)
3073
3074        comment = "\n// %s" % extension_name
3075        win_def_comment = "\n    ; %s" % (extension_name)
3076
3077        egl_ext_commands += ext_cmd_names
3078
3079        egl_ext_decls += [comment] + eps.decls
3080        egl_ext_defs += [comment] + eps.defs
3081        libegl_ep_defs += [comment] + eps.export_defs
3082        egl_validation_protos += [comment] + eps.validation_protos
3083        libegl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
3084
3085        # Avoid writing out entry points defined by a prior extension.
3086        for dupe in eglxml.ext_dupes[extension_name]:
3087            msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
3088            egl_ext_defs.append(msg)
3089
3090    egl_ext_decls.append("} // extern \"C\"")
3091    egl_ext_defs.append("} // extern \"C\"")
3092
3093    write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_ext_decls),
3094               "h", EGL_EXT_HEADER_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
3095    write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_ext_defs),
3096               "cpp", EGL_EXT_SOURCE_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
3097    write_validation_header("EGL", "EGL", egl_validation_protos, "egl.xml and egl_angle_ext.xml",
3098                            TEMPLATE_EGL_VALIDATION_HEADER)
3099    write_stubs_header("EGL", "egl_ext", "EXT extension", "egl.xml and egl_angle_ext.xml",
3100                       EGL_EXT_STUBS_HEADER_PATH, eglxml.all_commands, egl_ext_commands,
3101                       EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
3102
3103    # WGL
3104    wglxml = registry_xml.RegistryXML('wgl.xml')
3105
3106    name_prefix = "WGL_VERSION_"
3107    version = "1_0"
3108    comment = version.replace("_", ".")
3109    feature_name = "{}{}".format(name_prefix, version)
3110    wglxml.AddCommands(feature_name, version)
3111    wgl_commands = wglxml.commands[version]
3112
3113    wgl_commands = [cmd if cmd[:3] == 'wgl' else 'wgl' + cmd for cmd in wgl_commands]
3114
3115    # Write the version as a comment before the first EP.
3116    libgl_ep_exports.append("\n    ; WGL %s" % comment)
3117
3118    # Other versions of these functions are used
3119    wgl_commands.remove("wglUseFontBitmaps")
3120    wgl_commands.remove("wglUseFontOutlines")
3121
3122    libgl_ep_exports += get_exports(wgl_commands)
3123    extension_decls.append("} // extern \"C\"")
3124    extension_defs.append("} // extern \"C\"")
3125
3126    write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_HEADER,
3127               "\n".join([item for item in extension_decls]), "h", GLES_EXT_HEADER_INCLUDES,
3128               "libGLESv2", "gl.xml and gl_angle_ext.xml")
3129    write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_SOURCE,
3130               "\n".join([item for item in extension_defs]), "cpp", GLES_EXT_SOURCE_INCLUDES,
3131               "libGLESv2", "gl.xml and gl_angle_ext.xml")
3132
3133    write_gl_validation_header("ESEXT", "ES extension", ext_validation_protos,
3134                               "gl.xml and gl_angle_ext.xml")
3135    write_capture_header("ext", "extension", ext_capture_protos, ext_capture_pointer_funcs)
3136    write_capture_source("ext", "ESEXT", "extension", ext_capture_methods)
3137
3138    write_context_api_decls(glesdecls, "gles")
3139    write_context_api_decls(desktop_gl_decls, "gl")
3140
3141    # Entry point enum
3142    cl_cmd_names = [strip_api_prefix(cmd) for cmd in clxml.all_cmd_names.get_all_commands()]
3143    egl_cmd_names = [strip_api_prefix(cmd) for cmd in eglxml.all_cmd_names.get_all_commands()]
3144    gles_cmd_names = ["Invalid"
3145                     ] + [strip_api_prefix(cmd) for cmd in xml.all_cmd_names.get_all_commands()]
3146    gl_cmd_names = [strip_api_prefix(cmd) for cmd in glxml.all_cmd_names.get_all_commands()]
3147    wgl_cmd_names = [strip_api_prefix(cmd) for cmd in wglxml.all_cmd_names.get_all_commands()]
3148    unsorted_enums = [("CL%s" % cmd, "cl%s" % cmd) for cmd in cl_cmd_names] + [
3149        ("EGL%s" % cmd, "egl%s" % cmd) for cmd in egl_cmd_names
3150    ] + [("GL%s" % cmd, "gl%s" % cmd) for cmd in set(gles_cmd_names + gl_cmd_names)
3151        ] + [("WGL%s" % cmd, "wgl%s" % cmd) for cmd in wgl_cmd_names]
3152    all_enums = sorted(unsorted_enums)
3153
3154    entry_points_enum_header = TEMPLATE_ENTRY_POINTS_ENUM_HEADER.format(
3155        script_name=os.path.basename(sys.argv[0]),
3156        data_source_name="gl.xml and gl_angle_ext.xml",
3157        lib="GL/GLES",
3158        entry_points_list=",\n".join(["    " + enum for (enum, _) in all_enums]))
3159
3160    entry_points_enum_header_path = path_to("common", "entry_points_enum_autogen.h")
3161    with open(entry_points_enum_header_path, "w") as out:
3162        out.write(entry_points_enum_header)
3163        out.close()
3164
3165    entry_points_cases = [
3166        TEMPLATE_ENTRY_POINTS_NAME_CASE.format(enum=enum, cmd=cmd) for (enum, cmd) in all_enums
3167    ]
3168    entry_points_enum_source = TEMPLATE_ENTRY_POINTS_ENUM_SOURCE.format(
3169        script_name=os.path.basename(sys.argv[0]),
3170        data_source_name="gl.xml and gl_angle_ext.xml",
3171        lib="GL/GLES",
3172        entry_points_name_cases="\n".join(entry_points_cases))
3173
3174    entry_points_enum_source_path = path_to("common", "entry_points_enum_autogen.cpp")
3175    with open(entry_points_enum_source_path, "w") as out:
3176        out.write(entry_points_enum_source)
3177        out.close()
3178
3179    write_export_files("\n".join([item for item in libgles_ep_defs]), LIBGLESV2_EXPORT_INCLUDES,
3180                       "gl.xml and gl_angle_ext.xml", "libGLESv2", "OpenGL ES")
3181    write_export_files("\n".join([item for item in libgl_ep_defs]), LIBGL_EXPORT_INCLUDES,
3182                       "gl.xml and wgl.xml", "libGL", "Windows GL")
3183    write_export_files("\n".join([item for item in libegl_ep_defs]),
3184                       LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE, "egl.xml and egl_angle_ext.xml",
3185                       "libEGL", "EGL")
3186    write_export_files("\n".join([item for item in libcl_ep_defs]), LIBCL_EXPORT_INCLUDES,
3187                       "cl.xml", "libOpenCL", "CL")
3188
3189    libgles_ep_exports += get_egl_exports()
3190
3191    everything = "Khronos and ANGLE XML files"
3192
3193    for lib in ["libGLESv2" + suffix for suffix in ["", "_no_capture", "_with_capture"]]:
3194        write_windows_def_file(everything, lib, lib, "libGLESv2", libgles_ep_exports)
3195    write_windows_def_file(everything, "libGL", "openGL32", "libGL", libgl_ep_exports)
3196    write_windows_def_file("egl.xml and egl_angle_ext.xml", "libEGL", "libEGL", "libEGL",
3197                           libegl_windows_def_exports)
3198
3199    all_gles_param_types = sorted(GLEntryPoints.all_param_types)
3200    all_egl_param_types = sorted(EGLEntryPoints.all_param_types)
3201    # Get a sorted list of param types without duplicates
3202    all_param_types = sorted(list(set(all_gles_param_types + all_egl_param_types)))
3203    write_capture_helper_header(all_param_types)
3204    write_capture_helper_source(all_param_types)
3205    write_capture_replay_source(apis.GLES, xml.all_commands, all_commands_no_suffix,
3206                                GLEntryPoints.get_packed_enums(), [])
3207
3208
3209if __name__ == '__main__':
3210    sys.exit(main())
3211