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