• 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 fnmatch
13import registry_xml
14from registry_xml import apis, script_relative, strip_api_prefix, api_enums
15
16# Paths
17CL_STUBS_HEADER_PATH = "../src/libGLESv2/cl_stubs_autogen.h"
18EGL_GET_LABELED_OBJECT_DATA_PATH = "../src/libGLESv2/egl_get_labeled_object_data.json"
19EGL_STUBS_HEADER_PATH = "../src/libGLESv2/egl_stubs_autogen.h"
20EGL_EXT_STUBS_HEADER_PATH = "../src/libGLESv2/egl_ext_stubs_autogen.h"
21
22# List of GLES1 extensions for which we don't need to add Context.h decls.
23GLES1_NO_CONTEXT_DECL_EXTENSIONS = [
24    "GL_OES_framebuffer_object",
25]
26
27# This is a list of exceptions for entry points which don't want to have
28# the EVENT macro. This is required for some debug marker entry points.
29NO_EVENT_MARKER_EXCEPTIONS_LIST = sorted([
30    "glPushGroupMarkerEXT",
31    "glPopGroupMarkerEXT",
32    "glInsertEventMarkerEXT",
33])
34
35ALIASING_EXCEPTIONS = [
36    # glRenderbufferStorageMultisampleEXT aliases
37    # glRenderbufferStorageMultisample on desktop GL, and is marked as such in
38    # the registry.  However, that is not correct for GLES where this entry
39    # point comes from GL_EXT_multisampled_render_to_texture which is never
40    # promoted to core GLES.
41    'renderbufferStorageMultisampleEXT',
42    # Other entry points where the extension behavior is not identical to core
43    # behavior.
44    'drawArraysInstancedBaseInstanceANGLE',
45    'drawElementsInstancedBaseVertexBaseInstanceANGLE',
46    'logicOpANGLE',
47]
48
49# These are the entry points which potentially are used first by an application
50# and require that the back ends are initialized before the front end is called.
51INIT_DICT = {
52    "clGetPlatformIDs": "false",
53    "clGetPlatformInfo": "false",
54    "clGetDeviceIDs": "false",
55    "clCreateContext": "false",
56    "clCreateContextFromType": "false",
57    "clIcdGetPlatformIDsKHR": "true",
58}
59
60# These are the only entry points that are allowed while pixel local storage is active.
61PLS_ALLOW_LIST = {
62    "ActiveTexture",
63    "BindBuffer",
64    "BindBufferBase",
65    "BindBufferRange",
66    "BindSampler",
67    "BindTexture",
68    "BindVertexArray",
69    "BufferData",
70    "BufferSubData",
71    "CheckFramebufferStatus",
72    "ClipControlEXT",
73    "CullFace",
74    "DepthFunc",
75    "DepthMask",
76    "DepthRangef",
77    "Disable",
78    "DisableVertexAttribArray",
79    "DispatchComputeIndirect",
80    "Enable",
81    "EnableClientState",
82    "EnableVertexAttribArray",
83    "EndPixelLocalStorageANGLE",
84    "FramebufferPixelLocalStorageInterruptANGLE",
85    "FrontFace",
86    "MapBufferRange",
87    "PixelLocalStorageBarrierANGLE",
88    "Scissor",
89    "StencilFunc",
90    "StencilFuncSeparate",
91    "StencilMask",
92    "StencilMaskSeparate",
93    "StencilOp",
94    "StencilOpSeparate",
95    "UnmapBuffer",
96    "UseProgram",
97    "ValidateProgram",
98    "Viewport",
99    "ProvokingVertexANGLE",
100    "FenceSync",
101    "FlushMappedBufferRange",
102}
103PLS_ALLOW_WILDCARDS = [
104    "BlendEquationSeparatei*",
105    "BlendEquationi*",
106    "BlendFuncSeparatei*",
107    "BlendFunci*",
108    "ClearBuffer*",
109    "ColorMaski*",
110    "DebugMessageCallback*",
111    "DebugMessageControl*",
112    "DebugMessageInsert*",
113    "Delete*",
114    "Disablei*",
115    "DrawArrays*",
116    "DrawElements*",
117    "DrawRangeElements*",
118    "Enablei*",
119    "Gen*",
120    "Get*",
121    "Is*",
122    "ObjectLabel*",
123    "ObjectPtrLabel*",
124    "PolygonMode*",
125    "PolygonOffset*",
126    "PopDebugGroup*",
127    "PushDebugGroup*",
128    "SamplerParameter*",
129    "TexParameter*",
130    "Uniform*",
131    "VertexAttrib*",
132]
133
134# These are the entry points which purely set state in the current context with
135# no interaction with the other contexts, including through shared resources.
136# As a result, they don't require the share group lock.
137CONTEXT_PRIVATE_LIST = [
138    'glActiveTexture',
139    'glBlendColor',
140    'glClearColor',
141    'glClearDepthf',
142    'glClearStencil',
143    'glClipControl',
144    'glColorMask',
145    'glColorMaski',
146    'glCoverageModulation',
147    'glCullFace',
148    'glDepthFunc',
149    'glDepthMask',
150    'glDepthRangef',
151    'glDisable',
152    'glDisablei',
153    'glEnable',
154    'glEnablei',
155    'glFrontFace',
156    'glHint',
157    'glIsEnabled',
158    'glIsEnabledi',
159    'glLineWidth',
160    'glLogicOpANGLE',
161    'glMinSampleShading',
162    'glPatchParameteri',
163    'glPixelStorei',
164    'glPolygonMode',
165    'glPolygonModeNV',
166    'glPolygonOffset',
167    'glPolygonOffsetClamp',
168    'glPrimitiveBoundingBox',
169    'glProvokingVertex',
170    'glSampleCoverage',
171    'glSampleMaski',
172    'glScissor',
173    'glShadingRate',
174    'glStencilFunc',
175    'glStencilFuncSeparate',
176    'glStencilMask',
177    'glStencilMaskSeparate',
178    'glStencilOp',
179    'glStencilOpSeparate',
180    'glViewport',
181    # GLES1 entry points
182    'glAlphaFunc',
183    'glAlphaFuncx',
184    'glClearColorx',
185    'glClearDepthx',
186    'glColor4f',
187    'glColor4ub',
188    'glColor4x',
189    'glDepthRangex',
190    'glLineWidthx',
191    'glLoadIdentity',
192    'glLogicOp',
193    'glMatrixMode',
194    'glPointSize',
195    'glPointSizex',
196    'glPopMatrix',
197    'glPolygonOffsetx',
198    'glPushMatrix',
199    'glSampleCoveragex',
200    'glShadeModel',
201]
202CONTEXT_PRIVATE_WILDCARDS = [
203    'glBlendFunc*',
204    'glBlendEquation*',
205    'glVertexAttrib[1-4]*',
206    'glVertexAttribI[1-4]*',
207    'glVertexAttribP[1-4]*',
208    'glVertexAttribL[1-4]*',
209    # GLES1 entry points
210    'glClipPlane[fx]',
211    'glGetClipPlane[fx]',
212    'glFog[fx]*',
213    'glFrustum[fx]',
214    'glGetLight[fx]v',
215    'glGetMaterial[fx]v',
216    'glGetTexEnv[fix]v',
217    'glLoadMatrix[fx]',
218    'glLight[fx]*',
219    'glLightModel[fx]*',
220    'glMaterial[fx]*',
221    'glMultMatrix[fx]',
222    'glMultiTexCoord4[fx]',
223    'glNormal3[fx]',
224    'glOrtho[fx]',
225    'glPointParameter[fx]*',
226    'glRotate[fx]',
227    'glScale[fx]',
228    'glTexEnv[fix]*',
229    'glTranslate[fx]',
230]
231
232TEMPLATE_ENTRY_POINT_HEADER = """\
233// GENERATED FILE - DO NOT EDIT.
234// Generated by {script_name} using data from {data_source_name}.
235//
236// Copyright 2020 The ANGLE Project Authors. All rights reserved.
237// Use of this source code is governed by a BSD-style license that can be
238// found in the LICENSE file.
239//
240// entry_points_{annotation_lower}_autogen.h:
241//   Defines the {comment} entry points.
242
243#ifndef {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
244#define {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
245
246{includes}
247
248{entry_points}
249
250#endif  // {lib}_ENTRY_POINTS_{annotation_upper}_AUTOGEN_H_
251"""
252
253TEMPLATE_ENTRY_POINT_SOURCE = """\
254// GENERATED FILE - DO NOT EDIT.
255// Generated by {script_name} using data from {data_source_name}.
256//
257// Copyright 2020 The ANGLE Project Authors. All rights reserved.
258// Use of this source code is governed by a BSD-style license that can be
259// found in the LICENSE file.
260//
261// entry_points_{annotation_lower}_autogen.cpp:
262//   Defines the {comment} entry points.
263
264{includes}
265
266{entry_points}
267"""
268
269TEMPLATE_ENTRY_POINTS_ENUM_HEADER = """\
270// GENERATED FILE - DO NOT EDIT.
271// Generated by {script_name} using data from {data_source_name}.
272//
273// Copyright 2020 The ANGLE Project Authors. All rights reserved.
274// Use of this source code is governed by a BSD-style license that can be
275// found in the LICENSE file.
276//
277// entry_points_enum_autogen.h:
278//   Defines the {lib} entry points enumeration.
279
280#ifndef COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
281#define COMMON_ENTRYPOINTSENUM_AUTOGEN_H_
282
283namespace angle
284{{
285enum class EntryPoint
286{{
287{entry_points_list}
288}};
289
290const char *GetEntryPointName(EntryPoint ep);
291}}  // namespace angle
292#endif  // COMMON_ENTRY_POINTS_ENUM_AUTOGEN_H_
293"""
294
295TEMPLATE_ENTRY_POINTS_NAME_CASE = """\
296        case EntryPoint::{enum}:
297            return "{cmd}";"""
298
299TEMPLATE_ENTRY_POINTS_ENUM_SOURCE = """\
300// GENERATED FILE - DO NOT EDIT.
301// Generated by {script_name} using data from {data_source_name}.
302//
303// Copyright 2020 The ANGLE Project Authors. All rights reserved.
304// Use of this source code is governed by a BSD-style license that can be
305// found in the LICENSE file.
306//
307// entry_points_enum_autogen.cpp:
308//   Helper methods for the {lib} entry points enumeration.
309
310#include "common/entry_points_enum_autogen.h"
311
312#include "common/debug.h"
313
314namespace angle
315{{
316const char *GetEntryPointName(EntryPoint ep)
317{{
318    switch (ep)
319    {{
320{entry_points_name_cases}
321        default:
322            UNREACHABLE();
323            return "error";
324    }}
325}}
326}}  // namespace angle
327"""
328
329TEMPLATE_LIB_ENTRY_POINT_SOURCE = """\
330// GENERATED FILE - DO NOT EDIT.
331// Generated by {script_name} using data from {data_source_name}.
332//
333// Copyright 2020 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// {lib_name}_autogen.cpp: Implements the exported {lib_description} functions.
338
339{includes}
340extern "C" {{
341{entry_points}
342}} // extern "C"
343"""
344
345TEMPLATE_ENTRY_POINT_DECL = """{angle_export}{return_type} {export_def} {name}({params});"""
346
347TEMPLATE_GLES_ENTRY_POINT_NO_RETURN = """\
348void GL_APIENTRY GL_{name}({params})
349{{
350    Context *context = {context_getter};
351    {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
352
353    if ({valid_context_check})
354    {{{packed_gl_enum_conversions}
355        {context_lock}
356        bool isCallValid = (context->skipValidation() || {validation_expression});
357        if (isCallValid)
358        {{
359            context->{name_lower_no_suffix}({internal_params});
360        }}
361        ANGLE_CAPTURE_GL({name}, isCallValid, {gl_capture_params});
362    }}
363    else
364    {{
365        {constext_lost_error_generator}
366    }}
367    {epilog}
368}}
369"""
370
371TEMPLATE_GLES_CONTEXT_PRIVATE_ENTRY_POINT_NO_RETURN = """\
372void GL_APIENTRY GL_{name}({params})
373{{
374    Context *context = {context_getter};
375    {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
376
377    if ({valid_context_check})
378    {{{packed_gl_enum_conversions}
379        bool isCallValid = (context->skipValidation() || {validation_expression});
380        if (isCallValid)
381        {{
382            ContextPrivate{name_no_suffix}({context_private_internal_params});
383        }}
384        ANGLE_CAPTURE_GL({name}, isCallValid, {gl_capture_params});
385    }}
386    else
387    {{
388        {constext_lost_error_generator}
389    }}
390    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
391}}
392"""
393
394TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN = """\
395{return_type} GL_APIENTRY GL_{name}({params})
396{{
397    Context *context = {context_getter};
398    {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
399
400    {return_type} returnValue;
401    if ({valid_context_check})
402    {{{packed_gl_enum_conversions}
403        {context_lock}
404        bool isCallValid = (context->skipValidation() || {validation_expression});
405        if (isCallValid)
406        {{
407            returnValue = context->{name_lower_no_suffix}({internal_params});
408        }}
409        else
410        {{
411            returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
412        }}
413        ANGLE_CAPTURE_GL({name}, isCallValid, {gl_capture_params}, returnValue);
414    }}
415    else
416    {{
417        {constext_lost_error_generator}
418        returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
419    }}
420    {epilog}
421    return returnValue;
422}}
423"""
424
425TEMPLATE_GLES_CONTEXT_PRIVATE_ENTRY_POINT_WITH_RETURN = """\
426{return_type} GL_APIENTRY GL_{name}({params})
427{{
428    Context *context = {context_getter};
429    {event_comment}EVENT(context, GL{name}, "context = %d{comma_if_needed}{format_params}", CID(context){comma_if_needed}{pass_params});
430
431    {return_type} returnValue;
432    if ({valid_context_check})
433    {{{packed_gl_enum_conversions}
434        bool isCallValid = (context->skipValidation() || {validation_expression});
435        if (isCallValid)
436        {{
437            returnValue = ContextPrivate{name_no_suffix}({context_private_internal_params});
438        }}
439        else
440        {{
441            returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
442        }}
443        ANGLE_CAPTURE_GL({name}, isCallValid, {gl_capture_params}, returnValue);
444    }}
445    else
446    {{
447        {constext_lost_error_generator}
448        returnValue = GetDefaultReturnValue<angle::EntryPoint::GL{name}, {return_type}>();
449    }}
450    ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());
451    return returnValue;
452}}
453"""
454
455TEMPLATE_EGL_ENTRY_POINT_NO_RETURN = """\
456void EGLAPIENTRY EGL_{name}({params})
457{{
458    {preamble}
459    Thread *thread = egl::GetCurrentThread();
460    {{
461        ANGLE_SCOPED_GLOBAL_LOCK();
462        EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
463
464        {packed_gl_enum_conversions}
465
466        {{
467            ANGLE_EGL_SCOPED_CONTEXT_LOCK({name}, thread{comma_if_needed_context_lock}{internal_context_lock_params});
468            if (IsEGLValidationEnabled())
469            {{
470                ANGLE_EGL_VALIDATE_VOID(thread, {name}, {labeled_object}, {internal_params});
471            }}
472            else
473            {{
474                {attrib_map_init}
475            }}
476
477            {name}(thread{comma_if_needed}{internal_params});
478        }}
479
480        ANGLE_CAPTURE_EGL({name}, true, {egl_capture_params});
481    }}
482    {epilog}
483}}
484"""
485
486TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN = """\
487{return_type} EGLAPIENTRY EGL_{name}({params})
488{{
489    {preamble}
490    Thread *thread = egl::GetCurrentThread();
491    {return_type} returnValue;
492    {{
493        ANGLE_SCOPED_GLOBAL_LOCK();
494        EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
495
496        {packed_gl_enum_conversions}
497
498        {{
499            ANGLE_EGL_SCOPED_CONTEXT_LOCK({name}, thread{comma_if_needed_context_lock}{internal_context_lock_params});
500            if (IsEGLValidationEnabled())
501            {{
502                ANGLE_EGL_VALIDATE(thread, {name}, {labeled_object}, {return_type}{comma_if_needed}{internal_params});
503            }}
504            else
505            {{
506                {attrib_map_init}
507            }}
508
509            returnValue = {name}(thread{comma_if_needed}{internal_params});
510        }}
511
512        ANGLE_CAPTURE_EGL({name}, true, {egl_capture_params}, returnValue);
513    }}
514    {epilog}
515    return returnValue;
516}}
517"""
518
519TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN_NO_LOCKS = """\
520{return_type} EGLAPIENTRY EGL_{name}({params})
521{{
522    {preamble}
523    Thread *thread = egl::GetCurrentThread();
524    {return_type} returnValue;
525
526    EGL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
527
528    {packed_gl_enum_conversions}
529
530    if (IsEGLValidationEnabled())
531    {{
532        ANGLE_EGL_VALIDATE(thread, {name}, {labeled_object}, {return_type}{comma_if_needed}{internal_params});
533    }}
534    else
535    {{
536        {attrib_map_init}
537    }}
538
539    returnValue = {name}(thread{comma_if_needed}{internal_params});
540
541    ANGLE_CAPTURE_EGL({name}, true, {egl_capture_params}, returnValue);
542
543    {epilog}
544    return returnValue;
545}}
546"""
547
548TEMPLATE_CL_ENTRY_POINT_NO_RETURN = """\
549void CL_API_CALL cl{name}({params})
550{{
551    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
552
553    {packed_gl_enum_conversions}
554
555    ANGLE_CL_VALIDATE_VOID({name}{comma_if_needed}{internal_params});
556
557    cl::gClErrorTls = CL_SUCCESS;
558    {name}({internal_params});
559}}
560"""
561
562TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR = """\
563cl_int CL_API_CALL cl{name}({params})
564{{{initialization}
565    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
566
567    {packed_gl_enum_conversions}
568
569    ANGLE_CL_VALIDATE_ERROR({name}{comma_if_needed}{internal_params});
570
571    cl::gClErrorTls = CL_SUCCESS;
572    return {name}({internal_params});
573}}
574"""
575
576TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET = """\
577{return_type} CL_API_CALL cl{name}({params})
578{{{initialization}
579    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
580
581    {packed_gl_enum_conversions}
582
583    ANGLE_CL_VALIDATE_ERRCODE_RET({name}{comma_if_needed}{internal_params});
584
585    cl::gClErrorTls      = CL_SUCCESS;
586    {return_type} object = {name}({internal_params});
587
588    ASSERT((cl::gClErrorTls == CL_SUCCESS) == (object != nullptr));
589    if (errcode_ret != nullptr)
590    {{
591        *errcode_ret = cl::gClErrorTls;
592    }}
593    return object;
594}}
595"""
596
597TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER = """\
598{return_type} CL_API_CALL cl{name}({params})
599{{{initialization}
600    CL_EVENT({name}, "{format_params}"{comma_if_needed}{pass_params});
601
602    {packed_gl_enum_conversions}
603
604    cl::gClErrorTls = CL_SUCCESS;
605    ANGLE_CL_VALIDATE_POINTER({name}{comma_if_needed}{internal_params});
606
607    return {name}({internal_params});
608}}
609"""
610
611TEMPLATE_CL_STUBS_HEADER = """\
612// GENERATED FILE - DO NOT EDIT.
613// Generated by {script_name} using data from {data_source_name}.
614//
615// Copyright 2021 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// {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
620
621#ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
622#define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
623
624#include "libANGLE/cl_types.h"
625
626namespace cl
627{{
628{stubs}
629}}  // namespace cl
630#endif  // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
631"""
632
633TEMPLATE_EGL_STUBS_HEADER = """\
634// GENERATED FILE - DO NOT EDIT.
635// Generated by {script_name} using data from {data_source_name}.
636//
637// Copyright 2020 The ANGLE Project Authors. All rights reserved.
638// Use of this source code is governed by a BSD-style license that can be
639// found in the LICENSE file.
640//
641// {annotation_lower}_stubs_autogen.h: Stubs for {title} entry points.
642
643#ifndef LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
644#define LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
645
646#include <EGL/egl.h>
647#include <EGL/eglext.h>
648
649#include "common/PackedEnums.h"
650#include "common/PackedEGLEnums_autogen.h"
651
652namespace gl
653{{
654class Context;
655}}  // namespace gl
656
657namespace egl
658{{
659class AttributeMap;
660class Device;
661class Display;
662class Image;
663class Stream;
664class Surface;
665class Sync;
666class Thread;
667struct Config;
668
669{stubs}
670}}  // namespace egl
671#endif  // LIBGLESV2_{annotation_upper}_STUBS_AUTOGEN_H_
672"""
673
674CONTEXT_HEADER = """\
675// GENERATED FILE - DO NOT EDIT.
676// Generated by {script_name} using data from {data_source_name}.
677//
678// Copyright 2020 The ANGLE Project Authors. All rights reserved.
679// Use of this source code is governed by a BSD-style license that can be
680// found in the LICENSE file.
681//
682// Context_{annotation_lower}_autogen.h: Creates a macro for interfaces in Context.
683
684#ifndef ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
685#define ANGLE_CONTEXT_{annotation_upper}_AUTOGEN_H_
686
687#define ANGLE_{annotation_upper}_CONTEXT_API \\
688{interface}
689
690#endif // ANGLE_CONTEXT_API_{version}_AUTOGEN_H_
691"""
692
693CONTEXT_DECL_FORMAT = """    {return_type} {name_lower_no_suffix}({internal_params}){maybe_const}; \\"""
694
695TEMPLATE_CL_ENTRY_POINT_EXPORT = """\
696{return_type} CL_API_CALL cl{name}({params})
697{{
698    return cl::GetDispatch().cl{name}({internal_params});
699}}
700"""
701
702TEMPLATE_GL_ENTRY_POINT_EXPORT = """\
703{return_type} GL_APIENTRY gl{name}({params})
704{{
705    return GL_{name}({internal_params});
706}}
707"""
708
709TEMPLATE_EGL_ENTRY_POINT_EXPORT = """\
710{return_type} EGLAPIENTRY egl{name}({params})
711{{
712    EnsureEGLLoaded();
713    return EGL_{name}({internal_params});
714}}
715"""
716
717TEMPLATE_GLX_ENTRY_POINT_EXPORT = """\
718{return_type} GLXENTRY {name}({params})
719{{
720    return GLX_{name}({internal_params});
721}}
722"""
723
724TEMPLATE_GLEXT_FUNCTION_POINTER = """typedef {return_type}(GL_APIENTRYP PFN{name_upper}PROC)({params});"""
725TEMPLATE_GLEXT_FUNCTION_PROTOTYPE = """{apicall} {return_type}GL_APIENTRY {name}({params});"""
726
727TEMPLATE_GL_VALIDATION_HEADER = """\
728// GENERATED FILE - DO NOT EDIT.
729// Generated by {script_name} using data from {data_source_name}.
730//
731// Copyright 2020 The ANGLE Project Authors. All rights reserved.
732// Use of this source code is governed by a BSD-style license that can be
733// found in the LICENSE file.
734//
735// validation{annotation}_autogen.h:
736//   Validation functions for the OpenGL {comment} entry points.
737
738#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
739#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
740
741#include "common/entry_points_enum_autogen.h"
742#include "common/PackedEnums.h"
743
744namespace gl
745{{
746class Context;
747class PrivateState;
748class ErrorSet;
749
750{prototypes}
751}}  // namespace gl
752
753#endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
754"""
755
756TEMPLATE_CL_VALIDATION_HEADER = """\
757// GENERATED FILE - DO NOT EDIT.
758// Generated by {script_name} using data from {data_source_name}.
759//
760// Copyright 2021 The ANGLE Project Authors. All rights reserved.
761// Use of this source code is governed by a BSD-style license that can be
762// found in the LICENSE file.
763//
764// validation{annotation}_autogen.h:
765//   Validation functions for the {comment} entry points.
766
767#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
768#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
769
770#include "libANGLE/validationCL.h"
771
772namespace cl
773{{
774{prototypes}
775}}  // namespace cl
776
777#endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
778"""
779
780TEMPLATE_EGL_VALIDATION_HEADER = """\
781// GENERATED FILE - DO NOT EDIT.
782// Generated by {script_name} using data from {data_source_name}.
783//
784// Copyright 2020 The ANGLE Project Authors. All rights reserved.
785// Use of this source code is governed by a BSD-style license that can be
786// found in the LICENSE file.
787//
788// validation{annotation}_autogen.h:
789//   Validation functions for the {comment} entry points.
790
791#ifndef LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
792#define LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
793
794#include "libANGLE/validationEGL.h"
795
796namespace egl
797{{
798{prototypes}
799}}  // namespace egl
800
801#endif  // LIBANGLE_VALIDATION_{annotation}_AUTOGEN_H_
802"""
803
804TEMPLATE_CONTEXT_PRIVATE_CALL_HEADER = """\
805// GENERATED FILE - DO NOT EDIT.
806// Generated by {script_name} using data from {data_source_name}.
807//
808// Copyright 2023 The ANGLE Project Authors. All rights reserved.
809// Use of this source code is governed by a BSD-style license that can be
810// found in the LICENSE file.
811//
812// context_private_call_{annotation}_autogen.h:
813//   Helpers that set/get state that is entirely privately accessed by the context.
814
815#ifndef LIBANGLE_CONTEXT_PRIVATE_CALL_{annotation}_AUTOGEN_H_
816#define LIBANGLE_CONTEXT_PRIVATE_CALL_{annotation}_AUTOGEN_H_
817
818#include "libANGLE/Context.h"
819
820namespace gl
821{{
822{prototypes}
823}}  // namespace gl
824
825#endif  // LIBANGLE_CONTEXT_PRIVATE_CALL_{annotation}_AUTOGEN_H_
826"""
827
828TEMPLATE_EGL_CONTEXT_LOCK_HEADER = """\
829// GENERATED FILE - DO NOT EDIT.
830// Generated by {script_name} using data from {data_source_name}.
831//
832// Copyright 2023 The ANGLE Project Authors. All rights reserved.
833// Use of this source code is governed by a BSD-style license that can be
834// found in the LICENSE file.
835//
836// {annotation_lower}_context_lock_autogen.h:
837//   Context Lock functions for the {comment} entry points.
838
839#ifndef LIBGLESV2_{annotation_upper}_CONTEXT_LOCK_AUTOGEN_H_
840#define LIBGLESV2_{annotation_upper}_CONTEXT_LOCK_AUTOGEN_H_
841
842#include "libGLESv2/global_state.h"
843
844namespace egl
845{{
846{prototypes}
847}}  // namespace egl
848
849#endif  // LIBGLESV2_{annotation_upper}_CONTEXT_LOCK_AUTOGEN_H_
850"""
851
852TEMPLATE_CAPTURE_HEADER = """\
853// GENERATED FILE - DO NOT EDIT.
854// Generated by {script_name} using data from {data_source_name}.
855//
856// Copyright 2020 The ANGLE Project Authors. All rights reserved.
857// Use of this source code is governed by a BSD-style license that can be
858// found in the LICENSE file.
859//
860// capture_{annotation_lower}_autogen.h:
861//   Capture functions for the OpenGL ES {comment} entry points.
862
863#ifndef LIBANGLE_CAPTURE_{annotation_upper}_AUTOGEN_H_
864#define LIBANGLE_CAPTURE_{annotation_upper}_AUTOGEN_H_
865
866#include "common/PackedEnums.h"
867#include "libANGLE/capture/FrameCapture.h"
868
869namespace {namespace}
870{{
871{prototypes}
872}}  // namespace {namespace}
873
874#endif  // LIBANGLE_CAPTURE_{annotation_upper}_AUTOGEN_H_
875"""
876
877TEMPLATE_CAPTURE_SOURCE = """\
878// GENERATED FILE - DO NOT EDIT.
879// Generated by {script_name} using data from {data_source_name}.
880//
881// Copyright 2020 The ANGLE Project Authors. All rights reserved.
882// Use of this source code is governed by a BSD-style license that can be
883// found in the LICENSE file.
884//
885// capture_{annotation_with_dash}_autogen.cpp:
886//   Capture functions for the OpenGL ES {comment} entry points.
887
888#include "libANGLE/capture/capture_{annotation_with_dash}_autogen.h"
889
890#include "common/gl_enum_utils.h"
891#include "libANGLE/Context.h"
892#include "libANGLE/capture/FrameCapture.h"
893#include "libANGLE/validation{annotation_no_dash}.h"
894
895using namespace angle;
896
897namespace {namespace}
898{{
899{capture_methods}
900}}  // namespace {namespace}
901"""
902
903TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE = """\
904CallCapture Capture{short_name}({params_with_type}, {return_value_type_original} returnValue)
905{{
906    ParamBuffer paramBuffer;
907
908    {parameter_captures}
909
910    ParamCapture returnValueCapture("returnValue", ParamType::T{return_value_type_custom});
911    InitParamValue(ParamType::T{return_value_type_custom}, returnValue, &returnValueCapture.value);
912    paramBuffer.addReturnValue(std::move(returnValueCapture));
913
914    return CallCapture(angle::EntryPoint::{api_upper}{short_name}, std::move(paramBuffer));
915}}
916"""
917
918TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE = """\
919CallCapture Capture{short_name}({params_with_type})
920{{
921    ParamBuffer paramBuffer;
922
923    {parameter_captures}
924
925    return CallCapture(angle::EntryPoint::{api_upper}{short_name}, std::move(paramBuffer));
926}}
927"""
928
929TEMPLATE_PARAMETER_CAPTURE_VALUE = """paramBuffer.addValueParam("{name}", ParamType::T{type}, {name});"""
930
931TEMPLATE_PARAMETER_CAPTURE_GL_ENUM = """paramBuffer.addEnumParam("{name}", {api_enum}::{group}, ParamType::T{type}, {name});"""
932
933TEMPLATE_PARAMETER_CAPTURE_POINTER = """
934    if (isCallValid)
935    {{
936        ParamCapture {name}Param("{name}", ParamType::T{type});
937        InitParamValue(ParamType::T{type}, {name}, &{name}Param.value);
938        {capture_name}({params}, &{name}Param);
939        paramBuffer.addParam(std::move({name}Param));
940    }}
941    else
942    {{
943        ParamCapture {name}Param("{name}", ParamType::T{type});
944        InitParamValue(ParamType::T{type}, static_cast<{cast_type}>(nullptr), &{name}Param.value);
945        paramBuffer.addParam(std::move({name}Param));
946    }}
947"""
948
949TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC = """void {name}({params});"""
950
951TEMPLATE_CAPTURE_REPLAY_SOURCE = """\
952// GENERATED FILE - DO NOT EDIT.
953// Generated by {script_name} using data from {data_source_name}.
954//
955// Copyright 2020 The ANGLE Project Authors. All rights reserved.
956// Use of this source code is governed by a BSD-style license that can be
957// found in the LICENSE file.
958//
959// frame_capture_replay_autogen.cpp:
960//   Replay captured GL calls.
961
962#include "angle_trace_gl.h"
963#include "common/debug.h"
964#include "common/frame_capture_utils.h"
965#include "frame_capture_test_utils.h"
966
967namespace angle
968{{
969void ReplayTraceFunctionCall(const CallCapture &call, const TraceFunctionMap &customFunctions)
970{{
971    const ParamBuffer &params = call.params;
972    const std::vector<ParamCapture> &captures = params.getParamCaptures();
973
974    switch (call.entryPoint)
975    {{
976{call_replay_cases}
977        default:
978            ASSERT(!call.customFunctionName.empty());
979            ReplayCustomFunctionCall(call, customFunctions);
980            break;
981    }}
982}}
983
984}}  // namespace angle
985
986"""
987
988TEMPLATE_REPLAY_CALL_CASE = """\
989        case angle::EntryPoint::{enum}:
990            {call}({params});
991            break;
992"""
993
994POINTER_FORMAT = "0x%016\" PRIxPTR \""
995UNSIGNED_LONG_LONG_FORMAT = "%llu"
996HEX_LONG_LONG_FORMAT = "0x%llX"
997
998FORMAT_DICT = {
999    "GLbitfield": "%s",
1000    "GLboolean": "%s",
1001    "GLbyte": "%d",
1002    "GLclampx": "0x%X",
1003    "GLDEBUGPROC": POINTER_FORMAT,
1004    "GLDEBUGPROCKHR": POINTER_FORMAT,
1005    "GLdouble": "%f",
1006    "GLeglClientBufferEXT": POINTER_FORMAT,
1007    "GLeglImageOES": POINTER_FORMAT,
1008    "GLenum": "%s",
1009    "GLfixed": "0x%X",
1010    "GLfloat": "%f",
1011    "GLint": "%d",
1012    "GLintptr": UNSIGNED_LONG_LONG_FORMAT,
1013    "GLshort": "%d",
1014    "GLsizei": "%d",
1015    "GLsizeiptr": UNSIGNED_LONG_LONG_FORMAT,
1016    "GLsync": POINTER_FORMAT,
1017    "GLubyte": "%d",
1018    "GLuint": "%u",
1019    "GLuint64": UNSIGNED_LONG_LONG_FORMAT,
1020    "GLushort": "%u",
1021    "int": "%d",
1022    # EGL-specific types
1023    "EGLBoolean": "%u",
1024    "EGLConfig": POINTER_FORMAT,
1025    "EGLContext": POINTER_FORMAT,
1026    "EGLDisplay": POINTER_FORMAT,
1027    "EGLSurface": POINTER_FORMAT,
1028    "EGLSync": POINTER_FORMAT,
1029    "EGLNativeDisplayType": POINTER_FORMAT,
1030    "EGLNativePixmapType": POINTER_FORMAT,
1031    "EGLNativeWindowType": POINTER_FORMAT,
1032    "EGLClientBuffer": POINTER_FORMAT,
1033    "EGLenum": "0x%X",
1034    "EGLint": "%d",
1035    "EGLImage": POINTER_FORMAT,
1036    "EGLTime": UNSIGNED_LONG_LONG_FORMAT,
1037    "EGLGetBlobFuncANDROID": POINTER_FORMAT,
1038    "EGLSetBlobFuncANDROID": POINTER_FORMAT,
1039    "EGLuint64KHR": UNSIGNED_LONG_LONG_FORMAT,
1040    "EGLSyncKHR": POINTER_FORMAT,
1041    "EGLnsecsANDROID": UNSIGNED_LONG_LONG_FORMAT,
1042    "EGLDeviceEXT": POINTER_FORMAT,
1043    "EGLDEBUGPROCKHR": POINTER_FORMAT,
1044    "EGLObjectKHR": POINTER_FORMAT,
1045    "EGLLabelKHR": POINTER_FORMAT,
1046    "EGLTimeKHR": UNSIGNED_LONG_LONG_FORMAT,
1047    "EGLImageKHR": POINTER_FORMAT,
1048    "EGLStreamKHR": POINTER_FORMAT,
1049    "EGLFrameTokenANGLE": HEX_LONG_LONG_FORMAT,
1050    # WGL-specific types
1051    "BOOL": "%u",
1052    "DWORD": POINTER_FORMAT,
1053    "FLOAT": "%f",
1054    "HDC": POINTER_FORMAT,
1055    "HENHMETAFILE": POINTER_FORMAT,
1056    "HGLRC": POINTER_FORMAT,
1057    "LPCSTR": POINTER_FORMAT,
1058    "LPGLYPHMETRICSFLOAT": POINTER_FORMAT,
1059    "UINT": "%u",
1060    # CL-specific types
1061    "size_t": "%zu",
1062    "cl_char": "%hhd",
1063    "cl_uchar": "%hhu",
1064    "cl_short": "%hd",
1065    "cl_ushort": "%hu",
1066    "cl_int": "%d",
1067    "cl_uint": "%u",
1068    "cl_long": "%lld",
1069    "cl_ulong": "%llu",
1070    "cl_half": "%hu",
1071    "cl_float": "%f",
1072    "cl_double": "%f",
1073    "cl_platform_id": POINTER_FORMAT,
1074    "cl_device_id": POINTER_FORMAT,
1075    "cl_context": POINTER_FORMAT,
1076    "cl_command_queue": POINTER_FORMAT,
1077    "cl_mem": POINTER_FORMAT,
1078    "cl_program": POINTER_FORMAT,
1079    "cl_kernel": POINTER_FORMAT,
1080    "cl_event": POINTER_FORMAT,
1081    "cl_sampler": POINTER_FORMAT,
1082    "cl_bool": "%u",
1083    "cl_bitfield": "%llu",
1084    "cl_properties": "%llu",
1085    "cl_device_type": "%llu",
1086    "cl_platform_info": "%u",
1087    "cl_device_info": "%u",
1088    "cl_device_fp_config": "%llu",
1089    "cl_device_mem_cache_type": "%u",
1090    "cl_device_local_mem_type": "%u",
1091    "cl_device_exec_capabilities": "%llu",
1092    "cl_device_svm_capabilities": "%llu",
1093    "cl_command_queue_properties": "%llu",
1094    "cl_device_partition_property": "%zu",
1095    "cl_device_affinity_domain": "%llu",
1096    "cl_context_properties": "%zu",
1097    "cl_context_info": "%u",
1098    "cl_queue_properties": "%llu",
1099    "cl_command_queue_info": "%u",
1100    "cl_channel_order": "%u",
1101    "cl_channel_type": "%u",
1102    "cl_mem_flags": "%llu",
1103    "cl_svm_mem_flags": "%llu",
1104    "cl_mem_object_type": "%u",
1105    "cl_mem_info": "%u",
1106    "cl_mem_migration_flags": "%llu",
1107    "cl_mem_properties": "%llu",
1108    "cl_image_info": "%u",
1109    "cl_buffer_create_type": "%u",
1110    "cl_addressing_mode": "%u",
1111    "cl_filter_mode": "%u",
1112    "cl_sampler_info": "%u",
1113    "cl_map_flags": "%llu",
1114    "cl_pipe_properties": "%zu",
1115    "cl_pipe_info": "%u",
1116    "cl_program_info": "%u",
1117    "cl_program_build_info": "%u",
1118    "cl_program_binary_type": "%u",
1119    "cl_build_status": "%d",
1120    "cl_kernel_info": "%u",
1121    "cl_kernel_arg_info": "%u",
1122    "cl_kernel_arg_address_qualifier": "%u",
1123    "cl_kernel_arg_access_qualifier": "%u",
1124    "cl_kernel_arg_type_qualifier": "%llu",
1125    "cl_kernel_work_group_info": "%u",
1126    "cl_kernel_sub_group_info": "%u",
1127    "cl_event_info": "%u",
1128    "cl_command_type": "%u",
1129    "cl_profiling_info": "%u",
1130    "cl_sampler_properties": "%llu",
1131    "cl_kernel_exec_info": "%u",
1132    "cl_device_atomic_capabilities": "%llu",
1133    "cl_khronos_vendor_id": "%u",
1134    "cl_version": "%u",
1135    "cl_device_device_enqueue_capabilities": "%llu",
1136}
1137
1138TEMPLATE_HEADER_INCLUDES = """\
1139#include <GLES{major}/gl{major}{minor}.h>
1140#include <export.h>"""
1141
1142TEMPLATE_SOURCES_INCLUDES = """\
1143#include "libGLESv2/entry_points_{header_version}_autogen.h"
1144
1145#include "common/entry_points_enum_autogen.h"
1146#include "common/gl_enum_utils.h"
1147#include "libANGLE/Context.h"
1148#include "libANGLE/Context.inl.h"
1149#include "libANGLE/context_private_call_gles_autogen.h"
1150#include "libANGLE/capture/capture_{header_version}_autogen.h"
1151#include "libANGLE/validation{validation_header_version}.h"
1152#include "libANGLE/entry_points_utils.h"
1153#include "libGLESv2/global_state.h"
1154
1155using namespace gl;
1156"""
1157
1158GLES_EXT_HEADER_INCLUDES = TEMPLATE_HEADER_INCLUDES.format(
1159    major="", minor="") + """
1160#include <GLES/glext.h>
1161#include <GLES2/gl2.h>
1162#include <GLES2/gl2ext.h>
1163#include <GLES3/gl32.h>
1164"""
1165
1166GLES_EXT_SOURCE_INCLUDES = TEMPLATE_SOURCES_INCLUDES.format(
1167    header_version="gles_ext", validation_header_version="ESEXT") + """
1168#include "libANGLE/capture/capture_gles_1_0_autogen.h"
1169#include "libANGLE/capture/capture_gles_2_0_autogen.h"
1170#include "libANGLE/capture/capture_gles_3_0_autogen.h"
1171#include "libANGLE/capture/capture_gles_3_1_autogen.h"
1172#include "libANGLE/capture/capture_gles_3_2_autogen.h"
1173#include "libANGLE/validationES1.h"
1174#include "libANGLE/validationES2.h"
1175#include "libANGLE/validationES3.h"
1176#include "libANGLE/validationES31.h"
1177#include "libANGLE/validationES32.h"
1178
1179using namespace gl;
1180"""
1181
1182DESKTOP_GL_HEADER_INCLUDES = """\
1183#include <export.h>
1184#include "angle_gl.h"
1185"""
1186
1187TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES = """\
1188#include "libGLESv2/entry_points_{0}_autogen.h"
1189
1190#include "common/gl_enum_utils.h"
1191#include "libANGLE/Context.h"
1192#include "libANGLE/Context.inl.h"
1193#include "libANGLE/context_private_call_gles_autogen.h"
1194#include "libANGLE/context_private_call_gl_autogen.h"
1195#include "libANGLE/capture/capture_gl_{1}_autogen.h"
1196#include "libANGLE/validationEGL.h"
1197#include "libANGLE/validationES.h"
1198#include "libANGLE/validationES1.h"
1199#include "libANGLE/validationES2.h"
1200#include "libANGLE/validationES3.h"
1201#include "libANGLE/validationES31.h"
1202#include "libANGLE/validationES32.h"
1203#include "libANGLE/validationESEXT.h"
1204#include "libANGLE/validationGL{1}_autogen.h"
1205#include "libANGLE/entry_points_utils.h"
1206#include "libGLESv2/global_state.h"
1207
1208using namespace gl;
1209"""
1210
1211EGL_HEADER_INCLUDES = """\
1212#include <EGL/egl.h>
1213#include <export.h>
1214"""
1215
1216EGL_SOURCE_INCLUDES = """\
1217#include "libGLESv2/entry_points_egl_autogen.h"
1218#include "libGLESv2/entry_points_egl_ext_autogen.h"
1219
1220#include "libANGLE/capture/capture_egl_autogen.h"
1221#include "libANGLE/entry_points_utils.h"
1222#include "libANGLE/validationEGL_autogen.h"
1223#include "libGLESv2/egl_context_lock_impl.h"
1224#include "libGLESv2/egl_stubs_autogen.h"
1225#include "libGLESv2/egl_ext_stubs_autogen.h"
1226#include "libGLESv2/global_state.h"
1227
1228using namespace egl;
1229"""
1230
1231EGL_EXT_HEADER_INCLUDES = """\
1232#include <EGL/egl.h>
1233#include <EGL/eglext.h>
1234#include <export.h>
1235"""
1236
1237EGL_EXT_SOURCE_INCLUDES = """\
1238#include "libGLESv2/entry_points_egl_ext_autogen.h"
1239
1240#include "libANGLE/capture/capture_egl_autogen.h"
1241#include "libANGLE/entry_points_utils.h"
1242#include "libANGLE/validationEGL_autogen.h"
1243#include "libGLESv2/egl_context_lock_impl.h"
1244#include "libGLESv2/egl_ext_stubs_autogen.h"
1245#include "libGLESv2/global_state.h"
1246
1247using namespace egl;
1248"""
1249
1250LIBCL_EXPORT_INCLUDES = """
1251#include "libOpenCL/dispatch.h"
1252"""
1253
1254LIBGLESV2_EXPORT_INCLUDES = """
1255#include "angle_gl.h"
1256
1257#include "libGLESv2/entry_points_gles_1_0_autogen.h"
1258#include "libGLESv2/entry_points_gles_2_0_autogen.h"
1259#include "libGLESv2/entry_points_gles_3_0_autogen.h"
1260#include "libGLESv2/entry_points_gles_3_1_autogen.h"
1261#include "libGLESv2/entry_points_gles_3_2_autogen.h"
1262#include "libGLESv2/entry_points_gles_ext_autogen.h"
1263
1264#if defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)
1265#   include "libGLESv2/entry_points_gl_1_autogen.h"
1266#   include "libGLESv2/entry_points_gl_2_autogen.h"
1267#   include "libGLESv2/entry_points_gl_3_autogen.h"
1268#   include "libGLESv2/entry_points_gl_4_autogen.h"
1269#endif
1270
1271#include "common/event_tracer.h"
1272"""
1273
1274LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE = """
1275#include "anglebase/no_destructor.h"
1276#include "common/system_utils.h"
1277
1278#include <memory>
1279
1280#if defined(ANGLE_USE_EGL_LOADER)
1281#    include "libEGL/egl_loader_autogen.h"
1282#else
1283#    include "libGLESv2/entry_points_egl_autogen.h"
1284#    include "libGLESv2/entry_points_egl_ext_autogen.h"
1285#endif  // defined(ANGLE_USE_EGL_LOADER)
1286
1287namespace
1288{
1289#if defined(ANGLE_USE_EGL_LOADER)
1290bool gLoaded = false;
1291void *gEntryPointsLib = nullptr;
1292
1293GenericProc KHRONOS_APIENTRY GlobalLoad(const char *symbol)
1294{
1295    return reinterpret_cast<GenericProc>(angle::GetLibrarySymbol(gEntryPointsLib, symbol));
1296}
1297
1298void EnsureEGLLoaded()
1299{
1300    if (gLoaded)
1301    {
1302        return;
1303    }
1304
1305    std::string errorOut;
1306    gEntryPointsLib = OpenSystemLibraryAndGetError(ANGLE_DISPATCH_LIBRARY, angle::SearchType::ModuleDir, &errorOut);
1307    if (gEntryPointsLib)
1308    {
1309        LoadLibEGL_EGL(GlobalLoad);
1310        gLoaded = true;
1311    }
1312    else
1313    {
1314        fprintf(stderr, "Error loading EGL entry points: %s\\n", errorOut.c_str());
1315    }
1316}
1317#else
1318void EnsureEGLLoaded() {}
1319#endif  // defined(ANGLE_USE_EGL_LOADER)
1320}  // anonymous namespace
1321"""
1322
1323LIBCL_HEADER_INCLUDES = """\
1324#include "angle_cl.h"
1325"""
1326
1327LIBCL_SOURCE_INCLUDES = """\
1328#include "libGLESv2/entry_points_cl_autogen.h"
1329
1330#include "libANGLE/validationCL_autogen.h"
1331#include "libGLESv2/cl_stubs_autogen.h"
1332#include "libGLESv2/entry_points_cl_utils.h"
1333"""
1334
1335TEMPLATE_EVENT_COMMENT = """\
1336    // Don't run the EVENT() macro on the EXT_debug_marker entry points.
1337    // It can interfere with the debug events being set by the caller.
1338    // """
1339
1340TEMPLATE_CAPTURE_PROTO = "angle::CallCapture Capture%s(%s);"
1341
1342TEMPLATE_VALIDATION_PROTO = "%s Validate%s(%s);"
1343
1344TEMPLATE_CONTEXT_PRIVATE_CALL_PROTO = "%s ContextPrivate%s(%s);"
1345
1346TEMPLATE_CONTEXT_LOCK_PROTO = "ScopedContextMutexLock GetContextLock_%s(%s);"
1347
1348TEMPLATE_WINDOWS_DEF_FILE = """\
1349; GENERATED FILE - DO NOT EDIT.
1350; Generated by {script_name} using data from {data_source_name}.
1351;
1352; Copyright 2020 The ANGLE Project Authors. All rights reserved.
1353; Use of this source code is governed by a BSD-style license that can be
1354; found in the LICENSE file.
1355LIBRARY {lib}
1356EXPORTS
1357{exports}
1358"""
1359
1360TEMPLATE_FRAME_CAPTURE_UTILS_HEADER = """\
1361// GENERATED FILE - DO NOT EDIT.
1362// Generated by {script_name} using data from {data_source_name}.
1363//
1364// Copyright 2020 The ANGLE Project Authors. All rights reserved.
1365// Use of this source code is governed by a BSD-style license that can be
1366// found in the LICENSE file.
1367//
1368// frame_capture_utils_autogen.h:
1369//   ANGLE Frame capture types and helper functions.
1370
1371#ifndef COMMON_FRAME_CAPTURE_UTILS_AUTOGEN_H_
1372#define COMMON_FRAME_CAPTURE_UTILS_AUTOGEN_H_
1373
1374#include "common/PackedEnums.h"
1375
1376namespace angle
1377{{
1378enum class ParamType
1379{{
1380    {param_types}
1381}};
1382
1383constexpr uint32_t kParamTypeCount = {param_type_count};
1384
1385union ParamValue
1386{{
1387    {param_union_values}
1388}};
1389
1390template <ParamType PType, typename T>
1391T GetParamVal(const ParamValue &value);
1392
1393{get_param_val_specializations}
1394
1395template <ParamType PType, typename T>
1396T GetParamVal(const ParamValue &value)
1397{{
1398    UNREACHABLE();
1399    return T();
1400}}
1401
1402template <typename T>
1403T AccessParamValue(ParamType paramType, const ParamValue &value)
1404{{
1405    switch (paramType)
1406    {{
1407{access_param_value_cases}
1408    }}
1409    UNREACHABLE();
1410    return T();
1411}}
1412
1413template <ParamType PType, typename T>
1414void SetParamVal(T valueIn, ParamValue *valueOut);
1415
1416{set_param_val_specializations}
1417
1418template <ParamType PType, typename T>
1419void SetParamVal(T valueIn, ParamValue *valueOut)
1420{{
1421    UNREACHABLE();
1422}}
1423
1424template <typename T>
1425void InitParamValue(ParamType paramType, T valueIn, ParamValue *valueOut)
1426{{
1427    switch (paramType)
1428    {{
1429{init_param_value_cases}
1430    }}
1431}}
1432
1433struct CallCapture;
1434struct ParamCapture;
1435
1436void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param);
1437const char *ParamTypeToString(ParamType paramType);
1438
1439enum class ResourceIDType
1440{{
1441    {resource_id_types}
1442}};
1443
1444ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType);
1445const char *GetResourceIDTypeName(ResourceIDType resourceIDType);
1446
1447template <typename ResourceType>
1448struct GetResourceIDTypeFromType;
1449
1450{type_to_resource_id_type_structs}
1451}}  // namespace angle
1452
1453#endif  // COMMON_FRAME_CAPTURE_UTILS_AUTOGEN_H_
1454"""
1455
1456TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE = """\
1457// GENERATED FILE - DO NOT EDIT.
1458// Generated by {script_name} using data from {data_source_name}.
1459//
1460// Copyright 2020 The ANGLE Project Authors. All rights reserved.
1461// Use of this source code is governed by a BSD-style license that can be
1462// found in the LICENSE file.
1463//
1464// frame_capture_utils_autogen.cpp:
1465//   ANGLE Frame capture types and helper functions.
1466
1467#include "common/frame_capture_utils_autogen.h"
1468
1469#include "common/frame_capture_utils.h"
1470
1471namespace angle
1472{{
1473void WriteParamCaptureReplay(std::ostream &os, const CallCapture &call, const ParamCapture &param)
1474{{
1475    switch (param.type)
1476    {{
1477{write_param_type_to_stream_cases}
1478        default:
1479            os << "unknown";
1480            break;
1481    }}
1482}}
1483
1484const char *ParamTypeToString(ParamType paramType)
1485{{
1486    switch (paramType)
1487    {{
1488{param_type_to_string_cases}
1489        default:
1490            UNREACHABLE();
1491            return "unknown";
1492    }}
1493}}
1494
1495ResourceIDType GetResourceIDTypeFromParamType(ParamType paramType)
1496{{
1497    switch (paramType)
1498    {{
1499{param_type_resource_id_cases}
1500        default:
1501            return ResourceIDType::InvalidEnum;
1502    }}
1503}}
1504
1505const char *GetResourceIDTypeName(ResourceIDType resourceIDType)
1506{{
1507    switch (resourceIDType)
1508    {{
1509{resource_id_type_name_cases}
1510        default:
1511            UNREACHABLE();
1512            return "GetResourceIDTypeName error";
1513    }}
1514}}
1515}}  // namespace angle
1516"""
1517
1518TEMPLATE_GET_PARAM_VAL_SPECIALIZATION = """\
1519template <>
1520inline {type} GetParamVal<ParamType::T{enum}, {type}>(const ParamValue &value)
1521{{
1522    return value.{union_name};
1523}}"""
1524
1525TEMPLATE_ACCESS_PARAM_VALUE_CASE = """\
1526        case ParamType::T{enum}:
1527            return GetParamVal<ParamType::T{enum}, T>(value);"""
1528
1529TEMPLATE_SET_PARAM_VAL_SPECIALIZATION = """\
1530template <>
1531inline void SetParamVal<ParamType::T{enum}>({type} valueIn, ParamValue *valueOut)
1532{{
1533    valueOut->{union_name} = valueIn;
1534}}"""
1535
1536TEMPLATE_INIT_PARAM_VALUE_CASE = """\
1537        case ParamType::T{enum}:
1538            SetParamVal<ParamType::T{enum}>(valueIn, valueOut);
1539            break;"""
1540
1541TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE = """\
1542        case ParamType::T{enum_in}:
1543            WriteParamValueReplay<ParamType::T{enum_out}>(os, call, param.value.{union_name});
1544            break;"""
1545
1546TEMPLATE_PARAM_TYPE_TO_STRING_CASE = """\
1547        case ParamType::T{enum}:
1548            return "{type}";"""
1549
1550TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE = """\
1551        case ParamType::T{enum}:
1552            return ResourceIDType::{resource_id_type};"""
1553
1554TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE = """\
1555        case ResourceIDType::{resource_id_type}:
1556            return "{resource_id_type}";"""
1557
1558CL_PACKED_TYPES = {
1559    # Enums
1560    "cl_platform_info": "PlatformInfo",
1561    "cl_device_info": "DeviceInfo",
1562    "cl_context_info": "ContextInfo",
1563    "cl_command_queue_info": "CommandQueueInfo",
1564    "cl_mem_object_type": "MemObjectType",
1565    "cl_mem_info": "MemInfo",
1566    "cl_image_info": "ImageInfo",
1567    "cl_pipe_info": "PipeInfo",
1568    "cl_addressing_mode": "AddressingMode",
1569    "cl_filter_mode": "FilterMode",
1570    "cl_sampler_info": "SamplerInfo",
1571    "cl_program_info": "ProgramInfo",
1572    "cl_program_build_info": "ProgramBuildInfo",
1573    "cl_kernel_info": "KernelInfo",
1574    "cl_kernel_arg_info": "KernelArgInfo",
1575    "cl_kernel_work_group_info": "KernelWorkGroupInfo",
1576    "cl_kernel_sub_group_info": "KernelSubGroupInfo",
1577    "cl_kernel_exec_info": "KernelExecInfo",
1578    "cl_event_info": "EventInfo",
1579    "cl_profiling_info": "ProfilingInfo",
1580    # Bit fields
1581    "cl_device_type": "DeviceType",
1582    "cl_device_fp_config": "DeviceFpConfig",
1583    "cl_device_exec_capabilities": "DeviceExecCapabilities",
1584    "cl_device_svm_capabilities": "DeviceSvmCapabilities",
1585    "cl_command_queue_properties": "CommandQueueProperties",
1586    "cl_device_affinity_domain": "DeviceAffinityDomain",
1587    "cl_mem_flags": "MemFlags",
1588    "cl_svm_mem_flags": "SVM_MemFlags",
1589    "cl_mem_migration_flags": "MemMigrationFlags",
1590    "cl_map_flags": "MapFlags",
1591    "cl_kernel_arg_type_qualifier": "KernelArgTypeQualifier",
1592    "cl_device_atomic_capabilities": "DeviceAtomicCapabilities",
1593    "cl_device_device_enqueue_capabilities": "DeviceEnqueueCapabilities",
1594}
1595
1596EGL_PACKED_TYPES = {
1597    "EGLContext": "gl::ContextID",
1598    "EGLConfig": "egl::Config *",
1599    "EGLDeviceEXT": "egl::Device *",
1600    "EGLDisplay": "egl::Display *",
1601    "EGLImage": "ImageID",
1602    "EGLImageKHR": "ImageID",
1603    "EGLStreamKHR": "egl::Stream *",
1604    "EGLSurface": "SurfaceID",
1605    "EGLSync": "egl::SyncID",
1606    "EGLSyncKHR": "egl::SyncID",
1607}
1608
1609CAPTURE_BLOCKLIST = ['eglGetProcAddress']
1610
1611
1612def is_aliasing_excepted(api, cmd_name):
1613    # For simplicity, strip the prefix gl and lower the case of the first
1614    # letter.  This makes sure that all variants of the cmd_name that reach
1615    # here end up looking similar for the sake of looking up in ALIASING_EXCEPTIONS
1616    cmd_name = cmd_name[2:] if cmd_name.startswith('gl') else cmd_name
1617    cmd_name = cmd_name[0].lower() + cmd_name[1:]
1618    return api == apis.GLES and cmd_name in ALIASING_EXCEPTIONS
1619
1620
1621def is_allowed_with_active_pixel_local_storage(name):
1622    return name in PLS_ALLOW_LIST or any(
1623        [fnmatch.fnmatchcase(name, entry) for entry in PLS_ALLOW_WILDCARDS])
1624
1625
1626def is_context_private_state_command(api, name):
1627    name = strip_suffix(api, name)
1628    return name in CONTEXT_PRIVATE_LIST or any(
1629        [fnmatch.fnmatchcase(name, entry) for entry in CONTEXT_PRIVATE_WILDCARDS])
1630
1631
1632def is_lockless_egl_entry_point(cmd_name):
1633    if cmd_name in [
1634            "eglGetError", "eglGetCurrentContext", "eglGetCurrentSurface", "eglGetCurrentDisplay"
1635    ]:
1636        return True
1637    return False
1638
1639
1640def get_validation_expression(api, cmd_name, entry_point_name, internal_params, is_gles1):
1641    name = strip_api_prefix(cmd_name)
1642    private_params = ["context->getPrivateState()", "context->getMutableErrorSetForValidation()"]
1643    extra_params = private_params if is_context_private_state_command(api,
1644                                                                      cmd_name) else ["context"]
1645    expr = "Validate{name}({params})".format(
1646        name=name, params=", ".join(extra_params + [entry_point_name] + internal_params))
1647    if not is_gles1 and not is_allowed_with_active_pixel_local_storage(name):
1648        expr = "(ValidatePixelLocalStorageInactive({extra_params}, {entry_point_name}) && {expr})".format(
1649            extra_params=", ".join(private_params), entry_point_name=entry_point_name, expr=expr)
1650    return expr
1651
1652
1653def entry_point_export(api):
1654    if api == apis.CL:
1655        return ""
1656    return "ANGLE_EXPORT "
1657
1658
1659def entry_point_prefix(api):
1660    if api == apis.CL:
1661        return "cl"
1662    if api == apis.GLES:
1663        return "GL_"
1664    return api + "_"
1665
1666
1667def get_api_entry_def(api):
1668    if api == apis.EGL:
1669        return "EGLAPIENTRY"
1670    elif api == apis.CL:
1671        return "CL_API_CALL"
1672    else:
1673        return "GL_APIENTRY"
1674
1675
1676def get_stubs_header_template(api):
1677    if api == apis.CL:
1678        return TEMPLATE_CL_STUBS_HEADER
1679    elif api == apis.EGL:
1680        return TEMPLATE_EGL_STUBS_HEADER
1681    else:
1682        return ""
1683
1684
1685def format_entry_point_decl(api, cmd_name, proto, params):
1686    comma_if_needed = ", " if len(params) > 0 else ""
1687    stripped = strip_api_prefix(cmd_name)
1688    return TEMPLATE_ENTRY_POINT_DECL.format(
1689        angle_export=entry_point_export(api),
1690        export_def=get_api_entry_def(api),
1691        name="%s%s" % (entry_point_prefix(api), stripped),
1692        return_type=proto[:-len(cmd_name)].strip(),
1693        params=", ".join(params),
1694        comma_if_needed=comma_if_needed)
1695
1696
1697# Returns index range of identifier in function parameter
1698def find_name_range(param):
1699
1700    def is_allowed_in_identifier(char):
1701        return char.isalpha() or char.isdigit() or char == "_"
1702
1703    # If type is a function declaration, only search in first parentheses
1704    left_paren = param.find("(")
1705    if left_paren >= 0:
1706        min = left_paren + 1
1707        end = param.index(")")
1708    else:
1709        min = 0
1710        end = len(param)
1711
1712    # Find last identifier in search range
1713    while end > min and not is_allowed_in_identifier(param[end - 1]):
1714        end -= 1
1715    if end == min:
1716        raise ValueError
1717    start = end - 1
1718    while start > min and is_allowed_in_identifier(param[start - 1]):
1719        start -= 1
1720    return start, end
1721
1722
1723def just_the_type(param):
1724    start, end = find_name_range(param)
1725    return param[:start].strip() + param[end:].strip()
1726
1727
1728def just_the_name(param):
1729    start, end = find_name_range(param)
1730    return param[start:end]
1731
1732
1733def make_param(param_type, param_name):
1734
1735    def insert_name(param_type, param_name, pos):
1736        return param_type[:pos] + " " + param_name + param_type[pos:]
1737
1738    # If type is a function declaration, insert identifier before first closing parentheses
1739    left_paren = param_type.find("(")
1740    if left_paren >= 0:
1741        right_paren = param_type.index(")")
1742        return insert_name(param_type, param_name, right_paren)
1743
1744    # If type is an array declaration, insert identifier before brackets
1745    brackets = param_type.find("[")
1746    if brackets >= 0:
1747        return insert_name(param_type, param_name, brackets)
1748
1749    # Otherwise just append identifier
1750    return param_type + " " + param_name
1751
1752
1753def just_the_type_packed(param, entry):
1754    name = just_the_name(param)
1755    if name in entry:
1756        return entry[name]
1757    else:
1758        return just_the_type(param)
1759
1760
1761def just_the_name_packed(param, reserved_set):
1762    name = just_the_name(param)
1763    if name in reserved_set:
1764        return name + 'Packed'
1765    else:
1766        return name
1767
1768
1769def is_unsigned_long_format(fmt):
1770    return fmt == UNSIGNED_LONG_LONG_FORMAT or fmt == HEX_LONG_LONG_FORMAT
1771
1772
1773def param_print_argument(api, command_node, param):
1774    name_only = just_the_name(param)
1775    type_only = just_the_type(param)
1776
1777    if "*" not in param and type_only not in FORMAT_DICT:
1778        print(" ".join(param))
1779        raise Exception("Missing '%s %s' from '%s' entry point" %
1780                        (type_only, name_only, registry_xml.get_cmd_name(command_node)))
1781
1782    if "*" in param or FORMAT_DICT[type_only] == POINTER_FORMAT:
1783        return "(uintptr_t)%s" % name_only
1784
1785    if is_unsigned_long_format(FORMAT_DICT[type_only]):
1786        return "static_cast<unsigned long long>(%s)" % name_only
1787
1788    if type_only == "GLboolean":
1789        return "GLbooleanToString(%s)" % name_only
1790
1791    if type_only == "GLbitfield":
1792        group_name = find_gl_enum_group_in_command(command_node, name_only)
1793        return "GLbitfieldToString(%s::%s, %s).c_str()" % (api_enums[api], group_name, name_only)
1794
1795    if type_only == "GLenum":
1796        group_name = find_gl_enum_group_in_command(command_node, name_only)
1797        return "GLenumToString(%s::%s, %s)" % (api_enums[api], group_name, name_only)
1798
1799    return name_only
1800
1801
1802def param_format_string(param):
1803    if "*" in param:
1804        return just_the_name(param) + " = 0x%016\" PRIxPTR \""
1805    else:
1806        type_only = just_the_type(param)
1807        if type_only not in FORMAT_DICT:
1808            raise Exception(type_only + " is not a known type in 'FORMAT_DICT'")
1809
1810        return just_the_name(param) + " = " + FORMAT_DICT[type_only]
1811
1812
1813def is_context_lost_acceptable_cmd(cmd_name):
1814    lost_context_acceptable_cmds = [
1815        "glGetError",
1816        "glGetSync",
1817        "glGetQueryObjecti",
1818        "glGetProgramiv",
1819        "glGetGraphicsResetStatus",
1820        "glGetShaderiv",
1821    ]
1822
1823    for context_lost_entry_pont in lost_context_acceptable_cmds:
1824        if cmd_name.startswith(context_lost_entry_pont):
1825            return True
1826    return False
1827
1828
1829def get_context_getter_function(cmd_name):
1830    if is_context_lost_acceptable_cmd(cmd_name):
1831        return "GetGlobalContext()"
1832
1833    return "GetValidGlobalContext()"
1834
1835
1836def get_valid_context_check(cmd_name):
1837    return "context"
1838
1839
1840def get_constext_lost_error_generator(cmd_name):
1841    # Don't generate context lost errors on commands that accept lost contexts
1842    if is_context_lost_acceptable_cmd(cmd_name):
1843        return ""
1844
1845    return "GenerateContextLostErrorOnCurrentGlobalContext();"
1846
1847
1848def strip_suffix_always(api, name):
1849    for suffix in registry_xml.strip_suffixes:
1850        if name.endswith(suffix):
1851            name = name[0:-len(suffix)]
1852    return name
1853
1854
1855def strip_suffix(api, name):
1856    # For commands where aliasing is excepted, keep the suffix
1857    if is_aliasing_excepted(api, name):
1858        return name
1859
1860    return strip_suffix_always(api, name)
1861
1862
1863def find_gl_enum_group_in_command(command_node, param_name):
1864    group_name = None
1865    for param_node in command_node.findall('./param'):
1866        if param_node.find('./name').text == param_name:
1867            group_name = param_node.attrib.get('group', None)
1868            break
1869
1870    if group_name is None or group_name in registry_xml.unsupported_enum_group_names:
1871        group_name = registry_xml.default_enum_group_name
1872
1873    return group_name
1874
1875
1876def get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types, params):
1877    # Always strip the suffix when querying packed enums.
1878    result = cmd_packed_gl_enums.get(strip_suffix_always(api, cmd_name), {})
1879    for param in params:
1880        param_type = just_the_type(param)
1881        if param_type in packed_param_types:
1882            result[just_the_name(param)] = packed_param_types[param_type]
1883    return result
1884
1885
1886def get_def_template(api, cmd_name, return_type, has_errcode_ret):
1887    if return_type == "void":
1888        if api == apis.EGL:
1889            return TEMPLATE_EGL_ENTRY_POINT_NO_RETURN
1890        elif api == apis.CL:
1891            return TEMPLATE_CL_ENTRY_POINT_NO_RETURN
1892        elif is_context_private_state_command(api, cmd_name):
1893            return TEMPLATE_GLES_CONTEXT_PRIVATE_ENTRY_POINT_NO_RETURN
1894        else:
1895            return TEMPLATE_GLES_ENTRY_POINT_NO_RETURN
1896    elif return_type == "cl_int":
1897        return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_ERROR
1898    else:
1899        if api == apis.EGL:
1900            if is_lockless_egl_entry_point(cmd_name):
1901                return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN_NO_LOCKS
1902            else:
1903                return TEMPLATE_EGL_ENTRY_POINT_WITH_RETURN
1904        elif api == apis.CL:
1905            if has_errcode_ret:
1906                return TEMPLATE_CL_ENTRY_POINT_WITH_ERRCODE_RET
1907            else:
1908                return TEMPLATE_CL_ENTRY_POINT_WITH_RETURN_POINTER
1909        elif is_context_private_state_command(api, cmd_name):
1910            return TEMPLATE_GLES_CONTEXT_PRIVATE_ENTRY_POINT_WITH_RETURN
1911        else:
1912            return TEMPLATE_GLES_ENTRY_POINT_WITH_RETURN
1913
1914
1915def format_entry_point_def(api, command_node, cmd_name, proto, params, cmd_packed_enums,
1916                           packed_param_types, ep_to_object, is_gles1):
1917    packed_enums = get_packed_enums(api, cmd_packed_enums, cmd_name, packed_param_types, params)
1918    internal_params = [just_the_name_packed(param, packed_enums) for param in params]
1919    if internal_params and internal_params[-1] == "errcode_ret":
1920        internal_params.pop()
1921        has_errcode_ret = True
1922    else:
1923        has_errcode_ret = False
1924
1925    internal_context_lock_params = [
1926        just_the_name_packed(param, packed_enums) for param in params if just_the_type_packed(
1927            param, packed_enums) in ["Thread *", "egl::Display *", "gl::ContextID"] or
1928        just_the_name_packed(param, packed_enums) in ["attribute"]
1929    ]
1930
1931    packed_gl_enum_conversions = []
1932
1933    # egl::AttributeMap objects do not convert the raw input parameters to a map until they are
1934    # validated because it is possible to have unterminated attribute lists if one of the
1935    # attributes is invalid.
1936    # When validation is disabled, force the conversion from attribute list to map using
1937    # initializeWithoutValidation.
1938    attrib_map_init = []
1939
1940    for param in params:
1941        name = just_the_name(param)
1942
1943        if name in packed_enums:
1944            internal_name = name + "Packed"
1945            internal_type = packed_enums[name]
1946            packed_gl_enum_conversions += [
1947                "\n        " + internal_type + " " + internal_name + " = PackParam<" +
1948                internal_type + ">(" + name + ");"
1949            ]
1950
1951            if 'AttributeMap' in internal_type:
1952                attrib_map_init.append(internal_name + ".initializeWithoutValidation();")
1953
1954    pass_params = [param_print_argument(api, command_node, param) for param in params]
1955    format_params = [param_format_string(param) for param in params]
1956    return_type = proto[:-len(cmd_name)].strip()
1957    initialization = "InitBackEnds(%s);\n" % INIT_DICT[cmd_name] if cmd_name in INIT_DICT else ""
1958    event_comment = TEMPLATE_EVENT_COMMENT if cmd_name in NO_EVENT_MARKER_EXCEPTIONS_LIST else ""
1959    name_no_suffix = strip_suffix(api, cmd_name[2:])
1960    name_lower_no_suffix = name_no_suffix[0:1].lower() + name_no_suffix[1:]
1961    entry_point_name = "angle::EntryPoint::GL" + strip_api_prefix(cmd_name)
1962
1963    format_params = {
1964        "name":
1965            strip_api_prefix(cmd_name),
1966        "name_no_suffix":
1967            name_no_suffix,
1968        "name_lower_no_suffix":
1969            name_lower_no_suffix,
1970        "return_type":
1971            return_type,
1972        "params":
1973            ", ".join(params),
1974        "internal_params":
1975            ", ".join(internal_params),
1976        "attrib_map_init":
1977            "\n".join(attrib_map_init),
1978        "context_private_internal_params":
1979            ", ".join(
1980                ["context->getMutablePrivateState()", "context->getMutablePrivateStateCache()"] +
1981                internal_params),
1982        "internal_context_lock_params":
1983            ", ".join(internal_context_lock_params),
1984        "initialization":
1985            initialization,
1986        "packed_gl_enum_conversions":
1987            "".join(packed_gl_enum_conversions),
1988        "pass_params":
1989            ", ".join(pass_params),
1990        "comma_if_needed":
1991            ", " if len(params) > 0 else "",
1992        "comma_if_needed_context_lock":
1993            ", " if len(internal_context_lock_params) > 0 else "",
1994        "gl_capture_params":
1995            ", ".join(["context"] + internal_params),
1996        "egl_capture_params":
1997            ", ".join(["thread"] + internal_params),
1998        "validation_expression":
1999            get_validation_expression(api, cmd_name, entry_point_name, internal_params, is_gles1),
2000        "format_params":
2001            ", ".join(format_params),
2002        "context_getter":
2003            get_context_getter_function(cmd_name),
2004        "valid_context_check":
2005            get_valid_context_check(cmd_name),
2006        "constext_lost_error_generator":
2007            get_constext_lost_error_generator(cmd_name),
2008        "event_comment":
2009            event_comment,
2010        "labeled_object":
2011            get_egl_entry_point_labeled_object(ep_to_object, cmd_name, params, packed_enums),
2012        "context_lock":
2013            get_context_lock(api, cmd_name),
2014        "preamble":
2015            get_preamble(api, cmd_name, params),
2016        "epilog":
2017            get_epilog(api, cmd_name),
2018    }
2019
2020    template = get_def_template(api, cmd_name, return_type, has_errcode_ret)
2021    return template.format(**format_params)
2022
2023
2024def get_capture_param_type_name(param_type):
2025    pointer_count = param_type.count("*")
2026    is_const = "const" in param_type.split()
2027
2028    param_type = param_type.replace("*", "")
2029    param_type = param_type.replace("&", "")
2030    param_type = param_type.replace("const", "")
2031    param_type = param_type.replace("struct", "")
2032    param_type = param_type.replace("egl::",
2033                                    "egl_" if pointer_count or param_type == 'egl::SyncID' else "")
2034    param_type = param_type.replace("gl::", "")
2035    param_type = param_type.strip()
2036
2037    if is_const and param_type != 'AttributeMap':
2038        param_type += "Const"
2039    for x in range(pointer_count):
2040        param_type += "Pointer"
2041
2042    return param_type
2043
2044
2045def format_capture_method(api, command, cmd_name, proto, params, all_param_types,
2046                          capture_pointer_funcs, cmd_packed_gl_enums, packed_param_types):
2047
2048    context_param_typed = 'egl::Thread *thread' if api == apis.EGL else 'const State &glState'
2049    context_param_name = 'thread' if api == apis.EGL else 'glState'
2050
2051    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
2052                                       params)
2053
2054    params_with_type = get_internal_params(api, cmd_name,
2055                                           [context_param_typed, "bool isCallValid"] + params,
2056                                           cmd_packed_gl_enums, packed_param_types)
2057    params_just_name = ", ".join(
2058        [context_param_name, "isCallValid"] +
2059        [just_the_name_packed(param, packed_gl_enums) for param in params])
2060
2061    parameter_captures = []
2062    for param in params:
2063
2064        param_name = just_the_name_packed(param, packed_gl_enums)
2065        param_type = just_the_type_packed(param, packed_gl_enums).strip()
2066
2067        if 'AttributeMap' in param_type:
2068            capture = 'paramBuffer.addParam(CaptureAttributeMap(%s));' % param_name
2069            parameter_captures += [capture]
2070            continue
2071
2072        pointer_count = param_type.count("*")
2073        capture_param_type = get_capture_param_type_name(param_type)
2074
2075        # With EGL capture, we don't currently support capturing specific pointer params.
2076        if pointer_count > 0 and api != apis.EGL:
2077            params = params_just_name
2078            capture_name = "Capture%s_%s" % (strip_api_prefix(cmd_name), param_name)
2079            capture = TEMPLATE_PARAMETER_CAPTURE_POINTER.format(
2080                name=param_name,
2081                type=capture_param_type,
2082                capture_name=capture_name,
2083                params=params,
2084                cast_type=param_type)
2085
2086            capture_pointer_func = TEMPLATE_PARAMETER_CAPTURE_POINTER_FUNC.format(
2087                name=capture_name, params=params_with_type + ", angle::ParamCapture *paramCapture")
2088            capture_pointer_funcs += [capture_pointer_func]
2089        elif capture_param_type in ('GLenum', 'GLbitfield'):
2090            gl_enum_group = find_gl_enum_group_in_command(command, param_name)
2091            capture = TEMPLATE_PARAMETER_CAPTURE_GL_ENUM.format(
2092                name=param_name,
2093                type=capture_param_type,
2094                api_enum=api_enums[api],
2095                group=gl_enum_group)
2096        else:
2097            capture = TEMPLATE_PARAMETER_CAPTURE_VALUE.format(
2098                name=param_name, type=capture_param_type)
2099
2100        # For specific methods we can't easily parse their types. Work around this by omitting
2101        # parameter captures, but keeping the capture method as a mostly empty stub.
2102        if cmd_name not in CAPTURE_BLOCKLIST:
2103            all_param_types.add(capture_param_type)
2104            parameter_captures += [capture]
2105
2106    return_type = proto[:-len(cmd_name)].strip()
2107    capture_return_type = get_capture_param_type_name(return_type)
2108    if capture_return_type != 'void':
2109        if cmd_name in CAPTURE_BLOCKLIST:
2110            params_with_type += ", %s returnValue" % capture_return_type
2111        else:
2112            all_param_types.add(capture_return_type)
2113
2114    format_args = {
2115        "api_upper": "EGL" if api == apis.EGL else "GL",
2116        "full_name": cmd_name,
2117        "short_name": strip_api_prefix(cmd_name),
2118        "params_with_type": params_with_type,
2119        "params_just_name": params_just_name,
2120        "parameter_captures": "\n    ".join(parameter_captures),
2121        "return_value_type_original": return_type,
2122        "return_value_type_custom": capture_return_type,
2123    }
2124
2125    if return_type == "void" or cmd_name in CAPTURE_BLOCKLIST:
2126        return TEMPLATE_CAPTURE_METHOD_NO_RETURN_VALUE.format(**format_args)
2127    else:
2128        return TEMPLATE_CAPTURE_METHOD_WITH_RETURN_VALUE.format(**format_args)
2129
2130
2131def const_pointer_type(param, packed_gl_enums):
2132    type = just_the_type_packed(param, packed_gl_enums)
2133    if just_the_name(param) == "errcode_ret" or type == "ErrorSet *" or "(" in type:
2134        return type
2135    elif "**" in type and "const" not in type:
2136        return type.replace("**", "* const *")
2137    elif "*" in type and "const" not in type:
2138        return type.replace("*", "*const ") if "[]" in type else "const " + type
2139    else:
2140        return type
2141
2142
2143def get_internal_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
2144    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
2145                                       params)
2146    return ", ".join([
2147        make_param(
2148            just_the_type_packed(param, packed_gl_enums),
2149            just_the_name_packed(param, packed_gl_enums)) for param in params
2150    ])
2151
2152
2153def get_validation_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
2154    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
2155                                       params)
2156    last = -1 if params and just_the_name(params[-1]) == "errcode_ret" else None
2157    return ", ".join([
2158        make_param(
2159            const_pointer_type(param, packed_gl_enums),
2160            just_the_name_packed(param, packed_gl_enums)) for param in params[:last]
2161    ])
2162
2163
2164def get_context_private_call_params(api, cmd_name, params, cmd_packed_gl_enums,
2165                                    packed_param_types):
2166    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
2167                                       params)
2168    return ", ".join([
2169        make_param(
2170            just_the_type_packed(param, packed_gl_enums),
2171            just_the_name_packed(param, packed_gl_enums)) for param in params
2172    ])
2173
2174
2175def get_context_lock_params(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
2176    packed_gl_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
2177                                       params)
2178    return ", ".join([
2179        make_param(
2180            just_the_type_packed(param, packed_gl_enums),
2181            just_the_name_packed(param, packed_gl_enums))
2182        for param in params
2183        if just_the_type_packed(
2184            param, packed_gl_enums) in ["Thread *", "egl::Display *", "gl::ContextID"] or
2185        just_the_name_packed(param, packed_gl_enums) in ["attribute"]
2186    ])
2187
2188
2189def format_context_decl(api, cmd_name, proto, params, template, cmd_packed_gl_enums,
2190                        packed_param_types):
2191    internal_params = get_internal_params(api, cmd_name, params, cmd_packed_gl_enums,
2192                                          packed_param_types)
2193
2194    return_type = proto[:-len(cmd_name)].strip()
2195    name_lower_no_suffix = cmd_name[2:3].lower() + cmd_name[3:]
2196    name_lower_no_suffix = strip_suffix(api, name_lower_no_suffix)
2197    maybe_const = " const" if name_lower_no_suffix.startswith(
2198        "is") and name_lower_no_suffix[2].isupper() else ""
2199
2200    return template.format(
2201        return_type=return_type,
2202        name_lower_no_suffix=name_lower_no_suffix,
2203        internal_params=internal_params,
2204        maybe_const=maybe_const)
2205
2206
2207def format_entry_point_export(cmd_name, proto, params, template):
2208    internal_params = [just_the_name(param) for param in params]
2209    return_type = proto[:-len(cmd_name)].strip()
2210
2211    return template.format(
2212        name=strip_api_prefix(cmd_name),
2213        return_type=return_type,
2214        params=", ".join(params),
2215        internal_params=", ".join(internal_params))
2216
2217
2218def format_validation_proto(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
2219    if api == apis.CL:
2220        return_type = "cl_int"
2221    else:
2222        return_type = "bool"
2223    if api in [apis.GL, apis.GLES]:
2224        with_extra_params = ["const PrivateState &state",
2225                             "ErrorSet *errors"] if is_context_private_state_command(
2226                                 api, cmd_name) else ["Context *context"]
2227        with_extra_params += ["angle::EntryPoint entryPoint"] + params
2228    elif api == apis.EGL:
2229        with_extra_params = ["ValidationContext *val"] + params
2230    else:
2231        with_extra_params = params
2232    internal_params = get_validation_params(api, cmd_name, with_extra_params, cmd_packed_gl_enums,
2233                                            packed_param_types)
2234    return TEMPLATE_VALIDATION_PROTO % (return_type, strip_api_prefix(cmd_name), internal_params)
2235
2236
2237def format_context_private_call_proto(api, cmd_name, proto, params, cmd_packed_gl_enums,
2238                                      packed_param_types):
2239    with_extra_params = ["PrivateState *privateState", "PrivateStateCache *privateStateCache"
2240                        ] + params
2241    packed_enums = get_packed_enums(api, cmd_packed_gl_enums, cmd_name, packed_param_types,
2242                                    with_extra_params)
2243    internal_params = get_context_private_call_params(api, cmd_name, with_extra_params,
2244                                                      cmd_packed_gl_enums, packed_param_types)
2245    stripped_name = strip_suffix(api, strip_api_prefix(cmd_name))
2246    return_type = proto[:-len(cmd_name)].strip()
2247    return TEMPLATE_CONTEXT_PRIVATE_CALL_PROTO % (return_type, stripped_name,
2248                                                  internal_params), stripped_name
2249
2250
2251def format_context_lock_proto(api, cmd_name, params, cmd_packed_gl_enums, packed_param_types):
2252    with_extra_params = ["Thread *thread"] + params
2253    internal_params = get_context_lock_params(api, cmd_name, with_extra_params,
2254                                              cmd_packed_gl_enums, packed_param_types)
2255    return TEMPLATE_CONTEXT_LOCK_PROTO % (strip_api_prefix(cmd_name), internal_params)
2256
2257
2258def format_capture_proto(api, cmd_name, proto, params, cmd_packed_gl_enums, packed_param_types):
2259    context_param_typed = 'egl::Thread *thread' if api == apis.EGL else 'const State &glState'
2260    internal_params = get_internal_params(api, cmd_name,
2261                                          [context_param_typed, "bool isCallValid"] + params,
2262                                          cmd_packed_gl_enums, packed_param_types)
2263    return_type = proto[:-len(cmd_name)].strip()
2264    if return_type != "void":
2265        internal_params += ", %s returnValue" % return_type
2266    return TEMPLATE_CAPTURE_PROTO % (strip_api_prefix(cmd_name), internal_params)
2267
2268
2269def path_to(folder, file):
2270    return os.path.join(script_relative(".."), "src", folder, file)
2271
2272
2273class ANGLEEntryPoints(registry_xml.EntryPoints):
2274
2275    def __init__(self,
2276                 api,
2277                 xml,
2278                 commands,
2279                 all_param_types,
2280                 cmd_packed_enums,
2281                 export_template=TEMPLATE_GL_ENTRY_POINT_EXPORT,
2282                 packed_param_types=[],
2283                 ep_to_object={},
2284                 is_gles1=False):
2285        super().__init__(api, xml, commands)
2286
2287        self.decls = []
2288        self.defs = []
2289        self.export_defs = []
2290        self.validation_protos = []
2291        self.context_private_call_protos = []
2292        self.context_private_call_functions = []
2293        self.context_lock_protos = []
2294        self.capture_protos = []
2295        self.capture_methods = []
2296        self.capture_pointer_funcs = []
2297
2298        for (cmd_name, command_node, param_text, proto_text) in self.get_infos():
2299            self.decls.append(format_entry_point_decl(self.api, cmd_name, proto_text, param_text))
2300            self.defs.append(
2301                format_entry_point_def(self.api, command_node, cmd_name, proto_text, param_text,
2302                                       cmd_packed_enums, packed_param_types, ep_to_object,
2303                                       is_gles1))
2304
2305            self.export_defs.append(
2306                format_entry_point_export(cmd_name, proto_text, param_text, export_template))
2307
2308            self.validation_protos.append(
2309                format_validation_proto(self.api, cmd_name, param_text, cmd_packed_enums,
2310                                        packed_param_types))
2311
2312            if is_context_private_state_command(self.api, cmd_name):
2313                proto, function = format_context_private_call_proto(self.api, cmd_name, proto_text,
2314                                                                    param_text, cmd_packed_enums,
2315                                                                    packed_param_types)
2316                self.context_private_call_protos.append(proto)
2317                self.context_private_call_functions.append(function)
2318
2319            if api == apis.EGL:
2320                self.context_lock_protos.append(
2321                    format_context_lock_proto(api, cmd_name, param_text, cmd_packed_enums,
2322                                              packed_param_types))
2323
2324            self.capture_protos.append(
2325                format_capture_proto(self.api, cmd_name, proto_text, param_text, cmd_packed_enums,
2326                                     packed_param_types))
2327            self.capture_methods.append(
2328                format_capture_method(self.api, command_node, cmd_name, proto_text, param_text,
2329                                      all_param_types, self.capture_pointer_funcs,
2330                                      cmd_packed_enums, packed_param_types))
2331
2332        # Ensure we store GLint64 in the param types for use with the replay interpreter.
2333        all_param_types.add('GLint64')
2334
2335
2336class GLEntryPoints(ANGLEEntryPoints):
2337
2338    all_param_types = set()
2339
2340    def __init__(self, api, xml, commands, is_gles1=False):
2341        super().__init__(
2342            api,
2343            xml,
2344            commands,
2345            GLEntryPoints.all_param_types,
2346            GLEntryPoints.get_packed_enums(),
2347            is_gles1=is_gles1)
2348
2349    _packed_enums = None
2350
2351    @classmethod
2352    def get_packed_enums(cls):
2353        if not cls._packed_enums:
2354            with open(script_relative('entry_point_packed_gl_enums.json')) as f:
2355                cls._packed_enums = json.loads(f.read())
2356        return cls._packed_enums
2357
2358
2359class EGLEntryPoints(ANGLEEntryPoints):
2360
2361    all_param_types = set()
2362
2363    def __init__(self, xml, commands):
2364        super().__init__(
2365            apis.EGL,
2366            xml,
2367            commands,
2368            EGLEntryPoints.all_param_types,
2369            EGLEntryPoints.get_packed_enums(),
2370            export_template=TEMPLATE_EGL_ENTRY_POINT_EXPORT,
2371            packed_param_types=EGL_PACKED_TYPES,
2372            ep_to_object=EGLEntryPoints._get_ep_to_object())
2373
2374    _ep_to_object = None
2375
2376    @classmethod
2377    def _get_ep_to_object(cls):
2378
2379        if cls._ep_to_object:
2380            return cls._ep_to_object
2381
2382        with open(EGL_GET_LABELED_OBJECT_DATA_PATH) as f:
2383            try:
2384                spec_json = json.loads(f.read())
2385            except ValueError:
2386                raise Exception("Could not decode JSON from %s" % EGL_GET_LABELED_OBJECT_DATA_PATH)
2387
2388        # Construct a mapping from EP to type. Fill in the gaps with Display/None.
2389        cls._ep_to_object = {}
2390
2391        for category, eps in spec_json.items():
2392            if category == 'description':
2393                continue
2394            for ep in eps:
2395                cls._ep_to_object[ep] = category
2396
2397        return cls._ep_to_object
2398
2399    _packed_enums = None
2400
2401    @classmethod
2402    def get_packed_enums(cls):
2403        if not cls._packed_enums:
2404            with open(script_relative('entry_point_packed_egl_enums.json')) as f:
2405                cls._packed_enums = json.loads(f.read())
2406        return cls._packed_enums
2407
2408
2409class GLXEntryPoints(ANGLEEntryPoints):
2410
2411    all_param_types = set()
2412
2413    def __init__(self, xml, commands):
2414        super().__init__(
2415            apis.GLX,
2416            xml,
2417            commands,
2418            GLXEntryPoints.all_param_types,
2419            GLXEntryPoints.get_packed_enums(),
2420            export_template=TEMPLATE_GLX_ENTRY_POINT_EXPORT,
2421            packed_param_types=GLX_PACKED_TYPES)
2422
2423
2424class CLEntryPoints(ANGLEEntryPoints):
2425
2426    all_param_types = set()
2427
2428    def __init__(self, xml, commands):
2429        super().__init__(
2430            apis.CL,
2431            xml,
2432            commands,
2433            CLEntryPoints.all_param_types,
2434            CLEntryPoints.get_packed_enums(),
2435            export_template=TEMPLATE_CL_ENTRY_POINT_EXPORT,
2436            packed_param_types=CL_PACKED_TYPES)
2437
2438    @classmethod
2439    def get_packed_enums(cls):
2440        return {}
2441
2442
2443def get_decls(api,
2444              formatter,
2445              all_commands,
2446              gles_commands,
2447              already_included,
2448              cmd_packed_gl_enums,
2449              packed_param_types=[]):
2450    decls = []
2451    for command in all_commands:
2452        proto = command.find('proto')
2453        cmd_name = proto.find('name').text
2454
2455        if cmd_name not in gles_commands:
2456            continue
2457
2458        name_no_suffix = strip_suffix(api, cmd_name)
2459        if name_no_suffix in already_included:
2460            continue
2461
2462        # Don't generate Context::entryPoint declarations for entry points that
2463        # directly access the context-private state.
2464        if is_context_private_state_command(api, cmd_name):
2465            continue
2466
2467        param_text = ["".join(param.itertext()) for param in command.findall('param')]
2468        proto_text = "".join(proto.itertext())
2469        decls.append(
2470            format_context_decl(api, cmd_name, proto_text, param_text, formatter,
2471                                cmd_packed_gl_enums, packed_param_types))
2472
2473    return decls
2474
2475
2476def get_glext_decls(all_commands, gles_commands, version):
2477    glext_ptrs = []
2478    glext_protos = []
2479    is_gles1 = False
2480
2481    if (version == ""):
2482        is_gles1 = True
2483
2484    for command in all_commands:
2485        proto = command.find('proto')
2486        cmd_name = proto.find('name').text
2487
2488        if cmd_name not in gles_commands:
2489            continue
2490
2491        param_text = ["".join(param.itertext()) for param in command.findall('param')]
2492        proto_text = "".join(proto.itertext())
2493
2494        return_type = proto_text[:-len(cmd_name)]
2495        params = ", ".join(param_text)
2496
2497        format_params = {
2498            "apicall": "GL_API" if is_gles1 else "GL_APICALL",
2499            "name": cmd_name,
2500            "name_upper": cmd_name.upper(),
2501            "return_type": return_type,
2502            "params": params,
2503        }
2504
2505        glext_ptrs.append(TEMPLATE_GLEXT_FUNCTION_POINTER.format(**format_params))
2506        glext_protos.append(TEMPLATE_GLEXT_FUNCTION_PROTOTYPE.format(**format_params))
2507
2508    return glext_ptrs, glext_protos
2509
2510
2511def write_file(annotation, comment, template, entry_points, suffix, includes, lib, file):
2512
2513    content = template.format(
2514        script_name=os.path.basename(sys.argv[0]),
2515        data_source_name=file,
2516        annotation_lower=annotation.lower(),
2517        annotation_upper=annotation.upper(),
2518        comment=comment,
2519        lib=lib.upper(),
2520        includes=includes,
2521        entry_points=entry_points)
2522
2523    path = path_to(lib, "entry_points_{}_autogen.{}".format(annotation.lower(), suffix))
2524
2525    with open(path, "w") as out:
2526        out.write(content)
2527        out.close()
2528
2529
2530def write_export_files(entry_points, includes, source, lib_name, lib_description, lib_dir=None):
2531    content = TEMPLATE_LIB_ENTRY_POINT_SOURCE.format(
2532        script_name=os.path.basename(sys.argv[0]),
2533        data_source_name=source,
2534        lib_name=lib_name,
2535        lib_description=lib_description,
2536        includes=includes,
2537        entry_points=entry_points,
2538    )
2539
2540    path = path_to(lib_name if not lib_dir else lib_dir, "{}_autogen.cpp".format(lib_name))
2541
2542    with open(path, "w") as out:
2543        out.write(content)
2544        out.close()
2545
2546
2547def write_context_api_decls(decls, api):
2548    for (major, minor), version_decls in sorted(decls['core'].items()):
2549        if minor == "X":
2550            annotation = '{}_{}'.format(api, major)
2551            version = str(major)
2552        else:
2553            annotation = '{}_{}_{}'.format(api, major, minor)
2554            version = '{}_{}'.format(major, minor)
2555        content = CONTEXT_HEADER.format(
2556            annotation_lower=annotation.lower(),
2557            annotation_upper=annotation.upper(),
2558            script_name=os.path.basename(sys.argv[0]),
2559            data_source_name="gl.xml",
2560            version=version,
2561            interface="\n".join(version_decls))
2562
2563        path = path_to("libANGLE", "Context_%s_autogen.h" % annotation.lower())
2564
2565        with open(path, "w") as out:
2566            out.write(content)
2567            out.close()
2568
2569    if 'exts' in decls.keys():
2570        interface_lines = []
2571        for annotation in decls['exts'].keys():
2572            interface_lines.append("\\\n    /* " + annotation + " */ \\\n\\")
2573
2574            for extname in sorted(decls['exts'][annotation].keys()):
2575                interface_lines.append("    /* " + extname + " */ \\")
2576                interface_lines.extend(decls['exts'][annotation][extname])
2577
2578        content = CONTEXT_HEADER.format(
2579            annotation_lower='gles_ext',
2580            annotation_upper='GLES_EXT',
2581            script_name=os.path.basename(sys.argv[0]),
2582            data_source_name="gl.xml",
2583            version='EXT',
2584            interface="\n".join(interface_lines))
2585
2586        path = path_to("libANGLE", "Context_gles_ext_autogen.h")
2587
2588        with open(path, "w") as out:
2589            out.write(content)
2590            out.close()
2591
2592
2593def write_validation_header(annotation, comment, protos, source, template):
2594    content = template.format(
2595        script_name=os.path.basename(sys.argv[0]),
2596        data_source_name=source,
2597        annotation=annotation,
2598        comment=comment,
2599        prototypes="\n".join(protos))
2600
2601    path = path_to("libANGLE", "validation%s_autogen.h" % annotation)
2602
2603    with open(path, "w") as out:
2604        out.write(content)
2605        out.close()
2606
2607
2608def write_context_private_call_header(annotation, protos, source, template):
2609    content = TEMPLATE_CONTEXT_PRIVATE_CALL_HEADER.format(
2610        script_name=os.path.basename(sys.argv[0]),
2611        data_source_name=source,
2612        annotation=annotation,
2613        prototypes="\n".join(protos))
2614
2615    path = path_to("libANGLE", "context_private_call_%s_autogen.h" % annotation)
2616
2617    with open(path, "w") as out:
2618        out.write(content)
2619        out.close()
2620
2621
2622def write_context_lock_header(annotation, comment, protos, source, template):
2623    content = template.format(
2624        script_name=os.path.basename(sys.argv[0]),
2625        data_source_name=source,
2626        annotation_lower=annotation.lower(),
2627        annotation_upper=annotation.upper(),
2628        comment=comment,
2629        prototypes="\n".join(protos))
2630
2631    path = path_to("libGLESv2", "%s_context_lock_autogen.h" % annotation.lower())
2632
2633    with open(path, "w") as out:
2634        out.write(content)
2635        out.close()
2636
2637
2638def write_gl_validation_header(annotation, comment, protos, source):
2639    return write_validation_header(annotation, comment, protos, source,
2640                                   TEMPLATE_GL_VALIDATION_HEADER)
2641
2642
2643def write_capture_header(api, annotation, comment, protos, capture_pointer_funcs):
2644    ns = 'egl' if api == apis.EGL else 'gl'
2645    combined_protos = ["\n// Method Captures\n"] + protos
2646    if capture_pointer_funcs:
2647        combined_protos += ["\n// Parameter Captures\n"] + capture_pointer_funcs
2648    content = TEMPLATE_CAPTURE_HEADER.format(
2649        script_name=os.path.basename(sys.argv[0]),
2650        data_source_name="%s.xml and %s_angle_ext.xml" % (ns, ns),
2651        annotation_lower=annotation.lower(),
2652        annotation_upper=annotation.upper(),
2653        comment=comment,
2654        namespace=ns,
2655        prototypes="\n".join(combined_protos))
2656
2657    path = path_to(os.path.join("libANGLE", "capture"), "capture_%s_autogen.h" % annotation)
2658
2659    with open(path, "w") as out:
2660        out.write(content)
2661        out.close()
2662
2663
2664def write_capture_source(api, annotation_with_dash, annotation_no_dash, comment, capture_methods):
2665    ns = 'egl' if api == apis.EGL else 'gl'
2666    content = TEMPLATE_CAPTURE_SOURCE.format(
2667        script_name=os.path.basename(sys.argv[0]),
2668        data_source_name="%s.xml and %s_angle_ext.xml" % (ns, ns),
2669        annotation_with_dash=annotation_with_dash,
2670        annotation_no_dash=annotation_no_dash,
2671        comment=comment,
2672        namespace=ns,
2673        capture_methods="\n".join(capture_methods))
2674
2675    path = path_to(
2676        os.path.join("libANGLE", "capture"), "capture_%s_autogen.cpp" % annotation_with_dash)
2677
2678    with open(path, "w") as out:
2679        out.write(content)
2680        out.close()
2681
2682
2683def is_packed_enum_param_type(param_type):
2684    return not param_type.startswith("GL") and not param_type.startswith(
2685        "EGL") and "void" not in param_type
2686
2687
2688def add_namespace(param_type):
2689    param_type = param_type.strip()
2690
2691    if param_type == 'AHardwareBufferConstPointer' or param_type == 'charConstPointer':
2692        return param_type
2693
2694    # ANGLE namespaced EGL types
2695    egl_namespace = [
2696        'CompositorTiming',
2697        'ObjectType',
2698        'Timestamp',
2699    ] + list(EGL_PACKED_TYPES.values())
2700
2701    if param_type[0:2] == "GL" or param_type[0:3] == "EGL" or "void" in param_type:
2702        return param_type
2703
2704    if param_type.startswith('gl_'):
2705        return param_type.replace('gl_', 'gl::')
2706    elif param_type.startswith('egl_'):
2707        return param_type.replace('egl_', 'egl::')
2708    elif param_type.startswith('wl_'):
2709        return param_type
2710    elif param_type in egl_namespace:
2711        return "egl::" + param_type
2712    else:
2713        return "gl::" + param_type
2714
2715
2716def get_gl_pointer_type(param_type):
2717
2718    if "ConstPointerPointer" in param_type:
2719        return "const " + param_type.replace("ConstPointerPointer", "") + " * const *"
2720
2721    if "ConstPointer" in param_type:
2722        return "const " + param_type.replace("ConstPointer", "") + " *"
2723
2724    if "PointerPointer" in param_type:
2725        return param_type.replace("PointerPointer", "") + " **"
2726
2727    if "Pointer" in param_type:
2728        return param_type.replace("Pointer", "") + " *"
2729
2730    return param_type
2731
2732
2733def get_param_type_type(param_type):
2734    param_type = add_namespace(param_type)
2735    return get_gl_pointer_type(param_type)
2736
2737
2738def is_id_type(t):
2739    return t.endswith('ID') and not t.endswith('ANDROID')
2740
2741
2742def is_id_pointer_type(t):
2743    return t.endswith("IDConstPointer") or t.endswith("IDPointer") and not 'ANDROID' in t
2744
2745
2746def get_gl_param_type_type(param_type):
2747    if is_packed_enum_param_type(param_type):
2748        base_type = param_type.replace("Pointer", "").replace("Const", "")
2749        if is_id_type(base_type):
2750            replace_type = "GLuint"
2751        else:
2752            replace_type = "GLenum"
2753        param_type = param_type.replace(base_type, replace_type)
2754    return get_gl_pointer_type(param_type)
2755
2756
2757def get_param_type_union_name(param_type):
2758    return param_type + "Val"
2759
2760
2761def format_param_type_union_type(param_type):
2762    return "%s %s;" % (get_param_type_type(param_type), get_param_type_union_name(param_type))
2763
2764
2765def format_get_param_val_specialization(param_type):
2766    return TEMPLATE_GET_PARAM_VAL_SPECIALIZATION.format(
2767        enum=param_type,
2768        type=get_param_type_type(param_type),
2769        union_name=get_param_type_union_name(param_type))
2770
2771
2772def format_access_param_value_case(param_type):
2773    return TEMPLATE_ACCESS_PARAM_VALUE_CASE.format(enum=param_type)
2774
2775
2776def format_set_param_val_specialization(param_type):
2777    return TEMPLATE_SET_PARAM_VAL_SPECIALIZATION.format(
2778        enum=param_type,
2779        type=get_param_type_type(param_type),
2780        union_name=get_param_type_union_name(param_type))
2781
2782
2783def format_init_param_value_case(param_type):
2784    return TEMPLATE_INIT_PARAM_VALUE_CASE.format(enum=param_type)
2785
2786
2787def format_write_param_type_to_stream_case(param_type):
2788    return TEMPLATE_WRITE_PARAM_TYPE_TO_STREAM_CASE.format(
2789        enum_in=param_type, enum_out=param_type, union_name=get_param_type_union_name(param_type))
2790
2791
2792def get_resource_id_types(all_param_types):
2793    return [t[:-2] for t in filter(lambda t: is_id_type(t), all_param_types)]
2794
2795
2796def format_resource_id_types(all_param_types):
2797    resource_id_types = get_resource_id_types(all_param_types)
2798    resource_id_types += ["EnumCount", "InvalidEnum = EnumCount"]
2799    resource_id_types = ",\n    ".join(resource_id_types)
2800    return resource_id_types
2801
2802
2803def format_resource_id_convert_structs(all_param_types):
2804    templ = """\
2805template <>
2806struct GetResourceIDTypeFromType<%s>
2807{
2808    static constexpr ResourceIDType IDType = ResourceIDType::%s;
2809};
2810"""
2811    resource_id_types = get_resource_id_types(all_param_types)
2812    convert_struct_strings = [templ % (add_namespace('%sID' % id), id) for id in resource_id_types]
2813    return "\n".join(convert_struct_strings)
2814
2815
2816def write_capture_helper_header(all_param_types):
2817
2818    param_types = "\n    ".join(["T%s," % t for t in all_param_types])
2819    param_union_values = "\n    ".join([format_param_type_union_type(t) for t in all_param_types])
2820    get_param_val_specializations = "\n\n".join(
2821        [format_get_param_val_specialization(t) for t in all_param_types])
2822    access_param_value_cases = "\n".join(
2823        [format_access_param_value_case(t) for t in all_param_types])
2824    set_param_val_specializations = "\n\n".join(
2825        [format_set_param_val_specialization(t) for t in all_param_types])
2826    init_param_value_cases = "\n".join([format_init_param_value_case(t) for t in all_param_types])
2827    resource_id_types = format_resource_id_types(all_param_types)
2828    convert_structs = format_resource_id_convert_structs(all_param_types)
2829
2830    content = TEMPLATE_FRAME_CAPTURE_UTILS_HEADER.format(
2831        script_name=os.path.basename(sys.argv[0]),
2832        data_source_name="gl.xml and gl_angle_ext.xml",
2833        param_types=param_types,
2834        param_type_count=len(all_param_types),
2835        param_union_values=param_union_values,
2836        get_param_val_specializations=get_param_val_specializations,
2837        access_param_value_cases=access_param_value_cases,
2838        set_param_val_specializations=set_param_val_specializations,
2839        init_param_value_cases=init_param_value_cases,
2840        resource_id_types=resource_id_types,
2841        type_to_resource_id_type_structs=convert_structs)
2842
2843    path = path_to("common", "frame_capture_utils_autogen.h")
2844
2845    with open(path, "w") as out:
2846        out.write(content)
2847        out.close()
2848
2849
2850def format_param_type_to_string_case(param_type):
2851    return TEMPLATE_PARAM_TYPE_TO_STRING_CASE.format(
2852        enum=param_type, type=get_gl_param_type_type(param_type))
2853
2854
2855def get_resource_id_type_from_param_type(param_type):
2856    if param_type.endswith("ConstPointer"):
2857        return param_type.replace("ConstPointer", "")[:-2]
2858    if param_type.endswith("Pointer"):
2859        return param_type.replace("Pointer", "")[:-2]
2860    return param_type[:-2]
2861
2862
2863def format_param_type_to_resource_id_type_case(param_type):
2864    return TEMPLATE_PARAM_TYPE_TO_RESOURCE_ID_TYPE_CASE.format(
2865        enum=param_type, resource_id_type=get_resource_id_type_from_param_type(param_type))
2866
2867
2868def format_param_type_resource_id_cases(all_param_types):
2869    id_types = filter(lambda t: is_id_type(t) or is_id_pointer_type(t), all_param_types)
2870    return "\n".join([format_param_type_to_resource_id_type_case(t) for t in id_types])
2871
2872
2873def format_resource_id_type_name_case(resource_id_type):
2874    return TEMPLATE_RESOURCE_ID_TYPE_NAME_CASE.format(resource_id_type=resource_id_type)
2875
2876
2877def write_capture_helper_source(all_param_types):
2878
2879    write_param_type_to_stream_cases = "\n".join(
2880        [format_write_param_type_to_stream_case(t) for t in all_param_types])
2881    param_type_to_string_cases = "\n".join(
2882        [format_param_type_to_string_case(t) for t in all_param_types])
2883
2884    param_type_resource_id_cases = format_param_type_resource_id_cases(all_param_types)
2885
2886    resource_id_types = get_resource_id_types(all_param_types)
2887    resource_id_type_name_cases = "\n".join(
2888        [format_resource_id_type_name_case(t) for t in resource_id_types])
2889
2890    content = TEMPLATE_FRAME_CAPTURE_UTILS_SOURCE.format(
2891        script_name=os.path.basename(sys.argv[0]),
2892        data_source_name="gl.xml and gl_angle_ext.xml",
2893        write_param_type_to_stream_cases=write_param_type_to_stream_cases,
2894        param_type_to_string_cases=param_type_to_string_cases,
2895        param_type_resource_id_cases=param_type_resource_id_cases,
2896        resource_id_type_name_cases=resource_id_type_name_cases)
2897
2898    path = path_to("common", "frame_capture_utils_autogen.cpp")
2899
2900    with open(path, "w") as out:
2901        out.write(content)
2902        out.close()
2903
2904
2905def get_command_params_text(command_node, cmd_name):
2906    param_text_list = list()
2907    for param_node in command_node.findall('param'):
2908        param_text_list.append("".join(param_node.itertext()))
2909    return param_text_list
2910
2911
2912def is_get_pointer_command(command_name):
2913    return command_name.endswith('Pointerv') and command_name.startswith('glGet')
2914
2915
2916def remove_id_suffix(t):
2917    return t[:-2] if is_id_type(t) else t
2918
2919
2920def format_replay_params(api, command_name, param_text_list, packed_enums, resource_id_types):
2921    param_access_strs = list()
2922    for i, param_text in enumerate(param_text_list):
2923        param_type = just_the_type(param_text)
2924        if param_type in EGL_PACKED_TYPES:
2925            param_type = 'void *'
2926        param_name = just_the_name(param_text)
2927        capture_type = get_capture_param_type_name(param_type)
2928        union_name = get_param_type_union_name(capture_type)
2929        param_access = 'captures[%d].value.%s' % (i, union_name)
2930        # Workaround for https://github.com/KhronosGroup/OpenGL-Registry/issues/545
2931        if command_name == 'glCreateShaderProgramvEXT' and i == 2:
2932            param_access = 'const_cast<const char **>(%s)' % param_access
2933        else:
2934            cmd_no_suffix = strip_suffix(api, command_name)
2935            if cmd_no_suffix in packed_enums and param_name in packed_enums[cmd_no_suffix]:
2936                packed_type = remove_id_suffix(packed_enums[cmd_no_suffix][param_name])
2937                if packed_type == 'Sync':
2938                    param_access = 'gSyncMap2[captures[%d].value.GLuintVal]' % i
2939                elif packed_type in resource_id_types:
2940                    param_access = 'g%sMap[%s]' % (packed_type, param_access)
2941                elif packed_type == 'UniformLocation':
2942                    param_access = 'gUniformLocations[gCurrentProgram][%s]' % param_access
2943                elif packed_type == 'egl::Image':
2944                    param_access = 'gEGLImageMap2[captures[%d].value.GLuintVal]' % i
2945                elif packed_type == 'egl::Sync':
2946                    param_access = 'gEGLSyncMap[captures[%d].value.egl_SyncIDVal]' % i
2947        param_access_strs.append(param_access)
2948    return ', '.join(param_access_strs)
2949
2950
2951def format_capture_replay_call_case(api, command_to_param_types_mapping, gl_packed_enums,
2952                                    resource_id_types):
2953    call_list = list()
2954    for command_name, cmd_param_texts in sorted(command_to_param_types_mapping.items()):
2955        entry_point_name = strip_api_prefix(command_name)
2956
2957        call_list.append(
2958            TEMPLATE_REPLAY_CALL_CASE.format(
2959                enum=('EGL' if api == 'EGL' else 'GL') + entry_point_name,
2960                params=format_replay_params(api, command_name, cmd_param_texts, gl_packed_enums,
2961                                            resource_id_types),
2962                call=command_name,
2963            ))
2964
2965    return ''.join(call_list)
2966
2967
2968def write_capture_replay_source(gl_command_nodes, gl_command_names, gl_packed_enums,
2969                                egl_command_nodes, egl_command_names, egl_packed_enums,
2970                                resource_id_types):
2971
2972    call_replay_cases = ''
2973
2974    for api, nodes, names, packed_enums in [
2975        (apis.GLES, gl_command_nodes, gl_command_names, gl_packed_enums),
2976        (apis.EGL, egl_command_nodes, egl_command_names, egl_packed_enums)
2977    ]:
2978        command_to_param_types_mapping = dict()
2979        all_commands_names = set(names)
2980        for command_node in nodes:
2981            command_name = command_node.find('proto').find('name').text
2982            if command_name not in all_commands_names:
2983                continue
2984            command_to_param_types_mapping[command_name] = get_command_params_text(
2985                command_node, command_name)
2986
2987        call_replay_cases += format_capture_replay_call_case(api, command_to_param_types_mapping,
2988                                                             packed_enums, resource_id_types)
2989
2990    source_content = TEMPLATE_CAPTURE_REPLAY_SOURCE.format(
2991        script_name=os.path.basename(sys.argv[0]),
2992        data_source_name="gl.xml and gl_angle_ext.xml",
2993        call_replay_cases=call_replay_cases,
2994    )
2995    source_file_path = registry_xml.script_relative(
2996        "../util/capture/frame_capture_replay_autogen.cpp")
2997    with open(source_file_path, 'w') as f:
2998        f.write(source_content)
2999
3000
3001def write_windows_def_file(data_source_name, lib, libexport, folder, exports):
3002
3003    content = TEMPLATE_WINDOWS_DEF_FILE.format(
3004        script_name=os.path.basename(sys.argv[0]),
3005        data_source_name=data_source_name,
3006        exports="\n".join(exports),
3007        lib=libexport)
3008
3009    path = path_to(folder, "%s_autogen.def" % lib)
3010
3011    with open(path, "w") as out:
3012        out.write(content)
3013        out.close()
3014
3015
3016def get_exports(commands, fmt=None):
3017    if fmt:
3018        return ["    %s" % fmt(cmd) for cmd in sorted(commands)]
3019    else:
3020        return ["    %s" % cmd for cmd in sorted(commands)]
3021
3022
3023# Get EGL exports
3024def get_egl_exports():
3025
3026    egl = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
3027    exports = []
3028
3029    capser = lambda fn: "EGL_" + fn[3:]
3030
3031    for major, minor in registry_xml.EGL_VERSIONS:
3032        annotation = "{}_{}".format(major, minor)
3033        name_prefix = "EGL_VERSION_"
3034
3035        feature_name = "{}{}".format(name_prefix, annotation)
3036
3037        egl.AddCommands(feature_name, annotation)
3038
3039        commands = egl.commands[annotation]
3040
3041        if len(commands) == 0:
3042            continue
3043
3044        exports.append("\n    ; EGL %d.%d" % (major, minor))
3045        exports += get_exports(commands, capser)
3046
3047    egl.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
3048
3049    for extension_name, ext_cmd_names in sorted(egl.ext_data.items()):
3050
3051        if len(ext_cmd_names) == 0:
3052            continue
3053
3054        exports.append("\n    ; %s" % extension_name)
3055        exports += get_exports(ext_cmd_names, capser)
3056
3057    return exports
3058
3059
3060# Construct a mapping from an EGL EP to object function
3061def get_egl_entry_point_labeled_object(ep_to_object, cmd_stripped, params, packed_enums):
3062
3063    if not ep_to_object:
3064        return ""
3065
3066    # Finds a packed parameter name in a list of params
3067    def find_param(params, type_name, packed_enums):
3068        for param in params:
3069            if just_the_type_packed(param, packed_enums).split(' ')[0] == type_name:
3070                return just_the_name_packed(param, packed_enums)
3071        return None
3072
3073    display_param = find_param(params, "egl::Display", packed_enums)
3074
3075    # For entry points not listed in the JSON file, they default to an EGLDisplay or nothing.
3076    if cmd_stripped not in ep_to_object:
3077        if display_param:
3078            return "GetDisplayIfValid(%s)" % display_param
3079        return "nullptr"
3080
3081    # We first handle a few special cases for certain type categories.
3082    category = ep_to_object[cmd_stripped]
3083    if category == "Thread":
3084        return "GetThreadIfValid(thread)"
3085    found_param = find_param(params, category, packed_enums)
3086    if category == "Context" and not found_param:
3087        return "GetContextIfValid(thread->getDisplay(), thread->getContext())"
3088    assert found_param, "Did not find %s for %s: %s" % (category, cmd_stripped, str(params))
3089    if category == "Device":
3090        return "GetDeviceIfValid(%s)" % found_param
3091    if category == "LabeledObject":
3092        object_type_param = find_param(params, "ObjectType", packed_enums)
3093        return "GetLabeledObjectIfValid(thread, %s, %s, %s)" % (display_param, object_type_param,
3094                                                                found_param)
3095
3096    # We then handle the general case which handles the rest of the type categories.
3097    return "Get%sIfValid(%s, %s)" % (category, display_param, found_param)
3098
3099
3100def disable_share_group_lock(api, cmd_name):
3101    if cmd_name == 'glBindBuffer':
3102        # This function looks up the ID in the buffer manager,
3103        # access to which is thread-safe for buffers.
3104        return True
3105
3106    if api == apis.GLES and cmd_name.startswith('glUniform'):
3107        # Thread safety of glUniform1/2/3/4 and glUniformMatrix* calls is defined by the backend,
3108        # frontend only does validation.
3109        keep_locked = [
3110            # Might set samplers:
3111            'glUniform1i',
3112            'glUniform1iv',
3113            # More complex state change with notifications:
3114            'glUniformBlockBinding',
3115        ]
3116        return cmd_name not in keep_locked
3117
3118    return False
3119
3120
3121def get_context_lock(api, cmd_name):
3122    # EGLImage related commands need to access EGLImage and Display which should
3123    # be protected with global lock
3124    # Also handles ContextMutex merging when "angle_enable_context_mutex" is true.
3125    if api == apis.GLES and cmd_name.startswith("glEGLImage"):
3126        return "SCOPED_EGL_IMAGE_SHARE_CONTEXT_LOCK(context, imagePacked);"
3127
3128    # Certain commands do not need to hold the share group lock.  Both
3129    # validation and their implementation in the context are limited to
3130    # context-local state.
3131    if disable_share_group_lock(api, cmd_name):
3132        return ""
3133
3134    return "SCOPED_SHARE_CONTEXT_LOCK(context);"
3135
3136
3137def get_prepare_swap_buffers_call(api, cmd_name, params):
3138    if cmd_name not in [
3139            "eglSwapBuffers",
3140            "eglSwapBuffersWithDamageKHR",
3141            "eglSwapBuffersWithFrameTokenANGLE",
3142            "eglQuerySurface",
3143            "eglQuerySurface64KHR",
3144    ]:
3145        return ""
3146
3147    passed_params = [None, None]
3148
3149    for param in params:
3150        param_type = just_the_type(param)
3151        if param_type == "EGLDisplay":
3152            passed_params[0] = param
3153        if param_type == "EGLSurface":
3154            passed_params[1] = param
3155
3156    prepareCall = "ANGLE_EGLBOOLEAN_TRY(EGL_PrepareSwapBuffersANGLE(%s));" % (", ".join(
3157        [just_the_name(param) for param in passed_params]))
3158
3159    # For eglQuerySurface, the prepare call is only needed for EGL_BUFFER_AGE
3160    if cmd_name in ["eglQuerySurface", "eglQuerySurface64KHR"]:
3161        prepareCall = "if (attribute == EGL_BUFFER_AGE_EXT) {" + prepareCall + "}"
3162
3163    return prepareCall
3164
3165
3166def get_preamble(api, cmd_name, params):
3167    preamble = ""
3168    preamble += get_prepare_swap_buffers_call(api, cmd_name, params)
3169    # TODO: others?
3170    return preamble
3171
3172
3173def get_unlocked_tail_call(api, cmd_name):
3174    # Only the following can generate tail calls:
3175    #
3176    # - eglDestroySurface, eglMakeCurrent and eglReleaseThread -> May destroy
3177    #   VkSurfaceKHR in tail call
3178    # - eglCreateWindowSurface and eglCreatePlatformWindowSurface[EXT] -> May
3179    #   destroy VkSurfaceKHR in tail call if surface initialization fails
3180    #
3181    # - eglPrepareSwapBuffersANGLE -> Calls vkAcquireNextImageKHR in tail call
3182    #
3183    # - eglSwapBuffers, eglSwapBuffersWithDamageKHR and
3184    #   eglSwapBuffersWithFrameTokenANGLE -> May throttle the CPU in tail call or
3185    #   calls native EGL function
3186    #
3187    # - eglClientWaitSyncKHR, eglClientWaitSync, glClientWaitSync,
3188    #   glFinishFenceNV -> May wait on fence in tail call or call native EGL function
3189    #
3190    # - glTexImage2D, glTexImage3D, glTexSubImage2D, glTexSubImage3D,
3191    #   glCompressedTexImage2D, glCompressedTexImage3D,
3192    #   glCompressedTexSubImage2D, glCompressedTexSubImage3D -> May perform the
3193    #   data upload on the host in tail call
3194    #
3195    # - glCompileShader and glLinkProgram -> May perform the compilation / link
3196    #   in tail call
3197    #
3198    # - eglCreateSync, eglCreateImage, eglDestroySync, eglDestroyImage,
3199    #   eglGetCompositorTimingANDROID, eglGetFrameTimestampsANDROID -> Calls
3200    #   native EGL function in tail call
3201    #
3202    if (cmd_name in [
3203            'eglDestroySurface', 'eglMakeCurrent', 'eglReleaseThread', 'eglCreateWindowSurface',
3204            'eglCreatePlatformWindowSurface', 'eglCreatePlatformWindowSurfaceEXT',
3205            'eglPrepareSwapBuffersANGLE', 'eglSwapBuffersWithFrameTokenANGLE', 'glFinishFenceNV',
3206            'glCompileShader', 'glLinkProgram'
3207    ] or cmd_name.startswith('glTexImage2D') or cmd_name.startswith('glTexImage3D') or
3208            cmd_name.startswith('glTexSubImage2D') or cmd_name.startswith('glTexSubImage3D') or
3209            cmd_name.startswith('glCompressedTexImage2D') or
3210            cmd_name.startswith('glCompressedTexImage3D') or
3211            cmd_name.startswith('glCompressedTexSubImage2D') or
3212            cmd_name.startswith('glCompressedTexSubImage3D')):
3213        return 'egl::Display::GetCurrentThreadUnlockedTailCall()->run(nullptr);'
3214
3215    if cmd_name in [
3216            'eglClientWaitSyncKHR',
3217            'eglClientWaitSync',
3218            'eglCreateImageKHR',
3219            'eglCreateImage',
3220            'eglCreateSyncKHR',
3221            'eglCreateSync',
3222            'eglDestroySyncKHR',
3223            'eglDestroySync',
3224            'eglGetCompositorTimingANDROID',
3225            'eglGetFrameTimestampsANDROID',
3226            'eglSwapBuffers',
3227            'eglSwapBuffersWithDamageKHR',
3228            'eglWaitSyncKHR',
3229            'eglWaitSync',
3230            'glClientWaitSync',
3231    ]:
3232        return 'egl::Display::GetCurrentThreadUnlockedTailCall()->run(&returnValue);'
3233
3234    # Otherwise assert that no tail calls where generated
3235    return 'ASSERT(!egl::Display::GetCurrentThreadUnlockedTailCall()->any());'
3236
3237
3238def get_epilog(api, cmd_name):
3239    epilog = get_unlocked_tail_call(api, cmd_name)
3240    return epilog
3241
3242
3243def write_stubs_header(api, annotation, title, data_source, out_file, all_commands, commands,
3244                       cmd_packed_egl_enums, packed_param_types):
3245
3246    stubs = []
3247
3248    for command in all_commands:
3249        proto = command.find('proto')
3250        cmd_name = proto.find('name').text
3251
3252        if cmd_name not in commands:
3253            continue
3254
3255        proto_text = "".join(proto.itertext())
3256
3257        params = [] if api == apis.CL else ["Thread *thread"]
3258        params += ["".join(param.itertext()) for param in command.findall('param')]
3259        if params and just_the_name(params[-1]) == "errcode_ret":
3260            # Using TLS object for CL error handling, no longer a need for errcode_ret
3261            del params[-1]
3262        return_type = proto_text[:-len(cmd_name)].strip()
3263
3264        internal_params = get_internal_params(api, cmd_name, params, cmd_packed_egl_enums,
3265                                              packed_param_types)
3266        stubs.append("%s %s(%s);" % (return_type, strip_api_prefix(cmd_name), internal_params))
3267
3268    args = {
3269        "annotation_lower": annotation.lower(),
3270        "annotation_upper": annotation.upper(),
3271        "data_source_name": data_source,
3272        "script_name": os.path.basename(sys.argv[0]),
3273        "stubs": "\n".join(stubs),
3274        "title": title,
3275    }
3276
3277    output = get_stubs_header_template(api).format(**args)
3278
3279    with open(out_file, "w") as f:
3280        f.write(output)
3281
3282
3283def main():
3284
3285    # auto_script parameters.
3286    if len(sys.argv) > 1:
3287        inputs = [
3288            'entry_point_packed_egl_enums.json', 'entry_point_packed_gl_enums.json',
3289            EGL_GET_LABELED_OBJECT_DATA_PATH
3290        ] + registry_xml.xml_inputs
3291        outputs = [
3292            CL_STUBS_HEADER_PATH,
3293            EGL_STUBS_HEADER_PATH,
3294            EGL_EXT_STUBS_HEADER_PATH,
3295            '../src/libOpenCL/libOpenCL_autogen.cpp',
3296            '../src/common/entry_points_enum_autogen.cpp',
3297            '../src/common/entry_points_enum_autogen.h',
3298            '../src/common/frame_capture_utils_autogen.cpp',
3299            '../src/common/frame_capture_utils_autogen.h',
3300            '../src/libANGLE/Context_gl_1_autogen.h',
3301            '../src/libANGLE/Context_gl_2_autogen.h',
3302            '../src/libANGLE/Context_gl_3_autogen.h',
3303            '../src/libANGLE/Context_gl_4_autogen.h',
3304            '../src/libANGLE/Context_gles_1_0_autogen.h',
3305            '../src/libANGLE/Context_gles_2_0_autogen.h',
3306            '../src/libANGLE/Context_gles_3_0_autogen.h',
3307            '../src/libANGLE/Context_gles_3_1_autogen.h',
3308            '../src/libANGLE/Context_gles_3_2_autogen.h',
3309            '../src/libANGLE/Context_gles_ext_autogen.h',
3310            '../src/libANGLE/context_private_call_gles_autogen.h',
3311            '../src/libANGLE/context_private_call_gl_autogen.h',
3312            '../src/libANGLE/capture/capture_egl_autogen.cpp',
3313            '../src/libANGLE/capture/capture_egl_autogen.h',
3314            '../src/libANGLE/capture/capture_gl_1_autogen.cpp',
3315            '../src/libANGLE/capture/capture_gl_1_autogen.h',
3316            '../src/libANGLE/capture/capture_gl_2_autogen.cpp',
3317            '../src/libANGLE/capture/capture_gl_2_autogen.h',
3318            '../src/libANGLE/capture/capture_gl_3_autogen.cpp',
3319            '../src/libANGLE/capture/capture_gl_3_autogen.h',
3320            '../src/libANGLE/capture/capture_gl_4_autogen.cpp',
3321            '../src/libANGLE/capture/capture_gl_4_autogen.h',
3322            '../src/libANGLE/capture/capture_gles_1_0_autogen.cpp',
3323            '../src/libANGLE/capture/capture_gles_1_0_autogen.h',
3324            '../src/libANGLE/capture/capture_gles_2_0_autogen.cpp',
3325            '../src/libANGLE/capture/capture_gles_2_0_autogen.h',
3326            '../src/libANGLE/capture/capture_gles_3_0_autogen.cpp',
3327            '../src/libANGLE/capture/capture_gles_3_0_autogen.h',
3328            '../src/libANGLE/capture/capture_gles_3_1_autogen.cpp',
3329            '../src/libANGLE/capture/capture_gles_3_1_autogen.h',
3330            '../src/libANGLE/capture/capture_gles_3_2_autogen.cpp',
3331            '../src/libANGLE/capture/capture_gles_3_2_autogen.h',
3332            '../src/libANGLE/capture/capture_gles_ext_autogen.cpp',
3333            '../src/libANGLE/capture/capture_gles_ext_autogen.h',
3334            '../src/libANGLE/validationCL_autogen.h',
3335            '../src/libANGLE/validationEGL_autogen.h',
3336            '../src/libANGLE/validationES1_autogen.h',
3337            '../src/libANGLE/validationES2_autogen.h',
3338            '../src/libANGLE/validationES31_autogen.h',
3339            '../src/libANGLE/validationES32_autogen.h',
3340            '../src/libANGLE/validationES3_autogen.h',
3341            '../src/libANGLE/validationESEXT_autogen.h',
3342            '../src/libANGLE/validationGL1_autogen.h',
3343            '../src/libANGLE/validationGL2_autogen.h',
3344            '../src/libANGLE/validationGL3_autogen.h',
3345            '../src/libANGLE/validationGL4_autogen.h',
3346            '../src/libEGL/libEGL_autogen.cpp',
3347            '../src/libEGL/libEGL_autogen.def',
3348            '../src/libGLESv2/entry_points_cl_autogen.cpp',
3349            '../src/libGLESv2/entry_points_cl_autogen.h',
3350            '../src/libGLESv2/entry_points_egl_autogen.cpp',
3351            '../src/libGLESv2/entry_points_egl_autogen.h',
3352            '../src/libGLESv2/entry_points_egl_ext_autogen.cpp',
3353            '../src/libGLESv2/entry_points_egl_ext_autogen.h',
3354            '../src/libGLESv2/entry_points_gles_1_0_autogen.cpp',
3355            '../src/libGLESv2/entry_points_gles_1_0_autogen.h',
3356            '../src/libGLESv2/entry_points_gles_2_0_autogen.cpp',
3357            '../src/libGLESv2/entry_points_gles_2_0_autogen.h',
3358            '../src/libGLESv2/entry_points_gles_3_0_autogen.cpp',
3359            '../src/libGLESv2/entry_points_gles_3_0_autogen.h',
3360            '../src/libGLESv2/entry_points_gles_3_1_autogen.cpp',
3361            '../src/libGLESv2/entry_points_gles_3_1_autogen.h',
3362            '../src/libGLESv2/entry_points_gles_3_2_autogen.cpp',
3363            '../src/libGLESv2/entry_points_gles_3_2_autogen.h',
3364            '../src/libGLESv2/entry_points_gles_ext_autogen.cpp',
3365            '../src/libGLESv2/entry_points_gles_ext_autogen.h',
3366            '../src/libGLESv2/libGLESv2_autogen.cpp',
3367            '../src/libGLESv2/libGLESv2_autogen.def',
3368            '../src/libGLESv2/libGLESv2_no_capture_autogen.def',
3369            '../src/libGLESv2/libGLESv2_with_capture_autogen.def',
3370            '../src/libGLESv2/entry_points_gl_1_autogen.cpp',
3371            '../src/libGLESv2/entry_points_gl_1_autogen.h',
3372            '../src/libGLESv2/entry_points_gl_2_autogen.cpp',
3373            '../src/libGLESv2/entry_points_gl_2_autogen.h',
3374            '../src/libGLESv2/entry_points_gl_3_autogen.cpp',
3375            '../src/libGLESv2/entry_points_gl_3_autogen.h',
3376            '../src/libGLESv2/entry_points_gl_4_autogen.cpp',
3377            '../src/libGLESv2/entry_points_gl_4_autogen.h',
3378            '../src/libGLESv2/egl_context_lock_autogen.h',
3379            '../util/capture/frame_capture_replay_autogen.cpp',
3380        ]
3381
3382        if sys.argv[1] == 'inputs':
3383            print(','.join(inputs))
3384        elif sys.argv[1] == 'outputs':
3385            print(','.join(outputs))
3386        else:
3387            print('Invalid script parameters')
3388            return 1
3389        return 0
3390
3391    glesdecls = {}
3392    glesdecls['core'] = {}
3393    glesdecls['exts'] = {}
3394    for ver in registry_xml.GLES_VERSIONS:
3395        glesdecls['core'][ver] = []
3396    for ver in ['GLES1 Extensions', 'GLES2+ Extensions', 'ANGLE Extensions']:
3397        glesdecls['exts'][ver] = {}
3398
3399    libgles_ep_defs = []
3400    libgles_ep_exports = []
3401
3402    xml = registry_xml.RegistryXML('gl.xml', 'gl_angle_ext.xml')
3403
3404    # Stores core commands to keep track of duplicates
3405    all_commands_no_suffix = []
3406    all_commands_with_suffix = []
3407
3408    # Collect all context-private-state-accessing helper declarations
3409    context_private_call_gles_protos = []
3410    context_private_call_gl_protos = []
3411    context_private_call_functions = set()
3412
3413    # First run through the main GLES entry points.  Since ES2+ is the primary use
3414    # case, we go through those first and then add ES1-only APIs at the end.
3415    for major_version, minor_version in registry_xml.GLES_VERSIONS:
3416        version = "{}_{}".format(major_version, minor_version)
3417        annotation = "GLES_{}".format(version)
3418        name_prefix = "GL_ES_VERSION_"
3419
3420        if major_version == 1:
3421            name_prefix = "GL_VERSION_ES_CM_"
3422
3423        comment = version.replace("_", ".")
3424        feature_name = "{}{}".format(name_prefix, version)
3425
3426        xml.AddCommands(feature_name, version)
3427
3428        version_commands = xml.commands[version]
3429        all_commands_no_suffix.extend(xml.commands[version])
3430        all_commands_with_suffix.extend(xml.commands[version])
3431
3432        eps = GLEntryPoints(apis.GLES, xml, version_commands, is_gles1=(major_version == 1))
3433        eps.decls.insert(0, "extern \"C\" {")
3434        eps.decls.append("} // extern \"C\"")
3435        eps.defs.insert(0, "extern \"C\" {")
3436        eps.defs.append("} // extern \"C\"")
3437
3438        # Write the version as a comment before the first EP.
3439        libgles_ep_exports.append("\n    ; OpenGL ES %s" % comment)
3440
3441        libgles_ep_defs += ["\n// OpenGL ES %s" % comment] + eps.export_defs
3442        libgles_ep_exports += get_exports(version_commands)
3443
3444        major_if_not_one = major_version if major_version != 1 else ""
3445        minor_if_not_zero = minor_version if minor_version != 0 else ""
3446
3447        header_includes = TEMPLATE_HEADER_INCLUDES.format(
3448            major=major_if_not_one, minor=minor_if_not_zero)
3449
3450        version_annotation = "%s%s" % (major_version, minor_if_not_zero)
3451        source_includes = TEMPLATE_SOURCES_INCLUDES.format(
3452            header_version=annotation.lower(), validation_header_version="ES" + version_annotation)
3453
3454        write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_HEADER,
3455                   "\n".join(eps.decls), "h", header_includes, "libGLESv2", "gl.xml")
3456        write_file(annotation, "GLES " + comment, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(eps.defs),
3457                   "cpp", source_includes, "libGLESv2", "gl.xml")
3458
3459        glesdecls['core'][(major_version,
3460                           minor_version)] = get_decls(apis.GLES, CONTEXT_DECL_FORMAT,
3461                                                       xml.all_commands, version_commands, [],
3462                                                       GLEntryPoints.get_packed_enums())
3463
3464        validation_annotation = "ES%s%s" % (major_version, minor_if_not_zero)
3465        write_gl_validation_header(validation_annotation, "ES %s" % comment, eps.validation_protos,
3466                                   "gl.xml and gl_angle_ext.xml")
3467
3468        context_private_call_gles_protos += eps.context_private_call_protos
3469        context_private_call_functions.update(eps.context_private_call_functions)
3470
3471        write_capture_header(apis.GLES, 'gles_' + version, comment, eps.capture_protos,
3472                             eps.capture_pointer_funcs)
3473        write_capture_source(apis.GLES, 'gles_' + version, validation_annotation, comment,
3474                             eps.capture_methods)
3475
3476    # After we finish with the main entry points, we process the extensions.
3477    extension_decls = ["extern \"C\" {"]
3478    extension_defs = ["extern \"C\" {"]
3479    extension_commands = []
3480
3481    # Accumulated validation prototypes.
3482    ext_validation_protos = []
3483    ext_capture_protos = []
3484    ext_capture_methods = []
3485    ext_capture_pointer_funcs = []
3486
3487    for gles1ext in registry_xml.gles1_extensions:
3488        glesdecls['exts']['GLES1 Extensions'][gles1ext] = []
3489    for glesext in registry_xml.gles_extensions:
3490        glesdecls['exts']['GLES2+ Extensions'][glesext] = []
3491    for angle_ext in registry_xml.angle_extensions:
3492        glesdecls['exts']['ANGLE Extensions'][angle_ext] = []
3493
3494    xml.AddExtensionCommands(registry_xml.supported_extensions, ['gles2', 'gles1'])
3495
3496    for extension_name, ext_cmd_names in sorted(xml.ext_data.items()):
3497        extension_commands.extend(xml.ext_data[extension_name])
3498
3499        # Detect and filter duplicate extensions.
3500        is_gles1 = extension_name in registry_xml.gles1_extensions
3501        eps = GLEntryPoints(apis.GLES, xml, ext_cmd_names, is_gles1=is_gles1)
3502
3503        # Write the extension name as a comment before the first EP.
3504        comment = "\n// {}".format(extension_name)
3505        libgles_ep_exports.append("\n    ; %s" % extension_name)
3506
3507        extension_defs += [comment] + eps.defs
3508        extension_decls += [comment] + eps.decls
3509
3510        # Avoid writing out entry points defined by a prior extension.
3511        for dupe in xml.ext_dupes[extension_name]:
3512            msg = "// {} is already defined.\n".format(strip_api_prefix(dupe))
3513            extension_defs.append(msg)
3514
3515        ext_validation_protos += [comment] + eps.validation_protos
3516        ext_capture_protos += [comment] + eps.capture_protos
3517        ext_capture_methods += eps.capture_methods
3518        ext_capture_pointer_funcs += eps.capture_pointer_funcs
3519
3520        for proto, function in zip(eps.context_private_call_protos,
3521                                   eps.context_private_call_functions):
3522            if function not in context_private_call_functions:
3523                context_private_call_gles_protos.append(proto)
3524        context_private_call_functions.update(eps.context_private_call_functions)
3525
3526        libgles_ep_defs += [comment] + eps.export_defs
3527        libgles_ep_exports += get_exports(ext_cmd_names)
3528
3529        if (extension_name in registry_xml.gles1_extensions and
3530                extension_name not in GLES1_NO_CONTEXT_DECL_EXTENSIONS):
3531            glesdecls['exts']['GLES1 Extensions'][extension_name] = get_decls(
3532                apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
3533                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
3534        if extension_name in registry_xml.gles_extensions:
3535            glesdecls['exts']['GLES2+ Extensions'][extension_name] = get_decls(
3536                apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
3537                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
3538        if extension_name in registry_xml.angle_extensions:
3539            glesdecls['exts']['ANGLE Extensions'][extension_name] = get_decls(
3540                apis.GLES, CONTEXT_DECL_FORMAT, xml.all_commands, ext_cmd_names,
3541                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
3542
3543    write_context_private_call_header("gles", context_private_call_gles_protos,
3544                                      "gl.xml and gl_angle_ext.xml",
3545                                      TEMPLATE_CONTEXT_PRIVATE_CALL_HEADER)
3546
3547    for name in extension_commands:
3548        all_commands_with_suffix.append(name)
3549        all_commands_no_suffix.append(strip_suffix(apis.GLES, name))
3550
3551    # Now we generate entry points for the desktop implementation
3552    desktop_gl_decls = {}
3553    desktop_gl_decls['core'] = {}
3554    for major, _ in registry_xml.DESKTOP_GL_VERSIONS:
3555        desktop_gl_decls['core'][(major, "X")] = []
3556
3557    libgles_ep_defs.append('#if defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)')
3558    libgl_ep_exports = libgles_ep_exports.copy()
3559
3560    glxml = registry_xml.RegistryXML('gl.xml')
3561
3562    for major_version in sorted(
3563            set([major for (major, minor) in registry_xml.DESKTOP_GL_VERSIONS])):
3564        is_major = lambda ver: ver[0] == major_version
3565
3566        ver_decls = ["extern \"C\" {"]
3567        ver_defs = ["extern \"C\" {"]
3568        validation_protos = []
3569        capture_protos = []
3570        capture_pointer_funcs = []
3571        capture_defs = []
3572
3573        for _, minor_version in filter(is_major, registry_xml.DESKTOP_GL_VERSIONS):
3574            version = "{}_{}".format(major_version, minor_version)
3575            annotation = "GL_{}".format(version)
3576            name_prefix = "GL_VERSION_"
3577
3578            comment = version.replace("_", ".")
3579            feature_name = "{}{}".format(name_prefix, version)
3580
3581            glxml.AddCommands(feature_name, version)
3582
3583            all_libgl_commands = glxml.commands[version]
3584            just_libgl_commands_suffix = [
3585                cmd for cmd in all_libgl_commands if cmd not in all_commands_with_suffix
3586            ]
3587
3588            # Validation duplicates handled with suffix
3589            eps = GLEntryPoints(apis.GL, glxml, just_libgl_commands_suffix)
3590
3591            desktop_gl_decls['core'][(major_version, "X")] += get_decls(
3592                apis.GL, CONTEXT_DECL_FORMAT, glxml.all_commands, just_libgl_commands_suffix,
3593                all_commands_no_suffix, GLEntryPoints.get_packed_enums())
3594
3595            # Write the version as a comment before the first EP.
3596            cpp_comment = "\n// GL %s" % comment
3597            def_comment = "\n    ; GL %s" % comment
3598
3599            libgles_ep_defs += [cpp_comment] + eps.export_defs
3600            libgl_ep_exports += [def_comment] + get_exports(all_libgl_commands)
3601            validation_protos += [cpp_comment] + eps.validation_protos
3602
3603            for proto, function in zip(eps.context_private_call_protos,
3604                                       eps.context_private_call_functions):
3605                if function not in context_private_call_functions:
3606                    context_private_call_gl_protos.append(proto)
3607            context_private_call_functions.update(eps.context_private_call_functions)
3608
3609            capture_protos += [cpp_comment] + eps.capture_protos
3610            capture_pointer_funcs += [cpp_comment] + eps.capture_pointer_funcs
3611            capture_defs += [cpp_comment] + eps.capture_methods
3612            ver_decls += [cpp_comment] + eps.decls
3613            ver_defs += [cpp_comment] + eps.defs
3614
3615        ver_decls.append("} // extern \"C\"")
3616        ver_defs.append("} // extern \"C\"")
3617        annotation = "GL_%d" % major_version
3618        name = "Desktop GL %s.x" % major_version
3619
3620        source_includes = TEMPLATE_DESKTOP_GL_SOURCE_INCLUDES.format(annotation.lower(),
3621                                                                     major_version)
3622
3623        # Entry point files
3624        write_file(annotation, name, TEMPLATE_ENTRY_POINT_HEADER, "\n".join(ver_decls), "h",
3625                   DESKTOP_GL_HEADER_INCLUDES, "libGLESv2", "gl.xml")
3626        write_file(annotation, name, TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(ver_defs), "cpp",
3627                   source_includes, "libGLESv2", "gl.xml")
3628
3629        # Capture files
3630        write_capture_header(apis.GL, annotation.lower(), name, capture_protos,
3631                             capture_pointer_funcs)
3632        write_capture_source(apis.GL, annotation.lower(), 'GL' + str(major_version) + '_autogen',
3633                             name, capture_defs)
3634
3635        # Validation files
3636        write_gl_validation_header("GL%s" % major_version, name, validation_protos, "gl.xml")
3637
3638    libgles_ep_defs.append('#endif // defined(ANGLE_ENABLE_GL_DESKTOP_FRONTEND)')
3639
3640    write_context_private_call_header("gl", context_private_call_gl_protos,
3641                                      "gl.xml and gl_angle_ext.xml",
3642                                      TEMPLATE_CONTEXT_PRIVATE_CALL_HEADER)
3643
3644    # GLX
3645    glxxml = registry_xml.RegistryXML('glx.xml')
3646    glx_validation_protos = []
3647    glx_decls = ["namespace glx\n{"]
3648    glx_defs = ["namespace glx\n{"]
3649    libglx_ep_defs = []
3650    glx_commands = []
3651    for major_version, minor_version in registry_xml.GLX_VERSIONS:
3652        version = "{}_{}".format(major_version, minor_version)
3653        annotation = "GLX_{}".format(version)
3654        name_prefix = "GLX_VERSION_"
3655
3656        comment = version.replace("_", ".")
3657        feature_name = "{}{}".format(name_prefix, version)
3658
3659        glxxml.AddCommands(feature_name, version)
3660        glx_version_commands = glxxml.commands[version]
3661        glx_commands += glx_version_commands
3662
3663        if not glx_version_commands:
3664            continue
3665
3666
3667
3668    # OpenCL
3669    clxml = registry_xml.RegistryXML('cl.xml')
3670
3671    cl_validation_protos = []
3672    cl_decls = ["namespace cl\n{"]
3673    cl_defs = ["namespace cl\n{"]
3674    libcl_ep_defs = []
3675    libcl_windows_def_exports = []
3676    cl_commands = []
3677
3678    for major_version, minor_version in registry_xml.CL_VERSIONS:
3679        version = "%d_%d" % (major_version, minor_version)
3680        annotation = "CL_%s" % version
3681        name_prefix = "CL_VERSION_"
3682
3683        comment = version.replace("_", ".")
3684        feature_name = "%s%s" % (name_prefix, version)
3685
3686        clxml.AddCommands(feature_name, version)
3687
3688        cl_version_commands = clxml.commands[version]
3689        cl_commands += cl_version_commands
3690
3691        # Spec revs may have no new commands.
3692        if not cl_version_commands:
3693            continue
3694
3695        eps = CLEntryPoints(clxml, cl_version_commands)
3696
3697        comment = "\n// CL %d.%d" % (major_version, minor_version)
3698        win_def_comment = "\n    ; CL %d.%d" % (major_version, minor_version)
3699
3700        cl_decls += [comment] + eps.decls
3701        cl_defs += [comment] + eps.defs
3702        libcl_ep_defs += [comment] + eps.export_defs
3703        cl_validation_protos += [comment] + eps.validation_protos
3704        libcl_windows_def_exports += [win_def_comment] + get_exports(clxml.commands[version])
3705
3706    clxml.AddExtensionCommands(registry_xml.supported_cl_extensions, ['cl'])
3707    for extension_name, ext_cmd_names in sorted(clxml.ext_data.items()):
3708
3709        # Extensions may have no new commands.
3710        if not ext_cmd_names:
3711            continue
3712
3713        # Detect and filter duplicate extensions.
3714        eps = CLEntryPoints(clxml, ext_cmd_names)
3715
3716        comment = "\n// %s" % extension_name
3717        win_def_comment = "\n    ; %s" % (extension_name)
3718
3719        cl_commands += ext_cmd_names
3720
3721        cl_decls += [comment] + eps.decls
3722        cl_defs += [comment] + eps.defs
3723        libcl_ep_defs += [comment] + eps.export_defs
3724        cl_validation_protos += [comment] + eps.validation_protos
3725        libcl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
3726
3727        # Avoid writing out entry points defined by a prior extension.
3728        for dupe in clxml.ext_dupes[extension_name]:
3729            msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
3730            cl_defs.append(msg)
3731
3732    cl_decls.append("}  // namespace cl")
3733    cl_defs.append("}  // namespace cl")
3734
3735    write_file("cl", "CL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(cl_decls), "h",
3736               LIBCL_HEADER_INCLUDES, "libGLESv2", "cl.xml")
3737    write_file("cl", "CL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(cl_defs), "cpp",
3738               LIBCL_SOURCE_INCLUDES, "libGLESv2", "cl.xml")
3739    write_validation_header("CL", "CL", cl_validation_protos, "cl.xml",
3740                            TEMPLATE_CL_VALIDATION_HEADER)
3741    write_stubs_header("CL", "cl", "CL", "cl.xml", CL_STUBS_HEADER_PATH, clxml.all_commands,
3742                       cl_commands, CLEntryPoints.get_packed_enums(), CL_PACKED_TYPES)
3743
3744    # EGL
3745    eglxml = registry_xml.RegistryXML('egl.xml', 'egl_angle_ext.xml')
3746
3747    egl_validation_protos = []
3748    egl_context_lock_protos = []
3749    egl_decls = ["extern \"C\" {"]
3750    egl_defs = ["extern \"C\" {"]
3751    libegl_ep_defs = []
3752    libegl_windows_def_exports = []
3753    egl_commands = []
3754    egl_capture_protos = []
3755    egl_capture_methods = []
3756
3757    for major_version, minor_version in registry_xml.EGL_VERSIONS:
3758        version = "%d_%d" % (major_version, minor_version)
3759        annotation = "EGL_%s" % version
3760        name_prefix = "EGL_VERSION_"
3761
3762        comment = version.replace("_", ".")
3763        feature_name = "%s%s" % (name_prefix, version)
3764
3765        eglxml.AddCommands(feature_name, version)
3766
3767        egl_version_commands = eglxml.commands[version]
3768        egl_commands += egl_version_commands
3769
3770        # Spec revs may have no new commands.
3771        if not egl_version_commands:
3772            continue
3773
3774        eps = EGLEntryPoints(eglxml, egl_version_commands)
3775
3776        comment = "\n// EGL %d.%d" % (major_version, minor_version)
3777        win_def_comment = "\n    ; EGL %d.%d" % (major_version, minor_version)
3778
3779        egl_decls += [comment] + eps.decls
3780        egl_defs += [comment] + eps.defs
3781        libegl_ep_defs += [comment] + eps.export_defs
3782        egl_validation_protos += [comment] + eps.validation_protos
3783        egl_context_lock_protos += [comment] + eps.context_lock_protos
3784        libegl_windows_def_exports += [win_def_comment] + get_exports(eglxml.commands[version])
3785        egl_capture_protos += eps.capture_protos
3786        egl_capture_methods += eps.capture_methods
3787
3788    egl_decls.append("} // extern \"C\"")
3789    egl_defs.append("} // extern \"C\"")
3790
3791    write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_decls), "h",
3792               EGL_HEADER_INCLUDES, "libGLESv2", "egl.xml")
3793    write_file("egl", "EGL", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_defs), "cpp",
3794               EGL_SOURCE_INCLUDES, "libGLESv2", "egl.xml")
3795    write_stubs_header("EGL", "egl", "EGL", "egl.xml", EGL_STUBS_HEADER_PATH, eglxml.all_commands,
3796                       egl_commands, EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
3797
3798    eglxml.AddExtensionCommands(registry_xml.supported_egl_extensions, ['egl'])
3799    egl_ext_decls = ["extern \"C\" {"]
3800    egl_ext_defs = ["extern \"C\" {"]
3801    egl_ext_commands = []
3802
3803    for extension_name, ext_cmd_names in sorted(eglxml.ext_data.items()):
3804
3805        # Extensions may have no new commands.
3806        if not ext_cmd_names:
3807            continue
3808
3809        # Detect and filter duplicate extensions.
3810        eps = EGLEntryPoints(eglxml, ext_cmd_names)
3811
3812        comment = "\n// %s" % extension_name
3813        win_def_comment = "\n    ; %s" % (extension_name)
3814
3815        egl_ext_commands += ext_cmd_names
3816
3817        egl_ext_decls += [comment] + eps.decls
3818        egl_ext_defs += [comment] + eps.defs
3819        libegl_ep_defs += [comment] + eps.export_defs
3820        egl_validation_protos += [comment] + eps.validation_protos
3821        egl_context_lock_protos += [comment] + eps.context_lock_protos
3822        libegl_windows_def_exports += [win_def_comment] + get_exports(ext_cmd_names)
3823        egl_capture_protos += eps.capture_protos
3824        egl_capture_methods += eps.capture_methods
3825
3826        # Avoid writing out entry points defined by a prior extension.
3827        for dupe in eglxml.ext_dupes[extension_name]:
3828            msg = "// %s is already defined.\n" % strip_api_prefix(dupe)
3829            egl_ext_defs.append(msg)
3830
3831    egl_ext_decls.append("} // extern \"C\"")
3832    egl_ext_defs.append("} // extern \"C\"")
3833
3834    write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_HEADER, "\n".join(egl_ext_decls),
3835               "h", EGL_EXT_HEADER_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
3836    write_file("egl_ext", "EGL Extension", TEMPLATE_ENTRY_POINT_SOURCE, "\n".join(egl_ext_defs),
3837               "cpp", EGL_EXT_SOURCE_INCLUDES, "libGLESv2", "egl.xml and egl_angle_ext.xml")
3838    write_validation_header("EGL", "EGL", egl_validation_protos, "egl.xml and egl_angle_ext.xml",
3839                            TEMPLATE_EGL_VALIDATION_HEADER)
3840    write_context_lock_header("EGL", "EGL", egl_context_lock_protos,
3841                              "egl.xml and egl_angle_ext.xml", TEMPLATE_EGL_CONTEXT_LOCK_HEADER)
3842    write_stubs_header("EGL", "egl_ext", "EXT extension", "egl.xml and egl_angle_ext.xml",
3843                       EGL_EXT_STUBS_HEADER_PATH, eglxml.all_commands, egl_ext_commands,
3844                       EGLEntryPoints.get_packed_enums(), EGL_PACKED_TYPES)
3845
3846    write_capture_header(apis.EGL, 'egl', 'EGL', egl_capture_protos, [])
3847    write_capture_source(apis.EGL, 'egl', 'EGL', 'all', egl_capture_methods)
3848
3849    wglxml = registry_xml.RegistryXML('wgl.xml')
3850
3851    name_prefix = "WGL_VERSION_"
3852    version = "1_0"
3853    comment = version.replace("_", ".")
3854    feature_name = "{}{}".format(name_prefix, version)
3855    wglxml.AddCommands(feature_name, version)
3856    wgl_commands = wglxml.commands[version]
3857
3858
3859    # Other versions of these functions are used
3860    wgl_commands.remove("wglUseFontBitmaps")
3861    wgl_commands.remove("wglUseFontOutlines")
3862
3863    # Formatting for outputting to def file
3864    wgl_commands = [cmd if cmd.startswith('wgl') else 'wgl' + cmd for cmd in wgl_commands]
3865    wgl_commands = ['\n    ; WGL 1.0'] + ['    {}'.format(cmd) for cmd in wgl_commands]
3866
3867    extension_decls.append("} // extern \"C\"")
3868    extension_defs.append("} // extern \"C\"")
3869
3870    write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_HEADER,
3871               "\n".join([item for item in extension_decls]), "h", GLES_EXT_HEADER_INCLUDES,
3872               "libGLESv2", "gl.xml and gl_angle_ext.xml")
3873    write_file("gles_ext", "GLES extension", TEMPLATE_ENTRY_POINT_SOURCE,
3874               "\n".join([item for item in extension_defs]), "cpp", GLES_EXT_SOURCE_INCLUDES,
3875               "libGLESv2", "gl.xml and gl_angle_ext.xml")
3876
3877    write_gl_validation_header("ESEXT", "ES extension", ext_validation_protos,
3878                               "gl.xml and gl_angle_ext.xml")
3879    write_capture_header(apis.GLES, "gles_ext", "extension", ext_capture_protos,
3880                         ext_capture_pointer_funcs)
3881    write_capture_source(apis.GLES, "gles_ext", "ESEXT", "extension", ext_capture_methods)
3882
3883    write_context_api_decls(glesdecls, "gles")
3884    write_context_api_decls(desktop_gl_decls, "gl")
3885
3886    # Entry point enum
3887    unsorted_enums = clxml.GetEnums() + eglxml.GetEnums() + xml.GetEnums() + glxml.GetEnums(
3888    ) + wglxml.GetEnums('wgl')
3889    all_enums = [('Invalid', 'Invalid')] + sorted(list(set(unsorted_enums)))
3890
3891    entry_points_enum_header = TEMPLATE_ENTRY_POINTS_ENUM_HEADER.format(
3892        script_name=os.path.basename(sys.argv[0]),
3893        data_source_name="gl.xml and gl_angle_ext.xml",
3894        lib="GL/GLES",
3895        entry_points_list=",\n".join(["    " + enum for (enum, _) in all_enums]))
3896
3897    entry_points_enum_header_path = path_to("common", "entry_points_enum_autogen.h")
3898    with open(entry_points_enum_header_path, "w") as out:
3899        out.write(entry_points_enum_header)
3900        out.close()
3901
3902    entry_points_cases = [
3903        TEMPLATE_ENTRY_POINTS_NAME_CASE.format(enum=enum, cmd=cmd) for (enum, cmd) in all_enums
3904    ]
3905    entry_points_enum_source = TEMPLATE_ENTRY_POINTS_ENUM_SOURCE.format(
3906        script_name=os.path.basename(sys.argv[0]),
3907        data_source_name="gl.xml and gl_angle_ext.xml",
3908        lib="GL/GLES",
3909        entry_points_name_cases="\n".join(entry_points_cases))
3910
3911    entry_points_enum_source_path = path_to("common", "entry_points_enum_autogen.cpp")
3912    with open(entry_points_enum_source_path, "w") as out:
3913        out.write(entry_points_enum_source)
3914        out.close()
3915
3916    write_export_files("\n".join([item for item in libgles_ep_defs]), LIBGLESV2_EXPORT_INCLUDES,
3917                       "gl.xml and gl_angle_ext.xml", "libGLESv2", "OpenGL ES")
3918    write_export_files("\n".join([item for item in libegl_ep_defs]),
3919                       LIBEGL_EXPORT_INCLUDES_AND_PREAMBLE, "egl.xml and egl_angle_ext.xml",
3920                       "libEGL", "EGL")
3921    write_export_files("\n".join([item for item in libcl_ep_defs]), LIBCL_EXPORT_INCLUDES,
3922                       "cl.xml", "libOpenCL", "CL")
3923
3924    libgles_ep_exports += get_egl_exports()
3925
3926    everything = "Khronos and ANGLE XML files"
3927
3928    for lib in [
3929            "libGLESv2" + suffix
3930            for suffix in ["", "_no_capture", "_with_capture", "_vulkan_secondaries"]
3931    ]:
3932        write_windows_def_file(everything, lib, lib, "libGLESv2", libgles_ep_exports)
3933
3934    write_windows_def_file(everything, "opengl32_with_wgl", "opengl32", "libGLESv2",
3935                           libgl_ep_exports + sorted(wgl_commands))
3936    write_windows_def_file(everything, "opengl32", "opengl32", "libGLESv2", libgl_ep_exports)
3937
3938    for lib in ["libEGL" + suffix for suffix in ["", "_vulkan_secondaries"]]:
3939        write_windows_def_file("egl.xml and egl_angle_ext.xml", lib, lib, "libEGL",
3940                               libegl_windows_def_exports)
3941
3942    all_gles_param_types = sorted(GLEntryPoints.all_param_types)
3943    all_egl_param_types = sorted(EGLEntryPoints.all_param_types)
3944    resource_id_types = get_resource_id_types(GLEntryPoints.all_param_types)
3945    # Get a sorted list of param types without duplicates
3946    all_param_types = sorted(list(set(all_gles_param_types + all_egl_param_types)))
3947    write_capture_helper_header(all_param_types)
3948    write_capture_helper_source(all_param_types)
3949    write_capture_replay_source(xml.all_commands, all_commands_with_suffix,
3950                                GLEntryPoints.get_packed_enums(), eglxml.all_commands,
3951                                egl_commands, EGLEntryPoints.get_packed_enums(), resource_id_types)
3952
3953
3954if __name__ == '__main__':
3955    sys.exit(main())
3956