• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3
2#
3# Copyright 2013-2020 The Khronos Group Inc.
4# SPDX-License-Identifier: Apache-2.0
5
6import sys, time, pdb, string, cProfile
7from reg import *
8
9# debug - start header generation in debugger
10# dump - dump registry after loading
11# profile - enable Python profiling
12# protect - whether to use #ifndef protections
13# registry <filename> - use specified XML registry instead of gl.xml
14# target - string name of target header, or all targets if None
15# timeit - time length of registry loading & header generation
16# validate - validate return & parameter group tags against <group>
17debug   = False
18dump    = False
19profile = False
20protect = True
21target  = None
22timeit  = False
23validate= False
24# Default input / log files
25errFilename = None
26diagFilename = 'diag.txt'
27regFilename = 'gl.xml'
28
29# Simple timer functions
30startTime = None
31def startTimer():
32    global startTime
33    startTime = time.process_time()
34def endTimer(msg):
35    global startTime
36    endTime = time.process_time()
37    if (timeit):
38        write(msg, endTime - startTime)
39        startTime = None
40
41# Turn a list of strings into a regexp string matching exactly those strings
42def makeREstring(list):
43    return '^(' + '|'.join(list) + ')$'
44
45# These are "mandatory" OpenGL ES 1 extensions, to
46# be included in the core GLES/gl.h header.
47es1CoreList = [
48    'GL_OES_read_format',
49    'GL_OES_compressed_paletted_texture',
50    'GL_OES_point_size_array',
51    'GL_OES_point_sprite'
52]
53
54# Descriptive names for various regexp patterns used to select
55# versions and extensions
56
57allVersions       = allExtensions = '.*'
58noVersions        = noExtensions = None
59gl12andLaterPat   = '1\.[2-9]|[234]\.[0-9]'
60gles2onlyPat      = '2\.[0-9]'
61gles2through30Pat = '2\.[0-9]|3\.0'
62gles2through31Pat = '2\.[0-9]|3\.[01]'
63gles2through32Pat = '2\.[0-9]|3\.[012]'
64es1CorePat        = makeREstring(es1CoreList)
65# Extensions in old glcorearb.h but not yet tagged accordingly in gl.xml
66glCoreARBPat      = None
67glx13andLaterPat  = '1\.[3-9]'
68
69# Copyright text prefixing all headers (list of strings).
70prefixStrings = [
71    '/*',
72    '** Copyright 2013-2020 The Khronos Group Inc.',
73    '** SPDX-' + 'License-Identifier: MIT',
74    '**',
75    '** This header is generated from the Khronos OpenGL / OpenGL ES XML',
76    '** API Registry. The current version of the Registry, generator scripts',
77    '** used to make the header, and the header can be found at',
78    '**   https://github.com/KhronosGroup/OpenGL-Registry',
79    '*/',
80    ''
81]
82
83# glext.h / glcorearb.h define calling conventions inline (no GL *platform.h)
84glExtPlatformStrings = [
85    '#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)',
86    '#ifndef WIN32_LEAN_AND_MEAN',
87    '#define WIN32_LEAN_AND_MEAN 1',
88    '#endif',
89    '#include <windows.h>',
90    '#endif',
91    '',
92    '#ifndef APIENTRY',
93    '#define APIENTRY',
94    '#endif',
95    '#ifndef APIENTRYP',
96    '#define APIENTRYP APIENTRY *',
97    '#endif',
98    '#ifndef GLAPI',
99    '#define GLAPI extern',
100    '#endif',
101    ''
102]
103
104glCorearbPlatformStrings = glExtPlatformStrings + [
105    '/* glcorearb.h is for use with OpenGL core profile implementations.',
106    '** It should should be placed in the same directory as gl.h and',
107    '** included as <GL/glcorearb.h>.',
108    '**',
109    '** glcorearb.h includes only APIs in the latest OpenGL core profile',
110    '** implementation together with APIs in newer ARB extensions which ',
111    '** can be supported by the core profile. It does not, and never will',
112    '** include functionality removed from the core profile, such as',
113    '** fixed-function vertex and fragment processing.',
114    '**',
115    '** Do not #include both <GL/glcorearb.h> and either of <GL/gl.h> or',
116    '** <GL/glext.h> in the same source file.',
117    '*/',
118    ''
119]
120
121# wglext.h needs Windows include
122wglPlatformStrings = [
123    '#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)',
124    '#define WIN32_LEAN_AND_MEAN 1',
125    '#include <windows.h>',
126    '#endif',
127    '',
128]
129
130# Different APIs use different *platform.h files to define calling
131# conventions
132gles1PlatformStrings = [ '#include <GLES/glplatform.h>', '' ]
133gles2PlatformStrings = [ '#include <GLES2/gl2platform.h>', '' ]
134gles3PlatformStrings = [ '#include <GLES3/gl3platform.h>', '' ]
135glsc2PlatformStrings = [ '#include <GLSC2/gl2platform.h>', '' ]
136eglPlatformStrings   = [ '#include <EGL/eglplatform.h>', '' ]
137
138# GLES headers have a small addition to calling convention headers for function pointer typedefs
139apiEntryPrefixStrings = [
140    '#ifndef GL_APIENTRYP',
141    '#define GL_APIENTRYP GL_APIENTRY*',
142    '#endif',
143    ''
144]
145
146# GLES 2/3 core API headers use a different protection mechanism for
147# prototypes, per bug 14206.
148glesProtoPrefixStrings = [
149    '#ifndef GL_GLES_PROTOTYPES',
150    '#define GL_GLES_PROTOTYPES 1',
151    '#endif',
152    ''
153]
154
155# Insert generation date in a comment for headers not having *GLEXT_VERSION macros
156genDateCommentString = [
157    format('/* Generated on date %s */' % time.strftime('%Y%m%d')),
158    ''
159]
160
161# GL_GLEXT_VERSION is defined only in glext.h
162glextVersionStrings = [
163    format('#define GL_GLEXT_VERSION %s' % time.strftime('%Y%m%d')),
164    ''
165]
166# WGL_WGLEXT_VERSION is defined only in wglext.h
167wglextVersionStrings = [
168    format('#define WGL_WGLEXT_VERSION %s' % time.strftime('%Y%m%d')),
169    ''
170]
171# GLX_GLXEXT_VERSION is defined only in glxext.h
172glxextVersionStrings = [
173    format('#define GLX_GLXEXT_VERSION %s' % time.strftime('%Y%m%d')),
174    ''
175]
176# This is a bad but functional workaround for a structural problem in the scripts
177# identified in https://github.com/KhronosGroup/OpenGL-Registry/pull/186#issuecomment-416196246
178glextKHRplatformStrings = [
179    '#include <KHR/khrplatform.h>',
180    ''
181]
182# EGL_EGLEXT_VERSION is defined only in eglext.h
183eglextVersionStrings = [
184    format('#define EGL_EGLEXT_VERSION %s' % time.strftime('%Y%m%d')),
185    ''
186]
187
188# Defaults for generating re-inclusion protection wrappers (or not)
189protectFile = protect
190protectFeature = protect
191protectProto = protect
192
193buildList = [
194    # GL API 1.2+ + extensions - GL/glext.h
195    CGeneratorOptions(
196        filename          = '../api/GL/glext.h',
197        apiname           = 'gl',
198        profile           = 'compatibility',
199        versions          = allVersions,
200        emitversions      = gl12andLaterPat,
201        defaultExtensions = 'gl',                   # Default extensions for GL
202        addExtensions     = None,
203        removeExtensions  = None,
204        prefixText        = prefixStrings + glExtPlatformStrings + glextVersionStrings + glextKHRplatformStrings,
205        genFuncPointers   = True,
206        protectFile       = protectFile,
207        protectFeature    = protectFeature,
208        protectProto      = protectProto,
209        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
210        apicall           = 'GLAPI ',
211        apientry          = 'APIENTRY ',
212        apientryp         = 'APIENTRYP '),
213    # GL core profile + extensions - GL/glcorearb.h
214    CGeneratorOptions(
215        filename          = '../api/GL/glcorearb.h',
216        apiname           = 'gl',
217        profile           = 'core',
218        versions          = allVersions,
219        emitversions      = allVersions,
220        defaultExtensions = 'glcore',               # Default extensions for GL core profile (only)
221        addExtensions     = glCoreARBPat,
222        removeExtensions  = None,
223        prefixText        = prefixStrings + glCorearbPlatformStrings,
224        genFuncPointers   = True,
225        protectFile       = protectFile,
226        protectFeature    = protectFeature,
227        protectProto      = protectProto,
228        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
229        apicall           = 'GLAPI ',
230        apientry          = 'APIENTRY ',
231        apientryp         = 'APIENTRYP '),
232    # GLES 1.x API + mandatory extensions - GLES/gl.h (no function pointers)
233    CGeneratorOptions(
234        filename          = '../api/GLES/gl.h',
235        apiname           = 'gles1',
236        profile           = 'common',
237        versions          = allVersions,
238        emitversions      = allVersions,
239        defaultExtensions = None,                   # No default extensions
240        addExtensions     = es1CorePat,             # Add mandatory ES1 extensions in GLES1/gl.h
241        removeExtensions  = None,
242        prefixText        = prefixStrings + gles1PlatformStrings + genDateCommentString,
243        genFuncPointers   = False,
244        protectFile       = protectFile,
245        protectFeature    = protectFeature,
246        protectProto      = False,                  # Core ES API functions are in the static link libraries
247        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
248        apicall           = 'GL_API ',
249        apientry          = 'GL_APIENTRY ',
250        apientryp         = 'GL_APIENTRYP '),
251    # GLES 1.x extensions - GLES/glext.h
252    CGeneratorOptions(
253        filename          = '../api/GLES/glext.h',
254        apiname           = 'gles1',
255        profile           = 'common',
256        versions          = allVersions,
257        emitversions      = noVersions,
258        defaultExtensions = 'gles1',                # Default extensions for GLES 1
259        addExtensions     = None,
260        removeExtensions  = es1CorePat,             # Remove mandatory ES1 extensions in GLES1/glext.h
261        prefixText        = prefixStrings + apiEntryPrefixStrings + genDateCommentString,
262        genFuncPointers   = True,
263        protectFile       = protectFile,
264        protectFeature    = protectFeature,
265        protectProto      = protectProto,
266        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
267        apicall           = 'GL_API ',
268        apientry          = 'GL_APIENTRY ',
269        apientryp         = 'GL_APIENTRYP '),
270    # GLES 2.0 API - GLES2/gl2.h (now with function pointers)
271    CGeneratorOptions(
272        filename          = '../api/GLES2/gl2.h',
273        apiname           = 'gles2',
274        profile           = 'common',
275        versions          = gles2onlyPat,
276        emitversions      = allVersions,
277        defaultExtensions = None,                   # No default extensions
278        addExtensions     = None,
279        removeExtensions  = None,
280        prefixText        = prefixStrings + gles2PlatformStrings + apiEntryPrefixStrings + glesProtoPrefixStrings + genDateCommentString,
281        genFuncPointers   = True,
282        protectFile       = protectFile,
283        protectFeature    = protectFeature,
284        protectProto      = 'nonzero',              # Core ES API functions are in the static link libraries
285        protectProtoStr   = 'GL_GLES_PROTOTYPES',
286        apicall           = 'GL_APICALL ',
287        apientry          = 'GL_APIENTRY ',
288        apientryp         = 'GL_APIENTRYP '),
289    # GLES 3.1 / 3.0 / 2.0 extensions - GLES2/gl2ext.h
290    CGeneratorOptions(
291        filename          = '../api/GLES2/gl2ext.h',
292        apiname           = 'gles2',
293        profile           = 'common',
294        versions          = gles2onlyPat,
295        emitversions      = None,
296        defaultExtensions = 'gles2',                # Default extensions for GLES 2
297        addExtensions     = None,
298        removeExtensions  = None,
299        prefixText        = prefixStrings + apiEntryPrefixStrings + genDateCommentString,
300        genFuncPointers   = True,
301        protectFile       = protectFile,
302        protectFeature    = protectFeature,
303        protectProto      = protectProto,
304        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
305        apicall           = 'GL_APICALL ',
306        apientry          = 'GL_APIENTRY ',
307        apientryp         = 'GL_APIENTRYP '),
308    # GLES 3.2 API - GLES3/gl32.h (now with function pointers)
309    CGeneratorOptions(
310        filename          = '../api/GLES3/gl32.h',
311        apiname           = 'gles2',
312        profile           = 'common',
313        versions          = gles2through32Pat,
314        emitversions      = allVersions,
315        defaultExtensions = None,                   # No default extensions
316        addExtensions     = None,
317        removeExtensions  = None,
318        prefixText        = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + glesProtoPrefixStrings + genDateCommentString,
319        genFuncPointers   = True,
320        protectFile       = protectFile,
321        protectFeature    = protectFeature,
322        protectProto      = 'nonzero',              # Core ES API functions are in the static link libraries
323        protectProtoStr   = 'GL_GLES_PROTOTYPES',
324        apicall           = 'GL_APICALL ',
325        apientry          = 'GL_APIENTRY ',
326        apientryp         = 'GL_APIENTRYP '),
327    # GLES 3.1 API - GLES3/gl31.h (now with function pointers)
328    CGeneratorOptions(
329        filename          = '../api/GLES3/gl31.h',
330        apiname           = 'gles2',
331        profile           = 'common',
332        versions          = gles2through31Pat,
333        emitversions      = allVersions,
334        defaultExtensions = None,                   # No default extensions
335        addExtensions     = None,
336        removeExtensions  = None,
337        prefixText        = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + glesProtoPrefixStrings + genDateCommentString,
338        genFuncPointers   = True,
339        protectFile       = protectFile,
340        protectFeature    = protectFeature,
341        protectProto      = 'nonzero',              # Core ES API functions are in the static link libraries
342        protectProtoStr   = 'GL_GLES_PROTOTYPES',
343        apicall           = 'GL_APICALL ',
344        apientry          = 'GL_APIENTRY ',
345        apientryp         = 'GL_APIENTRYP '),
346    # GLES 3.0 API - GLES3/gl3.h (now with function pointers)
347    CGeneratorOptions(
348        filename          = '../api/GLES3/gl3.h',
349        apiname           = 'gles2',
350        profile           = 'common',
351        versions          = gles2through30Pat,
352        emitversions      = allVersions,
353        defaultExtensions = None,                   # No default extensions
354        addExtensions     = None,
355        removeExtensions  = None,
356        prefixText        = prefixStrings + gles3PlatformStrings + apiEntryPrefixStrings + glesProtoPrefixStrings + genDateCommentString,
357        genFuncPointers   = True,
358        protectFile       = protectFile,
359        protectFeature    = protectFeature,
360        protectProto      = 'nonzero',              # Core ES API functions are in the static link libraries
361        protectProtoStr   = 'GL_GLES_PROTOTYPES',
362        apicall           = 'GL_APICALL ',
363        apientry          = 'GL_APIENTRY ',
364        apientryp         = 'GL_APIENTRYP '),
365    # GLSC 2.0 API - GLSC2/glsc2.h
366    CGeneratorOptions(
367        filename          = '../api/GLSC2/glsc2.h',
368        apiname           = 'glsc2',
369        profile           = 'common',
370        versions          = gles2onlyPat,
371        emitversions      = allVersions,
372        defaultExtensions = None,                   # No default extensions
373        addExtensions     = None,
374        removeExtensions  = None,
375        prefixText        = prefixStrings + glsc2PlatformStrings + apiEntryPrefixStrings + genDateCommentString,
376        genFuncPointers   = False,
377        protectFile       = protectFile,
378        protectFeature    = protectFeature,
379        protectProto      = False,
380        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
381        apicall           = 'GL_APICALL ',
382        apientry          = 'GL_APIENTRY ',
383        apientryp         = 'GL_APIENTRYP '),
384    # GLSC 2.0 extensions - GLSC2/gl2ext.h
385    CGeneratorOptions(
386        filename          = '../api/GLSC2/glsc2ext.h',
387        apiname           = 'glsc2',
388        profile           = 'common',
389        versions          = gles2onlyPat,
390        emitversions      = None,
391        defaultExtensions = 'glsc2',                # Default extensions for GLSC 2
392        addExtensions     = None,
393        removeExtensions  = None,
394        prefixText        = prefixStrings + apiEntryPrefixStrings + genDateCommentString,
395        genFuncPointers   = False,
396        protectFile       = protectFile,
397        protectFeature    = protectFeature,
398        protectProto      = False,
399        protectProtoStr   = 'GL_GLEXT_PROTOTYPES',
400        apicall           = 'GL_APICALL ',
401        apientry          = 'GL_APIENTRY ',
402        apientryp         = 'GL_APIENTRYP '),
403    # GLX 1.* API - GL/glx.h (experimental)
404    CGeneratorOptions(
405        filename          = '../api/GL/glx.h',
406        apiname           = 'glx',
407        profile           = None,
408        versions          = allVersions,
409        emitversions      = allVersions,
410        defaultExtensions = None,                   # No default extensions
411        addExtensions     = None,
412        removeExtensions  = None,
413        # add glXPlatformStrings?
414        prefixText        = prefixStrings + genDateCommentString,
415        genFuncPointers   = True,
416        protectFile       = protectFile,
417        protectFeature    = protectFeature,
418        protectProto      = protectProto,
419        protectProtoStr   = 'GLX_GLXEXT_PROTOTYPES',
420        apicall           = '',
421        apientry          = '',
422        apientryp         = ' *'),
423    # GLX 1.3+ API + extensions - GL/glxext.h (no function pointers, yet @@@)
424    CGeneratorOptions(
425        filename          = '../api/GL/glxext.h',
426        apiname           = 'glx',
427        profile           = None,
428        versions          = allVersions,
429        emitversions      = glx13andLaterPat,
430        defaultExtensions = 'glx',                  # Default extensions for GLX
431        addExtensions     = None,
432        removeExtensions  = None,
433        # add glXPlatformStrings?
434        prefixText        = prefixStrings + glxextVersionStrings,
435        genFuncPointers   = True,
436        protectFile       = protectFile,
437        protectFeature    = protectFeature,
438        protectProto      = protectProto,
439        protectProtoStr   = 'GLX_GLXEXT_PROTOTYPES',
440        apicall           = '',
441        apientry          = '',
442        apientryp         = ' *'),
443    # WGL API + extensions - GL/wgl.h (experimenta; no function pointers, yet @@@)
444    CGeneratorOptions(
445        filename          = '../api/GL/wgl.h',
446        apiname           = 'wgl',
447        profile           = None,
448        versions          = allVersions,
449        emitversions      = allVersions,
450        defaultExtensions = 'wgl',                  # Default extensions for WGL
451        addExtensions     = None,
452        removeExtensions  = None,
453        prefixText        = prefixStrings + wglPlatformStrings + genDateCommentString,
454        genFuncPointers   = True,
455        protectFile       = protectFile,
456        protectFeature    = protectFeature,
457        protectProto      = protectProto,
458        protectProtoStr   = 'WGL_WGLEXT_PROTOTYPES',
459        apicall           = '',
460        apientry          = 'WINAPI ',
461        apientryp         = 'WINAPI * '),
462    # WGL extensions - GL/wglext.h (no function pointers, yet @@@)
463    CGeneratorOptions(
464        filename          = '../api/GL/wglext.h',
465        apiname           = 'wgl',
466        profile           = None,
467        versions          = allVersions,
468        emitversions      = None,
469        defaultExtensions = 'wgl',                  # Default extensions for WGL
470        addExtensions     = None,
471        removeExtensions  = None,
472        prefixText        = prefixStrings + wglPlatformStrings + wglextVersionStrings,
473        genFuncPointers   = True,
474        protectFile       = protectFile,
475        protectFeature    = protectFeature,
476        protectProto      = protectProto,
477        protectProtoStr   = 'WGL_WGLEXT_PROTOTYPES',
478        apicall           = '',
479        apientry          = 'WINAPI ',
480        apientryp         = 'WINAPI * '),
481    # End of list
482    None
483]
484
485def genHeaders():
486    # Loop over targets, building each
487    generated = 0
488    for genOpts in buildList:
489        if (genOpts == None):
490            break
491        if (target and target != genOpts.filename):
492            # write('*** Skipping', genOpts.filename)
493            continue
494        write('*** Building', genOpts.filename)
495        generated = generated + 1
496        startTimer()
497        gen = COutputGenerator(errFile=errWarn,
498                               warnFile=errWarn,
499                               diagFile=diag)
500        reg.setGenerator(gen)
501        reg.apiGen(genOpts)
502        write('** Generated', genOpts.filename)
503        endTimer('Time to generate ' + genOpts.filename + ' =')
504    if (target and generated == 0):
505        write('Failed to generate target:', target)
506
507
508if __name__ == '__main__':
509    i = 1
510    while (i < len(sys.argv)):
511        arg = sys.argv[i]
512        i = i + 1
513        if (arg == '-debug'):
514            write('Enabling debug (-debug)', file=sys.stderr)
515            debug = True
516        elif (arg == '-dump'):
517            write('Enabling dump (-dump)', file=sys.stderr)
518            dump = True
519        elif (arg == '-noprotect'):
520            write('Disabling inclusion protection in output headers', file=sys.stderr)
521            protect = False
522        elif (arg == '-profile'):
523            write('Enabling profiling (-profile)', file=sys.stderr)
524            profile = True
525        elif (arg == '-registry'):
526            regFilename = sys.argv[i]
527            i = i+1
528            write('Using registry ', regFilename, file=sys.stderr)
529        elif (arg == '-time'):
530            write('Enabling timing (-time)', file=sys.stderr)
531            timeit = True
532        elif (arg == '-validate'):
533            write('Enabling group validation (-validate)', file=sys.stderr)
534            validate = True
535        elif (arg[0:1] == '-'):
536            write('Unrecognized argument:', arg, file=sys.stderr)
537            exit(1)
538        else:
539            target = arg
540            write('Using target', target, file=sys.stderr)
541
542    # Load & parse registry
543    reg = Registry()
544
545    startTimer()
546    tree = etree.parse(regFilename)
547    endTimer('Time to make ElementTree =')
548
549    startTimer()
550    reg.loadElementTree(tree)
551    endTimer('Time to parse ElementTree =')
552
553    if (validate):
554        reg.validateGroups()
555
556    if (dump):
557        write('***************************************')
558        write('Performing Registry dump to regdump.txt')
559        write('***************************************')
560        reg.dumpReg(filehandle = open('regdump.txt','w'))
561
562    # create error/warning & diagnostic files
563    if (errFilename):
564        errWarn = open(errFilename,'w')
565    else:
566        errWarn = sys.stderr
567    diag = open(diagFilename, 'w')
568
569    if (debug):
570        pdb.run('genHeaders()')
571    elif (profile):
572        import cProfile, pstats
573        cProfile.run('genHeaders()', 'profile.txt')
574        p = pstats.Stats('profile.txt')
575        p.strip_dirs().sort_stats('time').print_stats(50)
576    else:
577        genHeaders()
578