17ec681f3Smrg#!/usr/bin/env python3
27ec681f3Smrg
37ec681f3Smrgimport argparse
47ec681f3Smrgimport base64
57ec681f3Smrgimport pathlib
67ec681f3Smrgimport requests
77ec681f3Smrgimport subprocess
87ec681f3Smrgimport typing
97ec681f3Smrg
107ec681f3Smrg
117ec681f3Smrgdef error(msg: str) -> None:
127ec681f3Smrg    print('\033[31m' + msg + '\033[0m')
137ec681f3Smrg
147ec681f3Smrg
157ec681f3Smrgclass Source:
167ec681f3Smrg    def __init__(self, filename: str, url: typing.Optional[str]):
177ec681f3Smrg        self.file = pathlib.Path(filename)
187ec681f3Smrg        self.url = url
197ec681f3Smrg
207ec681f3Smrg    def sync(self) -> None:
217ec681f3Smrg        if self.url is None:
227ec681f3Smrg            return
237ec681f3Smrg
247ec681f3Smrg        print('Syncing {}...'.format(self.file), end=' ', flush=True)
257ec681f3Smrg        req = requests.get(self.url)
267ec681f3Smrg
277ec681f3Smrg        if not req.ok:
287ec681f3Smrg            error('Failed to retrieve file: {} {}'.format(req.status_code, req.reason))
297ec681f3Smrg            return
307ec681f3Smrg
317ec681f3Smrg        # Gitiles returns base64-encoded strings.
327ec681f3Smrg        # Google has been resisting for years to the idea of allowing plain text: https://github.com/google/gitiles/issues/7
337ec681f3Smrg        if 'format=TEXT' in self.url:
347ec681f3Smrg            content = base64.b64decode(req.content)
357ec681f3Smrg        else:
367ec681f3Smrg            content = req.content
377ec681f3Smrg
387ec681f3Smrg        with open(self.file, 'wb') as f:
397ec681f3Smrg            f.write(content)
407ec681f3Smrg
417ec681f3Smrg        print('Done')
427ec681f3Smrg
437ec681f3Smrg
447ec681f3Smrg# a URL of `None` means there is no upstream, because *we* are the upstream
457ec681f3SmrgSOURCES = [
467ec681f3Smrg    {
477ec681f3Smrg        'api': 'khr',
487ec681f3Smrg        'inc_folder': 'KHR',
497ec681f3Smrg        'sources': [
507ec681f3Smrg            Source('include/KHR/khrplatform.h',    'https://github.com/KhronosGroup/EGL-Registry/raw/main/api/KHR/khrplatform.h'),
517ec681f3Smrg        ],
527ec681f3Smrg    },
537ec681f3Smrg
547ec681f3Smrg    {
557ec681f3Smrg        'api': 'egl',
567ec681f3Smrg        'inc_folder': 'EGL',
577ec681f3Smrg        'sources': [
587ec681f3Smrg            Source('src/egl/generate/egl.xml',     'https://github.com/KhronosGroup/EGL-Registry/raw/main/api/egl.xml'),
597ec681f3Smrg            Source('include/EGL/egl.h',            'https://github.com/KhronosGroup/EGL-Registry/raw/main/api/EGL/egl.h'),
607ec681f3Smrg            Source('include/EGL/eglplatform.h',    'https://github.com/KhronosGroup/EGL-Registry/raw/main/api/EGL/eglplatform.h'),
617ec681f3Smrg            Source('include/EGL/eglext.h',         'https://github.com/KhronosGroup/EGL-Registry/raw/main/api/EGL/eglext.h'),
627ec681f3Smrg            Source('include/EGL/eglextchromium.h', 'https://chromium.googlesource.com/chromium/src/+/refs/heads/master/ui/gl/EGL/eglextchromium.h?format=TEXT'),
637ec681f3Smrg            Source('include/EGL/eglext_angle.h',   'https://chromium.googlesource.com/angle/angle/+/refs/heads/master/include/EGL/eglext_angle.h?format=TEXT'),
647ec681f3Smrg            Source('include/EGL/eglmesaext.h',     None),
657ec681f3Smrg        ],
667ec681f3Smrg    },
677ec681f3Smrg
687ec681f3Smrg    {
697ec681f3Smrg        'api': 'gl',
707ec681f3Smrg        'inc_folder': 'GL',
717ec681f3Smrg        'sources': [
727ec681f3Smrg            Source('src/mapi/glapi/registry/gl.xml', 'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/xml/gl.xml'),
737ec681f3Smrg            Source('include/GL/glcorearb.h',         'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GL/glcorearb.h'),
747ec681f3Smrg            Source('include/GL/glext.h',             'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GL/glext.h'),
757ec681f3Smrg            Source('include/GL/glxext.h',            'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GL/glxext.h'),
767ec681f3Smrg            Source('include/GL/wglext.h',            'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GL/wglext.h'),
777ec681f3Smrg            Source('include/GL/gl.h',                None),  # FIXME: I don't know what the canonical source is
787ec681f3Smrg            Source('include/GL/glx.h',               None),  # FIXME: I don't know what the canonical source is
797ec681f3Smrg            Source('include/GL/internal/',           None),
807ec681f3Smrg            Source('include/GL/mesa_glinterop.h',    None),
817ec681f3Smrg            Source('include/GL/osmesa.h',            None),
827ec681f3Smrg        ],
837ec681f3Smrg    },
847ec681f3Smrg
857ec681f3Smrg    {
867ec681f3Smrg        'api': 'gles1',
877ec681f3Smrg        'inc_folder': 'GLES',
887ec681f3Smrg        'sources': [
897ec681f3Smrg            Source('include/GLES/gl.h',         'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES/gl.h'),
907ec681f3Smrg            Source('include/GLES/glplatform.h', 'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES/glplatform.h'),
917ec681f3Smrg            Source('include/GLES/glext.h',      'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES/glext.h'),
927ec681f3Smrg            Source('include/GLES/egl.h',        'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES/egl.h'),
937ec681f3Smrg        ],
947ec681f3Smrg    },
957ec681f3Smrg
967ec681f3Smrg    {
977ec681f3Smrg        'api': 'gles2',
987ec681f3Smrg        'inc_folder': 'GLES2',
997ec681f3Smrg        'sources': [
1007ec681f3Smrg            Source('include/GLES2/gl2.h',         'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES2/gl2.h'),
1017ec681f3Smrg            Source('include/GLES2/gl2platform.h', 'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES2/gl2platform.h'),
1027ec681f3Smrg            Source('include/GLES2/gl2ext.h',      'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES2/gl2ext.h'),
1037ec681f3Smrg        ],
1047ec681f3Smrg    },
1057ec681f3Smrg
1067ec681f3Smrg    {
1077ec681f3Smrg        'api': 'gles3',
1087ec681f3Smrg        'inc_folder': 'GLES3',
1097ec681f3Smrg        'sources': [
1107ec681f3Smrg            Source('include/GLES3/gl3.h',         'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES3/gl3.h'),
1117ec681f3Smrg            Source('include/GLES3/gl31.h',        'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES3/gl31.h'),
1127ec681f3Smrg            Source('include/GLES3/gl32.h',        'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES3/gl32.h'),
1137ec681f3Smrg            Source('include/GLES3/gl3platform.h', 'https://github.com/KhronosGroup/OpenGL-Registry/raw/main/api/GLES3/gl3platform.h'),
1147ec681f3Smrg            Source('include/GLES3/gl3ext.h',      None),  # FIXME: I don't know what the canonical source is
1157ec681f3Smrg        ],
1167ec681f3Smrg    },
1177ec681f3Smrg
1187ec681f3Smrg    {
1197ec681f3Smrg        'api': 'opencl',
1207ec681f3Smrg        'inc_folder': 'CL',
1217ec681f3Smrg        'sources': [
1227ec681f3Smrg            Source('include/CL/opencl.h',                        'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/opencl.h'),
1237ec681f3Smrg            Source('include/CL/cl.h',                            'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl.h'),
1247ec681f3Smrg            Source('include/CL/cl_platform.h',                   'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_platform.h'),
1257ec681f3Smrg            Source('include/CL/cl_gl.h',                         'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_gl.h'),
1267ec681f3Smrg            Source('include/CL/cl_gl_ext.h',                     'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_gl_ext.h'),
1277ec681f3Smrg            Source('include/CL/cl_ext.h',                        'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_ext.h'),
1287ec681f3Smrg            Source('include/CL/cl_version.h',                    'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_version.h'),
1297ec681f3Smrg            Source('include/CL/cl_icd.h',                        'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_icd.h'),
1307ec681f3Smrg            Source('include/CL/cl_egl.h',                        'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_egl.h'),
1317ec681f3Smrg            Source('include/CL/cl_d3d10.h',                      'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_d3d10.h'),
1327ec681f3Smrg            Source('include/CL/cl_d3d11.h',                      'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_d3d11.h'),
1337ec681f3Smrg            Source('include/CL/cl_dx9_media_sharing.h',          'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_dx9_media_sharing.h'),
1347ec681f3Smrg            Source('include/CL/cl_dx9_media_sharing_intel.h',    'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_dx9_media_sharing_intel.h'),
1357ec681f3Smrg            Source('include/CL/cl_ext_intel.h',                  'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_ext_intel.h'),
1367ec681f3Smrg            Source('include/CL/cl_va_api_media_sharing_intel.h', 'https://github.com/KhronosGroup/OpenCL-Headers/raw/master/CL/cl_va_api_media_sharing_intel.h'),
1377ec681f3Smrg
1387ec681f3Smrg            Source('include/CL/cl.hpp',                          'https://github.com/KhronosGroup/OpenCL-CLHPP/raw/master/include/CL/cl.hpp'),
1397ec681f3Smrg            Source('include/CL/cl2.hpp',                         'https://github.com/KhronosGroup/OpenCL-CLHPP/raw/master/include/CL/cl2.hpp'),
1407ec681f3Smrg        ],
1417ec681f3Smrg    },
1427ec681f3Smrg
1437ec681f3Smrg    {
1447ec681f3Smrg        'api': 'spirv',
1457ec681f3Smrg        'sources': [
1467ec681f3Smrg            Source('src/compiler/spirv/spirv.h',                    'https://github.com/KhronosGroup/SPIRV-Headers/raw/master/include/spirv/unified1/spirv.h'),
1477ec681f3Smrg            Source('src/compiler/spirv/spirv.core.grammar.json',    'https://github.com/KhronosGroup/SPIRV-Headers/raw/master/include/spirv/unified1/spirv.core.grammar.json'),
1487ec681f3Smrg            Source('src/compiler/spirv/OpenCL.std.h',               'https://github.com/KhronosGroup/SPIRV-Headers/raw/master/include/spirv/unified1/OpenCL.std.h'),
1497ec681f3Smrg            Source('src/compiler/spirv/GLSL.std.450.h',             'https://github.com/KhronosGroup/SPIRV-Headers/raw/master/include/spirv/unified1/GLSL.std.450.h'),
1507ec681f3Smrg            Source('src/compiler/spirv/GLSL.ext.AMD.h',             'https://github.com/KhronosGroup/glslang/raw/master/SPIRV/GLSL.ext.AMD.h'),  # FIXME: is this the canonical source?
1517ec681f3Smrg        ],
1527ec681f3Smrg    },
1537ec681f3Smrg
1547ec681f3Smrg    {
1557ec681f3Smrg        'api': 'vulkan',
1567ec681f3Smrg        'inc_folder': 'vulkan',
1577ec681f3Smrg        'sources': [
1587ec681f3Smrg            Source('src/vulkan/registry/vk.xml',                'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/registry/vk.xml'),
1597ec681f3Smrg            Source('include/vulkan/vulkan.h',                   'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan.h'),
1607ec681f3Smrg            Source('include/vulkan/vulkan_core.h',              'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_core.h'),
1617ec681f3Smrg            Source('include/vulkan/vulkan_beta.h',              'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_beta.h'),
1627ec681f3Smrg            Source('include/vulkan/vk_icd.h',                   'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vk_icd.h'),
1637ec681f3Smrg            Source('include/vulkan/vk_layer.h',                 'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vk_layer.h'),
1647ec681f3Smrg            Source('include/vulkan/vk_platform.h',              'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vk_platform.h'),
1657ec681f3Smrg            Source('include/vulkan/vulkan_android.h',           'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_android.h'),
1667ec681f3Smrg            Source('include/vulkan/vulkan_directfb.h',          'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_directfb.h'),
1677ec681f3Smrg            Source('include/vulkan/vulkan_fuchsia.h',           'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_fuchsia.h'),
1687ec681f3Smrg            Source('include/vulkan/vulkan_ggp.h',               'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_ggp.h'),
1697ec681f3Smrg            Source('include/vulkan/vulkan_ios.h',               'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_ios.h'),
1707ec681f3Smrg            Source('include/vulkan/vulkan_macos.h',             'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_macos.h'),
1717ec681f3Smrg            Source('include/vulkan/vulkan_metal.h',             'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_metal.h'),
1727ec681f3Smrg            Source('include/vulkan/vulkan_screen.h',            'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_screen.h'),
1737ec681f3Smrg            Source('include/vulkan/vulkan_vi.h',                'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_vi.h'),
1747ec681f3Smrg            Source('include/vulkan/vulkan_wayland.h',           'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_wayland.h'),
1757ec681f3Smrg            Source('include/vulkan/vulkan_win32.h',             'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_win32.h'),
1767ec681f3Smrg            Source('include/vulkan/vulkan_xcb.h',               'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_xcb.h'),
1777ec681f3Smrg            Source('include/vulkan/vulkan_xlib.h',              'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_xlib.h'),
1787ec681f3Smrg            Source('include/vulkan/vulkan_xlib_xrandr.h',       'https://github.com/KhronosGroup/Vulkan-Headers/raw/main/include/vulkan/vulkan_xlib_xrandr.h'),
1797ec681f3Smrg            Source('include/vulkan/vk_android_native_buffer.h', 'https://android.googlesource.com/platform/frameworks/native/+/master/vulkan/include/vulkan/vk_android_native_buffer.h?format=TEXT'),
1807ec681f3Smrg            Source('include/vulkan/.editorconfig',              None),
1817ec681f3Smrg        ],
1827ec681f3Smrg    },
1837ec681f3Smrg]
1847ec681f3Smrg
1857ec681f3Smrg
1867ec681f3Smrgif __name__ == '__main__':
1877ec681f3Smrg    git_toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel'],
1887ec681f3Smrg                                           stderr=subprocess.DEVNULL).decode("ascii").strip()
1897ec681f3Smrg    if not pathlib.Path(git_toplevel).resolve() == pathlib.Path('.').resolve():
1907ec681f3Smrg        error('Please run this script from the root folder ({})'.format(git_toplevel))
1917ec681f3Smrg        exit(1)
1927ec681f3Smrg
1937ec681f3Smrg    parser = argparse.ArgumentParser()
1947ec681f3Smrg    parser.add_argument('apis', nargs='*',
1957ec681f3Smrg                        # the `[[]]` here is a workaround for python bug 9625
1967ec681f3Smrg                        # where having `choices` breaks `nargs='*'`:
1977ec681f3Smrg                        # https://bugs.python.org/issue9625
1987ec681f3Smrg                        choices=[group['api'] for group in SOURCES] + [[]],
1997ec681f3Smrg                        help='Only update the APIs specified.')
2007ec681f3Smrg    args = parser.parse_args()
2017ec681f3Smrg
2027ec681f3Smrg    # These APIs all depend on the KHR header
2037ec681f3Smrg    depend_on_khr = set(['egl', 'gl', 'gles', 'gles2', 'gles3'])
2047ec681f3Smrg    if args.apis and 'khr' not in args.apis and depend_on_khr.intersection(set(args.apis)):
2057ec681f3Smrg        args.apis = ['khr'] + args.apis
2067ec681f3Smrg
2077ec681f3Smrg    for group in SOURCES:
2087ec681f3Smrg        if args.apis and group['api'] not in args.apis:
2097ec681f3Smrg            continue
2107ec681f3Smrg
2117ec681f3Smrg        for source in group['sources']:
2127ec681f3Smrg            source.sync()
2137ec681f3Smrg
2147ec681f3Smrg        # Make sure all the API files are handled by this script
2157ec681f3Smrg        if 'inc_folder' in group:
2167ec681f3Smrg            for file in pathlib.Path('include/' + group['inc_folder']).iterdir():
2177ec681f3Smrg                if file not in [source.file for source in group['sources']]:
2187ec681f3Smrg                    error('{} is unknown, please add it to SOURCES'.format(file))
219