pixwerx/tools/glad-0.1.14a0/glad/lang/c/generator.py

299 lines
12 KiB
Python

import os
import sys
from glad.lang.common.generator import Generator
from glad.lang.common.util import makefiledir
KHRPLATFORM = 'https://www.khronos.org/registry/egl/api/KHR/khrplatform.h'
class CGenerator(Generator):
NAME = 'c'
NAME_LONG = 'C/C++'
def open(self):
suffix = ''
if not self.spec.NAME == 'gl':
suffix = '_{}'.format(self.spec.NAME)
if self.local_files:
self.h_include = '"glad{}.h"'.format(suffix)
self._f_c = open(make_path(self.path,
'glad{}.c'.format(suffix)), 'w')
self._f_h = open(make_path(self.path,
'glad{}.h'.format(suffix)), 'w')
khr = self.path
else:
self.h_include = '<glad/glad{}.h>'.format(suffix)
self._f_c = open(make_path(self.path, 'src',
'glad{}.c'.format(suffix)), 'w')
self._f_h = open(make_path(self.path, 'include', 'glad',
'glad{}.h'.format(suffix)), 'w')
khr = os.path.join(self.path, 'include', 'KHR')
if not self.omit_khrplatform:
khr_url = KHRPLATFORM
if os.path.exists('khrplatform.h'):
khr_url = 'file://' + os.path.abspath('khrplatform.h')
khrplatform = os.path.join(khr, 'khrplatform.h')
if not os.path.exists(khrplatform):
if not os.path.exists(khr):
os.makedirs(khr)
self.opener.urlretrieve(khr_url, khrplatform)
return self
def close(self):
self._f_c.close()
self._f_h.close()
def generate_header(self):
self._f_h.write('/*\n')
self._f_h.write(self.header)
self._f_h.write('*/\n\n')
self._f_c.write('/*\n')
self._f_c.write(self.header)
self._f_c.write('*/\n\n')
def generate_loader(self, features, extensions):
f = self._f_c
if self.spec.NAME in ('egl', 'wgl'):
features = {'egl': [], 'wgl': []}
written = set()
for api, version in self.api.items():
for feature in features[api]:
f.write('static void load_{}(GLADloadproc load) {{\n'
.format(feature.name))
if self.spec.NAME in ('gl', 'glx', 'wgl'):
f.write('\tif(!GLAD_{}) return;\n'.format(feature.name))
for func in feature.functions:
f.write('\tglad_{0} = (PFN{1}PROC)load("{0}");\n'
.format(func.proto.name, func.proto.name.upper()))
f.write('}\n')
for ext in extensions[api]:
if len(list(ext.functions)) == 0 or ext.name in written:
continue
f.write('static void load_{}(GLADloadproc load) {{\n'
.format(ext.name))
if self.spec.NAME in ('gl', 'glx', 'wgl'):
f.write('\tif(!GLAD_{}) return;\n'.format(ext.name))
if ext.name == 'GLX_SGIX_video_source': f.write('#ifdef _VL_H_\n')
if ext.name == 'GLX_SGIX_dmbuffer': f.write('#ifdef _DM_BUFFER_H_\n')
for func in ext.functions:
# even if they were in written we need to load it
f.write('\tglad_{0} = (PFN{1}PROC)load("{0}");\n'
.format(func.proto.name, func.proto.name.upper()))
if ext.name in ('GLX_SGIX_video_source', 'GLX_SGIX_dmbuffer'):
f.write('#else\n')
f.write('\t(void)load;\n')
f.write('#endif\n')
f.write('}\n')
written.add(ext.name)
f.write('static int find_extensions{}(void) {{\n'.format(api.upper()))
if self.spec.NAME in ('gl', 'glx', 'wgl'):
f.write('\tif (!get_exts()) return 0;\n')
for ext in extensions[api]:
f.write('\tGLAD_{0} = has_ext("{0}");\n'.format(ext.name))
if len(extensions[api]) == 0:
f.write('\t(void)&has_ext;\n') # suppress unused has_ext warnings
f.write('\tfree_exts();\n')
f.write('\treturn 1;\n')
f.write('}\n\n')
if api == 'glx':
f.write('static void find_core{}(Display *dpy, int screen) {{\n'.format(api.upper()))
elif api == 'wgl':
f.write('static void find_core{}(HDC hdc) {{\n'.format(api.upper()))
else:
f.write('static void find_core{}(void) {{\n'.format(api.upper()))
self.loader.write_find_core(f)
if self.spec.NAME in ('gl', 'glx', 'wgl'):
for feature in features[api]:
f.write('\tGLAD_{} = (major == {num[0]} && minor >= {num[1]}) ||'
' major > {num[0]};\n'.format(feature.name, num=feature.number))
if self.spec.NAME == 'gl':
f.write('\tif (GLVersion.major > {0} || (GLVersion.major >= {0} && GLVersion.minor >= {1})) {{\n'.format(version[0], version[1]))
f.write('\t\tmax_loaded_major = {0};\n'.format(version[0]))
f.write('\t\tmax_loaded_minor = {0};\n'.format(version[1]))
f.write('\t}\n')
f.write('}\n\n')
if api == 'glx':
f.write('int gladLoad{}Loader(GLADloadproc load, Display *dpy, int screen) {{\n'.format(api.upper()))
elif api == 'wgl':
f.write('int gladLoad{}Loader(GLADloadproc load, HDC hdc) {{\n'.format(api.upper()))
else:
f.write('int gladLoad{}Loader(GLADloadproc load) {{\n'.format(api.upper()))
self.loader.write_begin_load(f)
if api == 'glx':
f.write('\tfind_core{}(dpy, screen);\n'.format(api.upper()))
elif api == 'wgl':
f.write('\tfind_core{}(hdc);\n'.format(api.upper()))
else:
f.write('\tfind_core{}();\n'.format(api.upper()))
for feature in features[api]:
f.write('\tload_{}(load);\n'.format(feature.name))
f.write('\n\tif (!find_extensions{}()) return 0;\n'.format(api.upper()))
for ext in extensions[api]:
if len(list(ext.functions)) == 0:
continue
f.write('\tload_{}(load);\n'.format(ext.name))
self.loader.write_end_load(f)
f.write('}\n\n')
self.loader.write_header_end(self._f_h)
def generate_types(self, types):
f = self._f_h
self.loader.write_header(f)
self.write_api_header(f)
for type in types:
output_string = (type.raw + '\n').lstrip().replace(' ', ' ')
if output_string == '#include <KHR/khrplatform.h>\n':
if self.omit_khrplatform:
continue
elif self.local_files:
output_string = '#include "khrplatform.h"\n'
if not self.spec.NAME in ('egl',) and 'khronos' in type.raw:
continue
if type.name in ('GLsizeiptr', 'GLintptr', 'GLsizeiptrARB', 'GLintptrARB'):
# 10.6 is the last version supporting more than 64 bit (>1060)
output_string = \
'#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) ' +\
'&& (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060)\n' +\
output_string.replace('ptrdiff_t', 'long') + '#else\n' + output_string + '#endif\n'
f.write(output_string)
def generate_features(self, features):
f = self._f_h
write = set()
if self.spec.NAME in ('wgl',):
# These are already defined in windows.h
pass
elif self.spec.NAME in ('egl',):
self.write_enums(f, set(), features)
for feature in features:
for func in feature.functions:
self.write_function_def(f, func)
else:
self.write_functions(f, write, set(), features)
f = self._f_c
self.write_code_head(f)
self.loader.write(f)
self.loader.write_has_ext(f)
if self.spec.NAME in ('gl', 'glx', 'wgl'):
for feature in features:
f.write('int GLAD_{};\n'.format(feature.name))
for func in write:
self.write_function(f, func)
def generate_extensions(self, extensions, enums, functions):
write = set()
written = set(enum.name for enum in enums) | \
set(function.proto.name for function in functions)
f = self._f_h
self.write_functions(f, write, written, extensions)
f = self._f_c
if self.spec.NAME in ('gl', 'glx', 'wgl'):
for ext in set(ext.name for ext in extensions):
f.write('int GLAD_{};\n'.format(ext))
written = set()
for ext in extensions:
if ext.name == 'GLX_SGIX_video_source': f.write('#ifdef _VL_H_\n')
if ext.name == 'GLX_SGIX_dmbuffer': f.write('#ifdef _DM_BUFFER_H_\n')
for func in ext.functions:
if func in write and func not in written:
self.write_function(f, func)
written.add(func)
if ext.name in ('GLX_SGIX_video_source', 'GLX_SGIX_dmbuffer'): f.write('#endif\n')
def write_functions(self, f, write, written, extensions):
self.write_enums(f, written, extensions)
for ext in extensions:
f.write('#ifndef {0}\n#define {0} 1\n'.format(ext.name))
if self.spec.NAME in ('gl', 'glx', 'wgl'):
f.write('GLAPI int GLAD_{};\n'.format(ext.name))
if ext.name == 'GLX_SGIX_video_source': f.write('#ifdef _VL_H_\n')
if ext.name == 'GLX_SGIX_dmbuffer': f.write('#ifdef _DM_BUFFER_H_\n')
for func in ext.functions:
if not func.proto.name in written:
self.write_function_prototype(f, func)
write.add(func)
written.add(func.proto.name)
if ext.name in ('GLX_SGIX_video_source', 'GLX_SGIX_dmbuffer'): f.write('#endif\n')
f.write('#endif\n')
def write_enums(self, f, written, extensions):
for ext in extensions:
for enum in ext.enums:
if not enum.name in written:
f.write('#define {} {}\n'.format(enum.name, enum.value))
written.add(enum.name)
def write_api_header(self, f):
for api in self.api:
if api == 'glx':
f.write('GLAPI int gladLoad{}Loader(GLADloadproc, Display *dpy, int screen);\n\n'.format(api.upper()))
elif api == 'wgl':
f.write('GLAPI int gladLoad{}Loader(GLADloadproc, HDC hdc);\n\n'.format(api.upper()))
else:
f.write('GLAPI int gladLoad{}Loader(GLADloadproc);\n\n'.format(api.upper()))
def write_code_head(self, f):
f.write('#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include {}\n'.format(self.h_include))
def write_extern(self, fobj):
fobj.write('#ifdef __cplusplus\nextern "C" {\n#endif\n')
def write_extern_end(self, fobj):
fobj.write('#ifdef __cplusplus\n}\n#endif\n')
def write_function_def(self, fobj, func):
# write a function definition instead of a prototype.
# e.g. egl uses that, since the main functions get linked in and not loaded through a function.
fobj.write('{}('.format(func.proto.ret.raw))
fobj.write(', '.join(param.type.raw for param in func.params))
fobj.write(');\n')
def write_function_prototype(self, fobj, func):
fobj.write('typedef {} (APIENTRYP PFN{}PROC)({});\n'.format(
func.proto.ret.to_c(), func.proto.name.upper(),
', '.join(param.type.raw for param in func.params))
)
fobj.write('GLAPI PFN{}PROC glad_{};\n'.format(func.proto.name.upper(),
func.proto.name))
fobj.write('#define {0} glad_{0}\n'.format(func.proto.name))
def write_function(self, fobj, func):
fobj.write('PFN{}PROC glad_{};\n'.format(func.proto.name.upper(),
func.proto.name))
def make_path(path, *args):
path = os.path.join(path, *args)
makefiledir(path)
return path