added glad generator and a glad runtime

This commit is contained in:
Hartmut Seichter 2017-06-29 07:15:32 +02:00
parent 2017f6195e
commit ac18a84a9c
62 changed files with 32373 additions and 10 deletions

View file

@ -0,0 +1,3 @@
__version__ = '0.1.14a0'

View file

@ -0,0 +1,160 @@
#!/usr/bin/env python
"""
Uses the official Khronos-XML specs to generate a
GL/GLES/EGL/GLX/WGL Loader made for your needs. Glad currently supports
the languages C, D, Nim and Volt.
"""
from collections import namedtuple
import logging
import sys
from glad.opener import URLOpener
from glad.spec import SPECS
import glad.lang
Version = namedtuple('Version', ['major', 'minor'])
logger = logging.getLogger('glad')
def main():
import os.path
import argparse
from argparse import ArgumentParser
opener = URLOpener()
def get_spec(value):
if value not in SPECS:
raise argparse.ArgumentTypeError('Unknown specification')
spec_cls = SPECS[value]
if os.path.exists(value + '.xml'):
logger.info('using local specification: \'%s.xml\'', value)
return spec_cls.from_file(value + '.xml')
logger.info('getting \'%s\' specification from SVN', value)
return spec_cls.from_svn(opener=opener)
def ext_file(value):
msg = 'Invalid extensions argument'
if os.path.exists(value):
msg = 'Invalid extensions file'
try:
with open(value, 'r') as f:
return f.read().split()
except IOError:
pass
else:
return [v.strip() for v in value.split(',') if v]
raise argparse.ArgumentTypeError(msg)
def version(value):
if value is None or len(value.strip()) == 0:
return None
v = value
if '.' not in v:
v = '{}.0'.format(v)
try:
return Version(*map(int, v.split('.')))
except ValueError:
pass
raise argparse.ArgumentTypeError('Invalid version: "{}"'.format(value))
def cmdapi(value):
try:
return dict((p[0], version(p[1])) for p in
(list(map(str.strip, e.split('='))) for e in
filter(bool, map(str.strip, value.split(',')))))
except IndexError:
pass
raise argparse.ArgumentTypeError(
'Invalid api-string: "{}"'.format(value)
)
description = __doc__
parser = ArgumentParser(description=description)
parser.add_argument('--profile', dest='profile',
choices=['core', 'compatibility'],
default='compatibility',
help='OpenGL profile (defaults to compatibility)')
parser.add_argument('--out-path', dest='out', required=True,
help='Output path for loader')
parser.add_argument('--api', dest='api', type=cmdapi,
help='API type/version pairs, like "gl=3.2,gles=", '
'no version means latest')
parser.add_argument('--generator', dest='generator', default='d',
choices=['c', 'c-debug', 'd', 'nim', 'volt'], required=True,
help='Language to generate the binding for')
parser.add_argument('--extensions', dest='extensions',
default=None, type=ext_file,
help='Path to extensions file or comma separated '
'list of extensions, if missing '
'all extensions are included')
parser.add_argument('--spec', dest='spec', default='gl',
choices=['gl', 'egl', 'glx', 'wgl'],
help='Name of the spec')
parser.add_argument('--no-loader', dest='no_loader', action='store_true')
parser.add_argument('--omit-khrplatform', dest='omit_khrplatform', action='store_true',
help='Omits inclusion of the khrplatform.h '
'file which is often unnecessary. '
'Only has an effect if used together '
'with c generators.')
parser.add_argument('--local-files', dest='local_files', action='store_true',
help='Forces every file directly into the output '
'directory. No src or include subdirectories '
'are generated. '
'Only has an effect if used together '
'with c generators.')
parser.add_argument('--quiet', dest='quiet', action='store_true')
ns = parser.parse_args()
if not ns.quiet:
logging.basicConfig(
format='[%(asctime)s][%(levelname)s\t][%(name)-7s\t]: %(message)s',
datefmt='%m/%d/%Y %H:%M:%S', level=logging.DEBUG
)
spec = get_spec(ns.spec)
if spec.NAME == 'gl':
spec.profile = ns.profile
api = ns.api
if api is None or len(api.keys()) == 0:
api = {spec.NAME: None}
generator_cls, loader_cls = glad.lang.get_generator(
ns.generator, spec.NAME.lower()
)
if loader_cls is None:
return parser.error('API/Spec not yet supported')
loader = loader_cls(api, disabled=ns.no_loader, local_files=ns.local_files)
logger.info('generating \'%s\' bindings', spec.NAME)
with generator_cls(
ns.out,
spec,
api,
ns.extensions,
loader=loader,
opener=opener,
local_files=ns.local_files,
omit_khrplatform=ns.omit_khrplatform
) as generator:
generator.generate()
logger.info('generating \'%s\' bindings - done', spec.NAME)
if __name__ == '__main__':
main()

View file

@ -0,0 +1,19 @@
import glad.lang.c
import glad.lang.d
import glad.lang.nim
import glad.lang.volt
def get_generator(name, spec):
_langs = [
glad.lang.c,
glad.lang.d,
glad.lang.nim,
glad.lang.volt
]
for lang in _langs:
gen, loader = lang.get_generator(name, spec)
if gen is not None:
return gen, loader
return None, None

View file

@ -0,0 +1,28 @@
from glad.lang.c.loader.egl import EGLCLoader
from glad.lang.c.loader.gl import OpenGLCLoader
from glad.lang.c.loader.glx import GLXCLoader
from glad.lang.c.loader.wgl import WGLCLoader
from glad.lang.c.generator import CGenerator
from glad.lang.c.debug import CDebugGenerator
_specs = {
'egl': EGLCLoader,
'gl': OpenGLCLoader,
'glx': GLXCLoader,
'wgl': WGLCLoader
}
_generators = {
'c': CGenerator,
'c-debug': CDebugGenerator
}
def get_generator(name, spec):
gen = _generators.get(name)
loader = _specs.get(spec)
return gen, loader

View file

@ -0,0 +1,132 @@
from glad.lang.c.generator import CGenerator
DEFAULT_DEBUG_IMPL = '''
{return_def}
_pre_call_callback("{name}", {args_callback});
{return_assign} glad_{name}({args});
_post_call_callback("{name}", {args_callback});
{return_return}
'''
DEBUG_HEADER = '''
#define GLAD_DEBUG
typedef void (* GLADcallback)(const char *name, void *funcptr, int len_args, ...);
GLAPI void glad_set_pre_callback(GLADcallback cb);
GLAPI void glad_set_post_callback(GLADcallback cb);
'''
DEBUG_CODE = '''
static GLADcallback _pre_call_callback = _pre_call_callback_default;
void glad_set_pre_callback(GLADcallback cb) {
_pre_call_callback = cb;
}
static GLADcallback _post_call_callback = _post_call_callback_default;
void glad_set_post_callback(GLADcallback cb) {
_post_call_callback = cb;
}
'''
DEFAULT_CALLBACK = '''
void _pre_call_callback_default(const char *name, void *funcptr, int len_args, ...) {
(void) name;
(void) funcptr;
(void) len_args;
}
void _post_call_callback_default(const char *name, void *funcptr, int len_args, ...) {
(void) name;
(void) funcptr;
(void) len_args;
}
'''
DEFAULT_CALLBACK_GL = '''
void _pre_call_callback_default(const char *name, void *funcptr, int len_args, ...) {
(void) name;
(void) funcptr;
(void) len_args;
}
void _post_call_callback_default(const char *name, void *funcptr, int len_args, ...) {
GLenum error_code;
(void) funcptr;
(void) len_args;
error_code = glad_glGetError();
if (error_code != GL_NO_ERROR) {
fprintf(stderr, "ERROR %d in %s\\n", error_code, name);
}
}
'''
class CDebugGenerator(CGenerator):
NAME = 'c-debug'
NAME_LONG = 'C/C++ Debug'
def write_code_head(self, f):
CGenerator.write_code_head(self, f)
if self.spec.NAME == 'gl':
f.write(DEFAULT_CALLBACK_GL)
else:
f.write(DEFAULT_CALLBACK)
f.write(DEBUG_CODE)
def write_api_header(self, f):
CGenerator.write_api_header(self, f)
f.write(DEBUG_HEADER)
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('GLAPI PFN{}PROC glad_debug_{};\n'.format(
func.proto.name.upper(), func.proto.name
))
fobj.write('#define {0} glad_debug_{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
))
# write the default debug function
args_def = ', '.join(
'{type} arg{i}'.format(type=param.type.to_c(), i=i)
for i, param in enumerate(func.params)
)
fobj.write('{} APIENTRY glad_debug_impl_{}({}) {{'.format(
func.proto.ret.to_c(), func.proto.name, args_def
))
args = ', '.join('arg{}'.format(i) for i, _ in enumerate(func.params))
args_callback = ', '.join(filter(
None, ['(void*){}'.format(func.proto.name), str(len(func.params)), args]
))
return_def = ''
return_assign = ''
return_return = ''
# lower because of win API having VOID
if not func.proto.ret.to_c().lower() == 'void':
return_def = '\n {} ret;'.format(func.proto.ret.to_c())
return_assign = 'ret = '
return_return = 'return ret;'
fobj.write('\n'.join(filter(None, DEFAULT_DEBUG_IMPL.format(
name=func.proto.name, args=args, args_callback=args_callback,
return_def=return_def, return_assign=return_assign,
return_return=return_return
).splitlines())))
fobj.write('\n}\n')
fobj.write('PFN{0}PROC glad_debug_{1} = glad_debug_impl_{1};\n'.format(
func.proto.name.upper(), func.proto.name
))

View file

@ -0,0 +1,299 @@
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

View file

@ -0,0 +1,132 @@
LOAD_OPENGL_DLL = '''
%(pre)s void* %(proc)s(const char *namez);
#ifdef _WIN32
#include <windows.h>
static HMODULE libGL;
typedef void* (APIENTRYP PFNWGLGETPROCADDRESSPROC_PRIVATE)(const char*);
static PFNWGLGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
%(pre)s
int %(init)s(void) {
libGL = LoadLibraryW(L"opengl32.dll");
if(libGL != NULL) {
gladGetProcAddressPtr = (PFNWGLGETPROCADDRESSPROC_PRIVATE)GetProcAddress(
libGL, "wglGetProcAddress");
return gladGetProcAddressPtr != NULL;
}
return 0;
}
%(pre)s
void %(terminate)s(void) {
if(libGL != NULL) {
FreeLibrary(libGL);
libGL = NULL;
}
}
#else
#include <dlfcn.h>
static void* libGL;
#ifndef __APPLE__
typedef void* (APIENTRYP PFNGLXGETPROCADDRESSPROC_PRIVATE)(const char*);
static PFNGLXGETPROCADDRESSPROC_PRIVATE gladGetProcAddressPtr;
#endif
%(pre)s
int %(init)s(void) {
#ifdef __APPLE__
static const char *NAMES[] = {
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
};
#else
static const char *NAMES[] = {"libGL.so.1", "libGL.so"};
#endif
unsigned int index = 0;
for(index = 0; index < (sizeof(NAMES) / sizeof(NAMES[0])); index++) {
libGL = dlopen(NAMES[index], RTLD_NOW | RTLD_GLOBAL);
if(libGL != NULL) {
#ifdef __APPLE__
return 1;
#else
gladGetProcAddressPtr = (PFNGLXGETPROCADDRESSPROC_PRIVATE)dlsym(libGL,
"glXGetProcAddressARB");
return gladGetProcAddressPtr != NULL;
#endif
}
}
return 0;
}
%(pre)s
void %(terminate)s() {
if(libGL != NULL) {
dlclose(libGL);
libGL = NULL;
}
}
#endif
%(pre)s
void* %(proc)s(const char *namez) {
void* result = NULL;
if(libGL == NULL) return NULL;
#ifndef __APPLE__
if(gladGetProcAddressPtr != NULL) {
result = gladGetProcAddressPtr(namez);
}
#endif
if(result == NULL) {
#ifdef _WIN32
result = (void*)GetProcAddress(libGL, namez);
#else
result = dlsym(libGL, namez);
#endif
}
return result;
}
'''
LOAD_OPENGL_DLL_H = '''
'''
LOAD_OPENGL_GLAPI_H = '''
#ifndef GLAPI
# if defined(GLAD_GLAPI_EXPORT)
# if defined(_WIN32) || defined(__CYGWIN__)
# if defined(GLAD_GLAPI_EXPORT_BUILD)
# if defined(__GNUC__)
# define GLAPI __attribute__ ((dllexport)) extern
# else
# define GLAPI __declspec(dllexport) extern
# endif
# else
# if defined(__GNUC__)
# define GLAPI __attribute__ ((dllimport)) extern
# else
# define GLAPI __declspec(dllimport) extern
# endif
# endif
# elif defined(__GNUC__) && defined(GLAD_GLAPI_EXPORT_BUILD)
# define GLAPI __attribute__ ((visibility ("default"))) extern
# else
# define GLAPI extern
# endif
# else
# define GLAPI extern
# endif
#endif
'''

View file

@ -0,0 +1,85 @@
from glad.lang.common.loader import BaseLoader
_EGL_LOADER = '''
int gladLoadEGL(void) {
return gladLoadEGLLoader((GLADloadproc)eglGetProcAddress);
}
'''
_EGL_HEADER = '''
#ifndef __glad_egl_h_
#ifdef __egl_h_
#error EGL header already included, remove this include, glad already provides it
#endif
#define __glad_egl_h_
#define __egl_h_
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#endif
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef APIENTRYP
#define APIENTRYP APIENTRY *
#endif
#ifndef GLAPI
#define GLAPI extern
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void* (* GLADloadproc)(const char *name);
'''
_EGL_HEADER_LOADER = '''
GLAPI int gladLoadEGL(void);
'''
_EGL_HEADER_END = '''
#ifdef __cplusplus
}
#endif
#endif
'''
_EGL_HAS_EXT = '''
'''
class EGLCLoader(BaseLoader):
def write(self, fobj):
if not self.disabled:
fobj.write(_EGL_LOADER)
def write_begin_load(self, fobj):
# suppress unused warnings
fobj.write('\t(void) load;\n')
def write_end_load(self, fobj):
fobj.write('\treturn 1;\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_EGL_HAS_EXT)
def write_header(self, fobj):
fobj.write(_EGL_HEADER)
if not self.disabled:
fobj.write(_EGL_HEADER_LOADER)
def write_header_end(self, fobj):
fobj.write(_EGL_HEADER_END)

View file

@ -0,0 +1,242 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.c.loader import LOAD_OPENGL_DLL, LOAD_OPENGL_DLL_H, LOAD_OPENGL_GLAPI_H
_OPENGL_LOADER = \
LOAD_OPENGL_DLL % {'pre':'static', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
int gladLoadGL(void) {
int status = 0;
if(open_gl()) {
status = gladLoadGLLoader(&get_proc);
close_gl();
}
return status;
}
'''
_OPENGL_HAS_EXT = '''
struct gladGLversionStruct GLVersion;
#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0)
#define _GLAD_IS_SOME_NEW_VERSION 1
#endif
static int max_loaded_major;
static int max_loaded_minor;
static const char *exts = NULL;
static int num_exts_i = 0;
static const char **exts_i = NULL;
static int get_exts(void) {
#ifdef _GLAD_IS_SOME_NEW_VERSION
if(max_loaded_major < 3) {
#endif
exts = (const char *)glGetString(GL_EXTENSIONS);
#ifdef _GLAD_IS_SOME_NEW_VERSION
} else {
unsigned int index;
num_exts_i = 0;
glGetIntegerv(GL_NUM_EXTENSIONS, &num_exts_i);
if (num_exts_i > 0) {
exts_i = (const char **)realloc((void *)exts_i, (size_t)num_exts_i * (sizeof *exts_i));
}
if (exts_i == NULL) {
return 0;
}
for(index = 0; index < (unsigned)num_exts_i; index++) {
exts_i[index] = (const char*)glGetStringi(GL_EXTENSIONS, index);
}
}
#endif
return 1;
}
static void free_exts(void) {
if (exts_i != NULL) {
free(exts_i);
exts_i = NULL;
}
}
static int has_ext(const char *ext) {
#ifdef _GLAD_IS_SOME_NEW_VERSION
if(max_loaded_major < 3) {
#endif
const char *extensions;
const char *loc;
const char *terminator;
extensions = exts;
if(extensions == NULL || ext == NULL) {
return 0;
}
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL) {
return 0;
}
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\\0')) {
return 1;
}
extensions = terminator;
}
#ifdef _GLAD_IS_SOME_NEW_VERSION
} else {
int index;
for(index = 0; index < num_exts_i; index++) {
const char *e = exts_i[index];
if(strcmp(e, ext) == 0) {
return 1;
}
}
}
#endif
return 0;
}
'''
_OPENGL_HEADER_START = '''
#ifndef __glad_h_
#define __glad_h_
'''
_OPENGL_HEADER_INCLUDE_ERROR = '''
#ifdef __{0}_h_
#error {1} header already included, remove this include, glad already provides it
#endif
#define __{0}_h_
'''
_OPENGL_HEADER = '''
#if defined(_WIN32) && !defined(APIENTRY) && !defined(__CYGWIN__) && !defined(__SCITECH_SNAP__)
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN 1
#endif
#include <windows.h>
#endif
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef APIENTRYP
#define APIENTRYP APIENTRY *
#endif
#ifdef __cplusplus
extern "C" {
#endif
struct gladGLversionStruct {
int major;
int minor;
};
typedef void* (* GLADloadproc)(const char *name);
''' + LOAD_OPENGL_GLAPI_H + '''
GLAPI struct gladGLversionStruct GLVersion;
'''
_OPENGL_HEADER_LOADER = '''
GLAPI int gladLoadGL(void);
''' + LOAD_OPENGL_DLL_H
_OPENGL_HEADER_END = '''
#ifdef __cplusplus
}
#endif
#endif
'''
_FIND_VERSION = '''
/* Thank you @elmindreda
* https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
* https://github.com/glfw/glfw/blob/master/src/context.c#L36
*/
int i, major, minor;
const char* version;
const char* prefixes[] = {
"OpenGL ES-CM ",
"OpenGL ES-CL ",
"OpenGL ES ",
NULL
};
version = (const char*) glGetString(GL_VERSION);
if (!version) return;
for (i = 0; prefixes[i]; i++) {
const size_t length = strlen(prefixes[i]);
if (strncmp(version, prefixes[i], length) == 0) {
version += length;
break;
}
}
/* PR #18 */
#ifdef _MSC_VER
sscanf_s(version, "%d.%d", &major, &minor);
#else
sscanf(version, "%d.%d", &major, &minor);
#endif
GLVersion.major = major; GLVersion.minor = minor;
max_loaded_major = major; max_loaded_minor = minor;
'''
class OpenGLCLoader(BaseLoader):
def write(self, fobj):
if not self.disabled and 'gl' in self.apis:
fobj.write(_OPENGL_LOADER)
def write_begin_load(self, fobj):
fobj.write('\tGLVersion.major = 0; GLVersion.minor = 0;\n')
fobj.write('\tglGetString = (PFNGLGETSTRINGPROC)load("glGetString");\n')
fobj.write('\tif(glGetString == NULL) return 0;\n')
fobj.write('\tif(glGetString(GL_VERSION) == NULL) return 0;\n')
def write_end_load(self, fobj):
fobj.write('\treturn GLVersion.major != 0 || GLVersion.minor != 0;\n')
def write_find_core(self, fobj):
fobj.write(_FIND_VERSION)
def write_find_core_end(self, fobj):
fobj.write(_FIND_VERSION)
def write_has_ext(self, fobj):
fobj.write(_OPENGL_HAS_EXT)
def write_header(self, fobj):
fobj.write(_OPENGL_HEADER_START)
written = set()
for api, hname, name in [
('gl', 'gl', 'OpenGL'), ('gles1', 'gl', 'OpenGL ES 1'),
('gles2', 'gl2', 'OpenGL ES 2'), ('gles2', 'gl3', 'OpenGL ES 3')
]:
if api in self.apis and hname not in written:
fobj.write(_OPENGL_HEADER_INCLUDE_ERROR.format(hname, name))
written.add(hname)
fobj.write(_OPENGL_HEADER)
if not self.disabled and 'gl' in self.apis:
fobj.write(_OPENGL_HEADER_LOADER)
def write_header_end(self, fobj):
fobj.write(_OPENGL_HEADER_END)

View file

@ -0,0 +1,148 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.c.loader import LOAD_OPENGL_DLL, LOAD_OPENGL_DLL_H, LOAD_OPENGL_GLAPI_H
_GLX_LOADER = \
LOAD_OPENGL_DLL % {'pre':'static', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
int gladLoadGLX(Display *dpy, int screen) {
int status = 0;
if(open_gl()) {
status = gladLoadGLXLoader((GLADloadproc)get_proc, dpy, screen);
close_gl();
}
return status;
}
'''
_GLX_HEADER_START = '''
#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
'''
#include <glad/glad.h>
_WGL_HEADER_MID = '''
#ifndef __glad_glxext_h_
#ifdef __glxext_h_
#error GLX header already included, remove this include, glad already provides it
#endif
#define __glad_glxext_h_
#define __glxext_h_
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef APIENTRYP
#define APIENTRYP APIENTRY *
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void* (* GLADloadproc)(const char *name);
''' + LOAD_OPENGL_GLAPI_H
_GLX_HEADER_LOADER = '''
GLAPI int gladLoadGLX(Display *dpy, int screen);
''' + LOAD_OPENGL_DLL_H
_GLX_HEADER_END = '''
#ifdef __cplusplus
}
#endif
#endif
'''
_GLX_HAS_EXT = '''
static Display *GLADGLXDisplay = 0;
static int GLADGLXscreen = 0;
static int get_exts(void) {
return 1;
}
static void free_exts(void) {
return;
}
static int has_ext(const char *ext) {
const char *terminator;
const char *loc;
const char *extensions;
if(!GLAD_GLX_VERSION_1_1)
return 0;
extensions = glXQueryExtensionsString(GLADGLXDisplay, GLADGLXscreen);
if(extensions == NULL || ext == NULL)
return 0;
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL)
break;
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\\0'))
{
return 1;
}
extensions = terminator;
}
return 0;
}
'''
class GLXCLoader(BaseLoader):
def write(self, fobj):
if not self.disabled:
fobj.write(_GLX_LOADER)
def write_begin_load(self, fobj):
fobj.write('\tglXQueryVersion = (PFNGLXQUERYVERSIONPROC)load("glXQueryVersion");\n')
fobj.write('\tif(glXQueryVersion == NULL) return 0;\n')
def write_end_load(self, fobj):
fobj.write('\treturn 1;\n')
def write_find_core(self, fobj):
fobj.write('\tint major = 0, minor = 0;\n')
fobj.write('\tif(dpy == 0 && GLADGLXDisplay == 0) {\n')
fobj.write('\t\tdpy = XOpenDisplay(0);\n')
fobj.write('\t\tscreen = XScreenNumberOfScreen(XDefaultScreenOfDisplay(dpy));\n')
fobj.write('\t} else if(dpy == 0) {\n')
fobj.write('\t\tdpy = GLADGLXDisplay;\n')
fobj.write('\t\tscreen = GLADGLXscreen;\n')
fobj.write('\t}\n')
fobj.write('\tglXQueryVersion(dpy, &major, &minor);\n')
fobj.write('\tGLADGLXDisplay = dpy;\n')
fobj.write('\tGLADGLXscreen = screen;\n')
def write_has_ext(self, fobj):
fobj.write(_GLX_HAS_EXT)
def write_header(self, fobj):
fobj.write(_GLX_HEADER_START)
if self.local_files:
fobj.write('#include "glad.h"\n')
else:
fobj.write('#include <glad/glad.h>\n')
fobj.write(_WGL_HEADER_MID)
if not self.disabled:
fobj.write(_GLX_HEADER_LOADER)
def write_header_end(self, fobj):
fobj.write(_GLX_HEADER_END)

View file

@ -0,0 +1,142 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.c.loader import LOAD_OPENGL_DLL, LOAD_OPENGL_DLL_H, LOAD_OPENGL_GLAPI_H
_WGL_LOADER = \
LOAD_OPENGL_DLL % {'pre':'static', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
int gladLoadWGL(HDC hdc) {
int status = 0;
if(open_gl()) {
status = gladLoadWGLLoader((GLADloadproc)get_proc, hdc);
close_gl();
}
return status;
}
'''
_WGL_HEADER_START = '''
#ifndef WINAPI
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif
# include <windows.h>
#endif
'''
#include <glad/glad.h>
_WGL_HEADER_MID = '''
#ifndef __glad_wglext_h_
#ifdef __wglext_h_
#error WGL header already included, remove this include, glad already provides it
#endif
#define __glad_wglext_h_
#define __wglext_h_
#ifndef APIENTRY
#define APIENTRY
#endif
#ifndef APIENTRYP
#define APIENTRYP APIENTRY *
#endif
#ifdef __cplusplus
extern "C" {
#endif
typedef void* (* GLADloadproc)(const char *name);
''' + LOAD_OPENGL_GLAPI_H
_WGL_HEADER_LOADER = '''
GLAPI int gladLoadWGL(HDC hdc);
''' + LOAD_OPENGL_DLL_H
_WGL_HEADER_END = '''
#ifdef __cplusplus
}
#endif
#endif
'''
_WGL_HAS_EXT = '''
static HDC GLADWGLhdc = (HDC)INVALID_HANDLE_VALUE;
static int get_exts(void) {
return 1;
}
static void free_exts(void) {
return;
}
static int has_ext(const char *ext) {
const char *terminator;
const char *loc;
const char *extensions;
if(wglGetExtensionsStringEXT == NULL && wglGetExtensionsStringARB == NULL)
return 0;
if(wglGetExtensionsStringARB == NULL || GLADWGLhdc == INVALID_HANDLE_VALUE)
extensions = wglGetExtensionsStringEXT();
else
extensions = wglGetExtensionsStringARB(GLADWGLhdc);
if(extensions == NULL || ext == NULL)
return 0;
while(1) {
loc = strstr(extensions, ext);
if(loc == NULL)
break;
terminator = loc + strlen(ext);
if((loc == extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\\0'))
{
return 1;
}
extensions = terminator;
}
return 0;
}
'''
class WGLCLoader(BaseLoader):
def write(self, fobj):
if not self.disabled:
fobj.write(_WGL_LOADER)
def write_begin_load(self, fobj):
fobj.write('\twglGetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)load("wglGetExtensionsStringARB");\n')
fobj.write('\twglGetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)load("wglGetExtensionsStringEXT");\n')
fobj.write('\tif(wglGetExtensionsStringARB == NULL && wglGetExtensionsStringEXT == NULL) return 0;\n')
def write_end_load(self, fobj):
fobj.write('\treturn 1;\n')
def write_find_core(self, fobj):
fobj.write('\tGLADWGLhdc = hdc;\n')
def write_has_ext(self, fobj):
fobj.write(_WGL_HAS_EXT)
def write_header(self, fobj):
fobj.write(_WGL_HEADER_START)
if self.local_files:
fobj.write('#include "glad.h"\n')
else:
fobj.write('#include <glad/glad.h>\n')
fobj.write(_WGL_HEADER_MID)
if not self.disabled:
fobj.write(_WGL_HEADER_LOADER)
def write_header_end(self, fobj):
fobj.write(_WGL_HEADER_END)

View file

@ -0,0 +1,242 @@
from collections import defaultdict
from datetime import datetime
from itertools import chain
import os.path
import sys
from glad.lang.common.loader import NullLoader
from glad.opener import URLOpener
from glad.util import api_name
import glad
if sys.version_info >= (3, 0):
from urllib.parse import urlencode
else:
from urllib import urlencode
HEADER_TEMPLATE = '''
{apis_named} loader generated by glad {version} on {date}.
Language/Generator: {language}
Specification: {specification}
APIs: {apis}
Profile: {profile}
Extensions:
{extensions}
Loader: {loader}
Local files: {local_files}
Omit khrplatform: {omit_khrplatform}
Commandline:
{commandline}
Online:
{online}
'''
class Generator(object):
NAME = None
NAME_LONG = None
URL = 'http://glad.dav1d.de'
def __init__(self, path, spec, api, extension_names=None, loader=None,
opener=None, local_files=False, omit_khrplatform=False,
header_template=HEADER_TEMPLATE):
self.path = os.path.abspath(path)
self.spec = spec
for a in api:
if a not in self.spec.features:
raise ValueError(
'Unknown API "{0}" for specification "{1}"'
.format(a, self.spec.NAME)
)
self.api = api
self.extension_names = extension_names
self.has_loader = not loader.disabled
self.loader = loader
if self.loader is None:
self.loader = NullLoader
self.opener = opener
if self.opener is None:
self.opener = URLOpener.default()
self.local_files = local_files
self.omit_khrplatform = omit_khrplatform
self._header_template = header_template
def open(self):
raise NotImplementedError
def close(self):
raise NotImplementedError
def __enter__(self):
self.open()
return self
def __exit__(self, exc_type, exc_value, traceback):
self.close()
def generate(self):
features = list()
for api, version in self.api.items():
features.extend(self.spec.features[api])
if version is None:
version = list(self.spec.features[api].keys())[-1]
self.api[api] = version
if version not in self.spec.features[api]:
raise ValueError(
'Unknown version "{0}" for specification "{1}"'
.format(version, self.spec.NAME)
)
if self.extension_names is None:
self.extension_names = list(chain.from_iterable(self.spec.extensions[a]
for a in self.api))
# sort and eliminate duplicates
self.extension_names = list(sorted(set(self.extension_names)))
e = list(chain.from_iterable(self.spec.extensions[a] for a in self.api))
for ext in self.extension_names:
if ext not in e:
raise ValueError(
'Invalid extension "{0}" for specification "{1}"'
.format(ext, self.spec.NAME)
)
self.generate_header()
types = [t for t in self.spec.types if t.api is None or t.api in self.api]
self.generate_types(types)
f = list()
for api, version in self.api.items():
f.extend([value for key, value in self.spec.features[api].items()
if key <= version])
enums, functions = merge(f)
self.generate_features(f)
extensions = list()
for api in self.api:
extensions.extend(self.spec.extensions[api][ext]
for ext in self.extension_names if ext
in self.spec.extensions[api])
self.generate_extensions(extensions, enums, functions)
fs = defaultdict(list)
es = defaultdict(list)
for api, version in self.api.items():
fs[api].extend(
[value for key, value in
self.spec.features[api].items() if key <= version]
)
es[api].extend(self.spec.extensions[api][ext]
for ext in self.extension_names if ext
in self.spec.extensions[api])
self.generate_loader(fs, es)
@property
def header(self):
apis_named = ', '.join(sorted(set(api_name(api) for api in self.api)))
date = datetime.now().strftime('%c')
language = self.NAME_LONG
specification = self.spec.NAME
apis = ', '.join('{}={}'.format(api, '.'.join(map(str, version))) for api, version in self.api.items())
profile = getattr(self.spec, 'profile', '-')
extensions = ',\n '.join(self.extension_names)
online = self.online
if len(online) > 2000:
online = 'Too many extensions'
return self._header_template.format(
apis_named=apis_named,
version=glad.__version__,
date=date,
language=language,
specification=specification,
apis=apis,
profile=profile,
extensions=extensions,
loader=self.has_loader,
local_files=self.local_files,
omit_khrplatform=self.omit_khrplatform,
commandline=self.commandline,
online=online
)
@property
def commandline(self):
profile = getattr(self.spec, 'profile', None)
if profile is not None:
profile = '--profile="{}"'.format(profile)
api = '--api="{}"'.format(','.join(
'{}={}'.format(api, '.'.join(map(str, version))) for api, version in self.api.items())
)
generator = '--generator="{}"'.format(self.NAME)
specification = '--spec="{}"'.format(self.spec.NAME)
loader = '' if self.has_loader else '--no-loader'
extensions = '--extensions="{}"'.format(','.join(self.extension_names))
local_files = '--local-files' if self.local_files else ''
omit_khrplatform = '--omit-khrplatform' if self.omit_khrplatform else ''
return ' '.join(filter(None, [
profile, api, generator, specification,
loader, local_files, omit_khrplatform, extensions
]))
@property
def online(self):
profile = getattr(self.spec, 'profile', None)
if profile is not None:
profile = ('profile', profile)
api = [('api', s) for s in ('{}={}'.format(api, '.'.join(map(str, version))) for api, version in self.api.items())]
generator = ('language', self.NAME)
specification = ('specification', self.spec.NAME)
loader = ('loader', 'on') if self.has_loader else None
extensions = [('extensions', ext) for ext in self.extension_names]
data = [profile, generator, specification, loader]
data.extend(api)
data.extend(extensions)
data = list(filter(None, data))
serialized = urlencode(data)
# TODO: --local-files, --omit-khrplatform
return '{}/#{}'.format(self.URL, serialized)
def generate_header(self):
raise NotImplementedError
def generate_loader(self, features, extensions):
raise NotImplementedError
def generate_types(self, types):
raise NotImplementedError
def generate_features(self, features):
raise NotImplementedError
def generate_extensions(self, extensions, enums, functions):
raise NotImplementedError
def merge(features):
enums = set()
functions = set()
for feature in features:
enums |= set(feature.enums)
functions |= set(feature.functions)
return enums, functions

View file

@ -0,0 +1,60 @@
class BaseLoader(object):
def __init__(self, apis, disabled=False, local_files=False):
self.apis = apis
self.disabled = disabled
self.local_files = local_files
def write(self, fobj):
raise NotImplementedError
def write_begin_load(self, fobj):
raise NotImplementedError
def write_end_load(self, fobj):
raise NotImplementedError
def write_find_core(self, fobj):
raise NotImplementedError
def write_has_ext(self, fobj):
raise NotImplementedError
def write_header(self, fobj):
raise NotImplementedError
def write_header_end(self, fobj):
raise NotImplementedError
class NullLoader(BaseLoader):
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
pass
def write_header_end(self, fobj):
pass
def write_has_ext(self, fobj):
pass
def write(self, fobj):
pass
def write_header(self, fobj):
pass
def write_find_core(self, fobj):
pass
def __getattr__(self, name):
try:
return self.__getattribute__(name)
except AttributeError:
pass
def dummy(*args, **kwargs):
pass
return dummy

View file

@ -0,0 +1,13 @@
import os.path
import os
def enforce(exp, message, exc):
if not exp:
raise exc(message)
def makefiledir(path):
dir = os.path.split(path)[0]
if not os.path.exists(dir):
os.makedirs(dir)

View file

@ -0,0 +1,25 @@
from glad.lang.d.loader.egl import EGLDLoader
from glad.lang.d.loader.gl import OpenGLDLoader
from glad.lang.d.loader.glx import GLXDLoader
from glad.lang.d.loader.wgl import WGLDLoader
from glad.lang.d.generator import DGenerator
_specs = {
'egl': EGLDLoader,
'gl': OpenGLDLoader,
'glx': GLXDLoader,
'wgl': WGLDLoader
}
_generators = {
'd': DGenerator,
}
def get_generator(name, spec):
gen = _generators.get(name)
loader = _specs.get(spec)
return gen, loader

View file

@ -0,0 +1,861 @@
from itertools import chain
import os.path
import sys
from glad.lang.common.generator import Generator
from glad.lang.common.util import makefiledir
if sys.version_info >= (3, 0):
from io import StringIO
basestring = str
else:
from StringIO import StringIO
def _gl_types(gen, f):
gen.write_opaque_struct(f, '__GLsync')
gen.write_alias(f, 'GLsync', '__GLsync*')
gen.write_opaque_struct(f, '_cl_context')
gen.write_opaque_struct(f, '_cl_event')
gen.write_extern(f)
gen.write_alias(
f,
'GLDEBUGPROC', 'void function(GLenum, GLenum, '
'GLuint, GLenum, GLsizei, in GLchar*, GLvoid*)'
)
gen.write_alias(f, 'GLDEBUGPROCARB', 'GLDEBUGPROC')
gen.write_alias(f, 'GLDEBUGPROCKHR', 'GLDEBUGPROC')
gen.write_alias(
f,
'GLDEBUGPROCAMD', 'void function(GLuint, GLenum, '
'GLenum, GLsizei, in GLchar*, GLvoid*)'
)
gen.write_extern_end(f)
def _egl_types(gen, f):
io = StringIO()
gen.write_opaque_struct(io, 'egl_native_pixmap_t')
f.write('''
// Thanks to @jpf91 (github) for these declarations
version(Windows) {
import core.sys.windows.windows;
alias EGLNativeDisplayType = HDC;
alias EGLNativePixmapType = HBITMAP;
alias EGLNativeWindowType = HWND;
} else version(Symbian) {
alias EGLNativeDisplayType = int;
alias EGLNativeWindowType = void*;
alias EGLNativePixmapType = void*;
} else version(Android) {
//import android.native_window;
//struct egl_native_pixmap_t;
''' + io.getvalue() + '''
//alias ANativeWindow* EGLNativeWindowType;
//alias egl_native_pixmap_t* EGLNativePixmapType;
alias EGLNativeWindowType = void*;
alias EGLNativePixmapType = void*;
alias EGLNativeDisplayType = void*;
} else version(linux) {
version(Xlib) {
import X11.Xlib;
import X11.Xutil;
alias EGLNativeDisplayType = Display*;
alias EGLNativePixmapType = Pixmap;
alias EGLNativeWindowType = Window;
} else {
alias EGLNativeDisplayType = void*;
alias EGLNativePixmapType = uint;
alias EGLNativeWindowType = uint;
}
}
alias EGLObjectKHR = void*;
alias EGLLabelKHR = void*;
extern(System) {
alias EGLSetBlobFuncANDROID = void function(const(void)*, EGLsizeiANDROID, const(void)*, EGLsizeiANDROID);
alias EGLGetBlobFuncANDROID = EGLsizeiANDROID function(const(void)*, EGLsizeiANDROID, const(void)* EGLsizeiANDROID);
struct EGLClientPixmapHI {
void *pData;
EGLint iWidth;
EGLint iHeight;
EGLint iStride;
}
alias EGLDEBUGPROCKHR = void function(EGLenum error,const char *command,EGLint messageType,EGLLabelKHR threadLabel,EGLLabelKHR objectLabel,const char* message);
}
''')
gen.write_extern(f)
gen.write_opaque_struct(f, '_cl_event')
gen.write_extern_end(f)
def _glx_types(gen, f):
f.write('''
version(Xlib) {
import X11.Xlib;
import X11.Xutil;
} else {
alias Bool = int;
alias Status = int;
alias VisualID = uint;
alias XPointer = byte*;
alias XID = uint;
alias Colormap = XID;
alias Display = void;
alias Font = XID;
alias Window = XID;
alias Drawable = XID;
alias Pixmap = XID;
alias Cursor = XID;
alias GContext = XID;
alias KeySym = XID;
extern(System) {
// Borrowed from derelict
struct XExtData {
int number;
XExtData* next;
extern(C) int function(XExtData*) free_private;
XPointer private_data;
}
struct Visual {
XExtData* ext_data;
VisualID visualid;
int _class;
uint red_mask, green_mask, blue_mask;
int bits_per_rgb;
int map_entries;
}
struct XVisualInfo {
Visual *visual;
VisualID visualid;
int screen;
int depth;
int _class;
uint red_mask;
uint green_mask;
uint blue_mask;
int colormap_size;
int bits_per_rgb;
}
}
}
alias DMbuffer = void*;
alias DMparams = void*;
alias VLNode = void*;
alias VLPath = void*;
alias VLServer = void*;
alias int64_t = long;
alias uint64_t = ulong;
alias int32_t = int;
alias GLXContextID = uint;
alias GLXPixmap = uint;
alias GLXDrawable = uint;
alias GLXPbuffer = uint;
alias GLXWindow = uint;
alias GLXFBConfigID = uint;
alias GLXVideoCaptureDeviceNV = XID;
alias GLXPbufferSGIX = XID;
alias GLXVideoSourceSGIX = XID;
alias GLXVideoDeviceNV = uint;
extern(System) {
alias __GLXextFuncPtr = void function();
struct GLXPbufferClobberEvent {
int event_type; /* GLX_DAMAGED or GLX_SAVED */
int draw_type; /* GLX_WINDOW or GLX_PBUFFER */
ulong serial; /* # of last request processed by server */
Bool send_event; /* true if this came for SendEvent request */
Display *display; /* display the event was read from */
GLXDrawable drawable; /* XID of Drawable */
uint buffer_mask; /* mask indicating which buffers are affected */
uint aux_buffer; /* which aux buffer was affected */
int x, y;
int width, height;
int count; /* if nonzero, at least this many more */
}
struct GLXBufferSwapComplete {
int type;
ulong serial; /* # of last request processed by server */
Bool send_event; /* true if this came from a SendEvent request */
Display *display; /* Display the event was read from */
GLXDrawable drawable; /* drawable on which event was requested in event mask */
int event_type;
long ust;
long msc;
long sbc;
}
union GLXEvent {
GLXPbufferClobberEvent glxpbufferclobber;
GLXBufferSwapComplete glxbufferswapcomplete;
int[24] pad;
}
struct GLXBufferClobberEventSGIX {
int type;
ulong serial; /* # of last request processed by server */
Bool send_event; /* true if this came for SendEvent request */
Display *display; /* display the event was read from */
GLXDrawable drawable; /* i.d. of Drawable */
int event_type; /* GLX_DAMAGED_SGIX or GLX_SAVED_SGIX */
int draw_type; /* GLX_WINDOW_SGIX or GLX_PBUFFER_SGIX */
uint mask; /* mask indicating which buffers are affected*/
int x, y;
int width, height;
int count; /* if nonzero, at least this many more */
}
struct GLXHyperpipeNetworkSGIX {
char[80] pipeName; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
int networkId;
}
struct GLXHyperpipeConfigSGIX {
char[80] pipeName; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
int channel;
uint participationType;
int timeSlice;
}
struct GLXPipeRect {
char[80] pipeName; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
int srcXOrigin, srcYOrigin, srcWidth, srcHeight;
int destXOrigin, destYOrigin, destWidth, destHeight;
}
struct GLXPipeRectLimits {
char[80] pipeName; /* Should be [GLX_HYPERPIPE_PIPE_NAME_LENGTH_SGIX] */
int XOrigin, YOrigin, maxHeight, maxWidth;
}
}
''')
gen.write_extern(f)
gen.write_opaque_struct(f, '__GLXcontextRec')
gen.write_alias(f, 'GLXContext', '__GLXcontextRec*')
gen.write_opaque_struct(f, '__GLXFBConfigRec')
gen.write_alias(f, 'GLXFBConfig', '__GLXFBConfigRec*')
gen.write_alias(f, 'GLXFBConfigSGIX', '__GLXFBConfigRec*')
gen.write_extern_end(f)
def _wgl_types(gen, f):
f.write('''
version(Windows) {
public import core.sys.windows.windows;
} else {
alias BOOL = int;
alias CHAR = char;
alias WORD = ushort;
alias DWORD = uint;
alias FLOAT = float;
alias HANDLE = void*;
alias HDC = HANDLE;
alias HGLRC = HANDLE;
alias INT = int;
alias LPCSTR = const(CHAR)*;
alias LPVOID = void*;
alias UINT = uint;
alias USHORT = ushort;
alias VOID = void;
alias COLORREF = DWORD;
alias HENHMETAFILE = HANDLE;
alias BYTE = byte;
}
alias PROC = HANDLE;
extern(System) {
struct RECT {
int left;
int top;
int right;
int bottom;
}
struct LAYERPLANEDESCRIPTOR {
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
COLORREF crTransparent;
}
struct PIXELFORMATDESCRIPTOR {
WORD nSize;
WORD nVersion;
DWORD dwFlags;
BYTE iPixelType;
BYTE cColorBits;
BYTE cRedBits;
BYTE cRedShift;
BYTE cGreenBits;
BYTE cGreenShift;
BYTE cBlueBits;
BYTE cBlueShift;
BYTE cAlphaBits;
BYTE cAlphaShift;
BYTE cAccumBits;
BYTE cAccumRedBits;
BYTE cAccumGreenBits;
BYTE cAccumBlueBits;
BYTE cAccumAlphaBits;
BYTE cDepthBits;
BYTE cStencilBits;
BYTE cAuxBuffers;
BYTE iLayerType;
BYTE bReserved;
DWORD dwLayerMask;
DWORD dwVisibleMask;
DWORD dwDamageMask;
}
struct POINTFLOAT {
FLOAT x;
FLOAT y;
}
struct GLYPHMETRICSFLOAT {
FLOAT gmfBlackBoxX;
FLOAT gmfBlackBoxY;
POINTFLOAT gmfptGlyphOrigin;
FLOAT gmfCellIncX;
FLOAT gmfCellIncY;
}
alias PGLYPHMETRICSFLOAT = GLYPHMETRICSFLOAT*;
alias LPGLYPHMETRICSFLOAT = GLYPHMETRICSFLOAT;
struct GPU_DEVICE {
DWORD cb;
CHAR[32] DeviceName;
CHAR[128] DeviceString;
DWORD Flags;
RECT rcVirtualScreen;
}
alias PGPU_DEVICE = GPU_DEVICE;
}
''')
gen.write_opaque_struct(f, 'HPBUFFERARB')
gen.write_opaque_struct(f, 'HPBUFFEREXT')
gen.write_opaque_struct(f, 'HVIDEOOUTPUTDEVICENV')
gen.write_opaque_struct(f, 'HPVIDEODEV')
gen.write_opaque_struct(f, 'HPGPUNV')
gen.write_opaque_struct(f, 'HGPUNV')
gen.write_opaque_struct(f, 'HVIDEOINPUTDEVICENV')
DTYPES = {
'__pre': {
'egl': 'import core.stdc.stdint : intptr_t;\n\n'
},
'__other': {
'gl': _gl_types,
'egl': _egl_types,
'glx': _glx_types,
'wgl': _wgl_types
},
'gl': {
'GLenum': 'uint', 'GLvoid': 'void', 'GLboolean': 'ubyte',
'GLbitfield': 'uint', 'GLchar': 'char', 'GLbyte': 'byte',
'GLshort': 'short', 'GLint': 'int', 'GLclampx': 'int',
'GLsizei': 'int', 'GLubyte': 'ubyte', 'GLushort': 'ushort',
'GLuint': 'uint', 'GLhalf': 'ushort', 'GLfloat': 'float',
'GLclampf': 'float', 'GLdouble': 'double', 'GLclampd': 'double',
'GLfixed': 'int', 'GLintptr': 'ptrdiff_t', 'GLsizeiptr': 'ptrdiff_t',
'GLintptrARB': 'ptrdiff_t', 'GLsizeiptrARB': 'ptrdiff_t',
'GLcharARB': 'byte', 'GLhandleARB': 'uint', 'GLhalfARB': 'ushort',
'GLhalfNV': 'ushort', 'GLint64EXT': 'long', 'GLuint64EXT': 'ulong',
'GLint64': 'long', 'GLuint64': 'ulong',
'GLvdpauSurfaceNV': 'ptrdiff_t', 'GLeglImageOES': 'void*'
},
'egl': {
'EGLBoolean': 'uint', 'EGLenum': 'uint', 'EGLAttribKHR': 'intptr_t',
'EGLAttrib': 'intptr_t', 'EGLClientBuffer': 'void*', 'EGLConfig': 'void*',
'EGLContext': 'void*', 'EGLDeviceEXT': 'void*', 'EGLDisplay': 'void*',
'EGLImage': 'void*', 'EGLImageKHR': 'void*', 'EGLOutputLayerEXT': 'void*',
'EGLOutputPortEXT': 'void*', 'EGLStreamKHR': 'void*', 'EGLSurface': 'void*',
'EGLSync': 'void*', 'EGLSyncKHR': 'void*', 'EGLSyncNV': 'void*',
'__eglMustCastToProperFunctionPointerType': 'void function()',
'EGLint': 'int', 'EGLTimeKHR': 'ulong', 'EGLTime': 'ulong',
'EGLTimeNV': 'ulong', 'EGLuint64NV': 'ulong',
'EGLuint64KHR': 'ulong', 'EGLuint64MESA': 'ulong',
'EGLsizeiANDROID': 'ptrdiff_t', 'EGLNativeFileDescriptorKHR': 'int'
},
'glx': {
'GLboolean': 'ubyte', 'GLenum': 'uint', 'GLint': 'int',
'GLsizei': 'int', 'GLubyte': 'ubyte', 'GLuint': 'uint',
'GLfloat': 'float', 'GLbitfield': 'uint', 'GLintptr': 'ptrdiff_t',
'GLsizeiptr': 'ptrdiff_t'
},
'wgl': {
'GLbitfield': 'uint', 'GLenum': 'uint', 'GLfloat': 'float',
'GLint': 'int', 'GLsizei': 'int', 'GLuint': 'uint',
'GLushort': 'ushort', 'INT32': 'int', 'INT64': 'long',
'GLboolean': 'ubyte'
},
'SpecialNumbers': {
'gl': [
('GL_FALSE', '0', 'ubyte'), ('GL_TRUE', '1', 'ubyte'),
('GL_NO_ERROR', '0', 'uint'), ('GL_NONE', '0', 'uint'),
('GL_ZERO', '0', 'uint'), ('GL_ONE', '1', 'uint'),
('GL_NONE_OES', '0', 'uint'),
('GL_INVALID_INDEX', '0xFFFFFFFF', 'uint'),
('GL_TIMEOUT_IGNORED', '0xFFFFFFFFFFFFFFFF', 'ulong'),
('GL_TIMEOUT_IGNORED_APPLE', '0xFFFFFFFFFFFFFFFF', 'ulong'),
('GL_VERSION_ES_CL_1_0', '1', 'uint'), ('GL_VERSION_ES_CM_1_1', '1', 'uint'),
('GL_VERSION_ES_CL_1_1', '1', 'uint')
],
'egl': [
('EGL_DONT_CARE', '-1', 'int'), ('EGL_UNKNOWN', '-1', 'int'),
('EGL_NO_NATIVE_FENCE_FD_ANDROID', '-1', 'uint'),
('EGL_DEPTH_ENCODING_NONE_NV', '0', 'uint'),
('EGL_NO_CONTEXT', 'cast(EGLContext)0', 'EGLContext'),
('EGL_NO_DEVICE_EXT', 'cast(EGLDeviceEXT)0', 'EGLDeviceEXT'),
('EGL_NO_DISPLAY', 'cast(EGLDisplay)0', 'EGLDisplay'),
('EGL_NO_IMAGE', 'cast(EGLImage)0', 'EGLImage'),
('EGL_NO_IMAGE_KHR', 'cast(EGLImageKHR)0', 'EGLImageKHR'),
('EGL_DEFAULT_DISPLAY', 'cast(EGLNativeDisplayType)0', 'EGLNativeDisplayType'),
('EGL_NO_FILE_DESCRIPTOR_KHR', 'cast(EGLNativeFileDescriptorKHR)-1', 'EGLNativeFileDescriptorKHR'),
('EGL_NO_OUTPUT_LAYER_EXT', 'cast(EGLOutputLayerEXT)0', 'EGLOutputLayerEXT'),
('EGL_NO_OUTPUT_PORT_EXT', 'cast(EGLOutputPortEXT)0', 'EGLOutputPortEXT'),
('EGL_NO_STREAM_KHR', 'cast(EGLStreamKHR)0', 'EGLStreamKHR'),
('EGL_NO_SURFACE', 'cast(EGLSurface)0', 'EGLSurface'),
('EGL_NO_SYNC', 'cast(EGLSync)0', 'EGLSync'),
('EGL_NO_SYNC_KHR', 'cast(EGLSyncKHR)0', 'EGLSyncKHR'),
('EGL_NO_SYNC_NV', 'cast(EGLSyncNV)0', 'EGLSyncNV'),
('EGL_DISPLAY_SCALING', '10000', 'uint'),
('EGL_FOREVER', '0xFFFFFFFFFFFFFFFF', 'ulong'),
('EGL_FOREVER_KHR', '0xFFFFFFFFFFFFFFFF', 'ulong'),
('EGL_FOREVER_NV', '0xFFFFFFFFFFFFFFFF', 'ulong')
],
'glx': [
('GLX_DONT_CARE', '0xFFFFFFFF', 'uint'),
('GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB', '0', 'uint')
],
'wgl': [
('WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB', '0', 'uint'),
('WGL_FONT_LINES', '0', 'uint'),
('WGL_FONT_POLYGONS', 1, 'uint')
]
}
}
class BaseDGenerator(Generator):
NAME = 'd'
NAME_LONG = 'D'
def open(self):
self._f_loader = open(self.make_path(self.LOADER), 'w')
self._f_gl = open(self.make_path(self.PACKAGE), 'w')
self._f_types = open(self.make_path(self.TYPES), 'w')
self._f_enums = open(self.make_path(self.ENUMS), 'w')
self._f_funcs = open(self.make_path(self.FUNCS), 'w')
self._f_exts = open(self.make_path(self.EXT), 'w')
def close(self):
self._f_loader.close()
self._f_gl.close()
self._f_types.close()
self._f_enums.close()
self._f_funcs.close()
self._f_exts.close()
@property
def PACKAGE(self):
return 'all'
def generate_header(self):
self._f_gl.write('/*\n')
self._f_gl.write(self.header)
self._f_gl.write('*/\n\n')
def generate_loader(self, features, extensions):
f = self._f_loader
rfeatures = features
if self.spec.NAME in ('egl', 'wgl'):
features = {'egl': [], 'wgl': []}
self.write_module(f, self.LOADER)
self.write_imports(f, [self.FUNCS, self.EXT, self.ENUMS, self.TYPES])
self.loader.write(f)
self.loader.write_has_ext(f)
written = set()
for api, version in self.api.items():
loadername = 'Load' if self.LOAD_GL_PREFIX else 'load'
f.write('bool {}{}{}(Loader load) {{\n'
.format(self.LOAD_GL_PREFIX, loadername, api.upper()))
self.loader.write_begin_load(f)
f.write('\tfind_core{}();\n'.format(api.upper()))
for feature in features[api]:
f.write('\tload_{}(load);\n'.format(feature.name))
f.write('\n\tfind_extensions{}();\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')
f.write('private {\n\n')
f.write('void find_core{}() {{\n'.format(api.upper()))
self.loader.write_find_core(f)
if self.spec.NAME == 'gl':
for feature in features[api]:
f.write('\t{} = (major == {num[0]} && minor >= {num[1]}) ||'
' major > {num[0]};\n'.format(feature.name, num=feature.number))
f.write('\treturn;\n')
f.write('}\n\n')
f.write('void find_extensions{}() {{\n'.format(api.upper()))
if self.spec.NAME == 'gl':
for ext in extensions[api]:
f.write('\t{0} = has_ext("{0}");\n'.format(ext.name))
f.write('\treturn;\n')
f.write('}\n\n')
for feature in features[api]:
f.write('void load_{}(Loader load) {{\n'
.format(feature.name))
if self.spec.NAME == 'gl':
f.write('\tif(!{}) return;\n'.format(feature.name))
for func in feature.functions:
f.write('\t{name} = cast(typeof({name}))load("{name}");\n'
.format(name=func.proto.name))
f.write('\treturn;\n}\n\n')
for ext in extensions[api]:
if len(list(ext.functions)) == 0 or ext.name in written:
continue
f.write('void load_{}(Loader load) {{\n'
.format(ext.name))
if self.spec.NAME == 'gl':
f.write('\tif(!{}) return;\n'.format(ext.name))
for func in ext.functions:
# even if they were in written we need to load it
f.write('\t{name} = cast(typeof({name}))load("{name}");\n'
.format(name=func.proto.name))
f.write('\treturn;\n')
f.write('}\n')
written.add(ext.name)
f.write('\n} /* private */\n\n')
self.write_packages(rfeatures, extensions)
def write_packages(self, allfeatures, allextensions):
f = self._f_gl
self.write_module(f, self.PACKAGE)
self.write_imports(f, [self.FUNCS, self.EXT, self.ENUMS, self.TYPES], False)
for api, features in allfeatures.items():
extensions = allextensions[api]
with open(self.make_path(api), 'w') as f:
self.write_module(f, api)
self.write_imports(f, [self.TYPES], False)
extenums = chain.from_iterable(ext.enums for ext in extensions)
funcenums = chain.from_iterable(ext.enums for ext in extensions)
enums = set(enum.name for enum in extenums) | \
set(enum.name for enum in funcenums)
featfuncs = set(func.proto.name for func in
chain.from_iterable(feat.functions for feat in features))
extfuncs = set(func.proto.name for func in
chain.from_iterable(ext.functions for ext in extensions))
extfuncs = extfuncs - featfuncs
enums |= set(enum.name for enum in
chain.from_iterable(feat.enums for feat in features))
self.write_selective_import(f, self.FUNCS, featfuncs)
self.write_selective_import(f, self.EXT, extfuncs)
self.write_selective_import(f, self.ENUMS, enums)
def generate_types(self, types):
f = self._f_types
self.write_module(f, self.TYPES)
f.write(self.TYPE_DICT.get('__pre', {}).get(self.spec.NAME,''))
for ogl, d in self.TYPE_DICT[self.spec.NAME].items():
self.write_alias(f, ogl, d)
self.TYPE_DICT['__other'][self.spec.NAME](self, f)
def generate_features(self, features):
self.write_enums(features)
self.write_funcs(features)
def write_enums(self, features):
e = self._f_enums
self.write_module(e, self.ENUMS)
self.write_imports(e, [self.TYPES])
for v in self.TYPE_DICT['SpecialNumbers'][self.spec.NAME]:
self.write_enum(e, *v)
written = set()
for feature in features:
for enum in feature.enums:
if enum.group == 'SpecialNumbers':
written.add(enum)
continue
if not enum in written:
self.write_enum(e, enum.name, enum.value)
written.add(enum)
def write_funcs(self, features):
f = self._f_funcs
self.write_module(f, self.FUNCS)
self.write_imports(f, [self.TYPES])
if self.spec.NAME == 'gl':
for feature in features:
self.write_boolean(f, feature.name)
if self.spec.NAME in ('egl', 'wgl'):
self.write_extern(f)
for feature in features:
for func in feature.functions:
self.write_function_def(f, func)
self.write_extern_end(f)
else:
self.write_functions(f, set(), set(), features)
def generate_extensions(self, extensions, enums, functions):
f = self._f_exts
self.write_module(f, self.EXT)
self.write_imports(f, [self.TYPES, self.ENUMS, self.FUNCS])
write = set()
written = set(enum.name for enum in enums) | \
set(function.proto.name for function in functions)
for ext in extensions:
if self.spec.NAME == 'gl' and not ext.name in written:
self.write_boolean(f, ext.name)
for enum in ext.enums:
if not enum.name in written and not enum.group == 'SpecialNumbers':
self.write_enum(self._f_enums, enum.name, enum.value)
written.add(enum.name)
written.add(ext.name)
self.write_functions(f, write, written, extensions)
def write_functions(self, f, write, written, extensions):
self.write_prototype_pre(f)
for ext in extensions:
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)
self.write_prototype_post(f)
self.write_function_pre(f)
for func in write:
self.write_function(f, func)
self.write_function_post(f)
def make_path(self, name):
path = os.path.join(self.path, self.MODULE.split('.')[-1],
self.spec.NAME, name.split('.')[-1] + self.FILE_EXTENSION)
makefiledir(path)
return path
def write_imports(self, fobj, modules, private=True):
raise NotImplementedError
def write_selective_import(self, fobj, imports):
raise NotImplementedError
def write_module(self, fobj, name):
raise NotImplementedError
def write_prototype_pre(self, fobj):
raise NotImplementedError
def write_prototype_post(self, fobj):
raise NotImplementedError
def write_function_pre(self, fobj):
raise NotImplementedError
def write_function_post(self, fobj):
raise NotImplementedError
def write_extern(self, fobj):
raise NotImplementedError
def write_extern_end(self, fobj):
raise NotImplementedError
def write_shared(self, fobj):
raise NotImplementedError
def write_shared_end(self, fobj):
raise NotImplementedError
def write_function_def(self, fobj, func):
raise NotImplementedError
def write_function(self, fobj, func):
raise NotImplementedError
def write_function_prototype(self, fobj, func):
raise NotImplementedError
def write_boolean(self, fobj, name, value=False):
raise NotImplementedError
def write_enum(self, fobj, name, value, type='uint'):
raise NotImplementedError
def write_opaque_struct(self, fobj, name):
raise NotImplementedError
def write_alias(self, fobj, newn, decl):
raise NotImplementedError
class DGenerator(BaseDGenerator):
MODULE = 'glad'
LOADER = 'loader'
ENUMS = 'enums'
EXT = 'ext'
FUNCS = 'funcs'
TYPES = 'types'
FILE_EXTENSION = '.d'
TYPE_DICT = DTYPES
LOAD_GL_PREFIX = 'glad'
def write_imports(self, fobj, modules, private=True):
for mod in modules:
if private:
fobj.write('private ')
else:
fobj.write('public ')
fobj.write('import {}.{}.{};\n'.format(self.MODULE, self.spec.NAME, mod))
def write_selective_import(self, fobj, mod, imports):
if len(imports) == 0: return
fobj.write('public import {}.{}.{} :\n'.format(self.MODULE, self.spec.NAME, mod))
imports = set(imports)
last = len(imports)
for i, im in enumerate(imports, 1):
fobj.write(im)
if not i == last:
fobj.write(', ')
if (i % 5) == 0:
fobj.write('\n')
fobj.write(';\n\n')
def write_module(self, fobj, name):
fobj.write('module {}.{}.{};\n\n\n'.format(self.MODULE, self.spec.NAME, name))
def write_prototype_pre(self, fobj):
fobj.write('nothrow @nogc ')
self.write_extern(fobj)
def write_prototype_post(self, fobj):
self.write_extern_end(fobj)
def write_function_pre(self, fobj):
self.write_shared(fobj)
def write_function_post(self, fobj):
self.write_shared_end(fobj)
def write_extern(self, fobj):
fobj.write('extern(System) {\n')
def write_extern_end(self, fobj):
fobj.write('}\n')
def write_shared(self, fobj):
fobj.write('__gshared {\n')
def write_shared_end(self, fobj):
fobj.write('}\n')
def write_function_def(self, fobj, func):
fobj.write('{} {}('.format(func.proto.ret.to_d(), func.proto.name))
fobj.write(', '.join(param.type.to_d() for param in func.params))
fobj.write(');\n')
def write_function(self, fobj, func):
fobj.write('fp_{0} {0};\n'.format(func.proto.name))
def write_function_prototype(self, fobj, func):
fobj.write('alias fp_{} = {} function('
.format(func.proto.name, func.proto.ret.to_d()))
fobj.write(', '.join(param.type.to_d() for param in func.params))
fobj.write(');\n')
def write_boolean(self, fobj, name, value=False):
if value:
fobj.write('bool {} = true;\n'.format(name))
else:
fobj.write('bool {};\n'.format(name))
def write_enum(self, fobj, name, value, type='uint'):
if isinstance(value, basestring) and '"' in value:
type = 'const(char)*'
fobj.write('enum {} {} = {};\n'.format(type, name, value))
def write_opaque_struct(self, fobj, name):
fobj.write('struct _{name}; alias {name} = _{name}*;\n'.format(name=name))
def write_alias(self, fobj, newn, decl):
fobj.write('alias {} = {};\n'.format(newn, decl))

View file

@ -0,0 +1,90 @@
LOAD_OPENGL_DLL = '''
version(Windows) {
private import core.sys.windows.windows;
} else {
private import core.sys.posix.dlfcn;
}
version(Windows) {
private __gshared HMODULE libGL;
} else {
private __gshared void* libGL;
}
extern(System) private @nogc alias gladGetProcAddressPtrType = void* function(const(char)*);
private __gshared gladGetProcAddressPtrType gladGetProcAddressPtr;
%(pre)s
bool %(init)s() @nogc {
version(Windows) {
libGL = LoadLibraryA("opengl32.dll");
if(libGL !is null) {
gladGetProcAddressPtr = cast(typeof(gladGetProcAddressPtr))GetProcAddress(
libGL, "wglGetProcAddress");
return gladGetProcAddressPtr !is null;
}
return false;
} else {
version(OSX) {
enum const(char)*[] NAMES = [
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
];
} else {
enum const(char)*[] NAMES = ["libGL.so.1", "libGL.so"];
}
foreach(name; NAMES) {
libGL = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
if(libGL !is null) {
version(OSX) {
return true;
} else {
gladGetProcAddressPtr = cast(typeof(gladGetProcAddressPtr))dlsym(libGL,
"glXGetProcAddressARB");
return gladGetProcAddressPtr !is null;
}
}
}
return false;
}
}
%(pre)s
void* %(proc)s(const(char)* namez) @nogc {
if(libGL is null) return null;
void* result;
if(gladGetProcAddressPtr !is null) {
result = gladGetProcAddressPtr(namez);
}
if(result is null) {
version(Windows) {
result = GetProcAddress(libGL, namez);
} else {
result = dlsym(libGL, namez);
}
}
return result;
}
%(pre)s
void %(terminate)s() @nogc {
version(Windows) {
if(libGL !is null) {
FreeLibrary(libGL);
libGL = null;
}
} else {
if(libGL !is null) {
dlclose(libGL);
libGL = null;
}
}
}
'''

View file

@ -0,0 +1,39 @@
from glad.lang.common.loader import BaseLoader
_EGL_LOADER = '''
bool gladLoadEGL() {
return gladLoadEGL(x => eglGetProcAddress(x));
}
'''
_EGL_HAS_EXT = '''
private bool has_ext(const(char)* ext) @nogc {
return true;
}
'''
class EGLDLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('alias Loader = void* delegate(const(char)*);\n')
if not self.disabled:
fobj.write(_EGL_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write('\treturn true;\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_EGL_HAS_EXT)

View file

@ -0,0 +1,118 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.d.loader import LOAD_OPENGL_DLL
_OPENGL_LOADER = \
LOAD_OPENGL_DLL % {'pre':'private', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
bool gladLoadGL() {
bool status = false;
if(open_gl()) {
status = gladLoadGL(x => get_proc(x));
close_gl();
}
return status;
}
'''
_OPENGL_HAS_EXT = '''
static struct GLVersion { static int major = 0; static int minor = 0; }
private extern(C) char* strstr(const(char)*, const(char)*) @nogc;
private extern(C) int strcmp(const(char)*, const(char)*) @nogc;
private extern(C) int strncmp(const(char)*, const(char)*, size_t) @nogc;
private extern(C) size_t strlen(const(char)*) @nogc;
private bool has_ext(const(char)* ext) @nogc {
if(GLVersion.major < 3) {
const(char)* extensions = cast(const(char)*)glGetString(GL_EXTENSIONS);
const(char)* loc;
const(char)* terminator;
if(extensions is null || ext is null) {
return false;
}
while(1) {
loc = strstr(extensions, ext);
if(loc is null) {
return false;
}
terminator = loc + strlen(ext);
if((loc is extensions || *(loc - 1) == ' ') &&
(*terminator == ' ' || *terminator == '\\0')) {
return true;
}
extensions = terminator;
}
} else {
int num;
glGetIntegerv(GL_NUM_EXTENSIONS, &num);
for(uint i=0; i < cast(uint)num; i++) {
if(strcmp(cast(const(char)*)glGetStringi(GL_EXTENSIONS, i), ext) == 0) {
return true;
}
}
}
return false;
}
'''
_FIND_VERSION = '''
// Thank you @elmindreda
// https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
// https://github.com/glfw/glfw/blob/master/src/context.c#L36
int i;
const(char)* glversion;
const(char)*[] prefixes = [
"OpenGL ES-CM ".ptr,
"OpenGL ES-CL ".ptr,
"OpenGL ES ".ptr,
];
glversion = cast(const(char)*)glGetString(GL_VERSION);
if (glversion is null) return;
foreach(prefix; prefixes) {
size_t length = strlen(prefix);
if (strncmp(glversion, prefix, length) == 0) {
glversion += length;
break;
}
}
int major = glversion[0] - \'0\';
int minor = glversion[2] - \'0\';
GLVersion.major = major; GLVersion.minor = minor;
'''
class OpenGLDLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('alias Loader = void* delegate(const(char)*);\n')
if not self.disabled and 'gl' in self.apis:
fobj.write(_OPENGL_LOADER)
def write_begin_load(self, fobj):
fobj.write('\tglGetString = cast(typeof(glGetString))load("glGetString");\n')
fobj.write('\tif(glGetString is null) { return false; }\n')
fobj.write('\tif(glGetString(GL_VERSION) is null) { return false; }\n\n')
def write_end_load(self, fobj):
fobj.write('\treturn GLVersion.major != 0 || GLVersion.minor != 0;\n')
def write_find_core(self, fobj):
fobj.write(_FIND_VERSION)
def write_has_ext(self, fobj):
fobj.write(_OPENGL_HAS_EXT)

View file

@ -0,0 +1,49 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.d.loader import LOAD_OPENGL_DLL
_GLX_LOADER = \
LOAD_OPENGL_DLL % {'pre':'private', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
bool gladLoadGLX() {
bool status = false;
if(open_gl()) {
status = gladLoadGLX(x => get_proc(x));
close_gl();
}
return status;
}
'''
_GLX_HAS_EXT = '''
private bool has_ext(const(char)* name) @nogc {
return true;
}
'''
class GLXDLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('alias Loader = void* delegate(const(char)*);\n')
if not self.disabled:
fobj.write(_GLX_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write('\treturn true;\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_GLX_HAS_EXT)

View file

@ -0,0 +1,36 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.d.loader.glx import _GLX_LOADER
_WGL_LOADER = _GLX_LOADER.replace('GLX', 'WGL')
_WGL_HAS_EXT = '''
private bool has_ext(const(char)* name) @nogc {
return true;
}
'''
class WGLDLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('alias Loader = void* delegate(const(char)*);\n')
if not self.disabled:
fobj.write(_WGL_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write('\treturn true;\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_WGL_HAS_EXT)

View file

@ -0,0 +1,27 @@
from glad.lang.nim.loader.egl import EGLNimLoader
from glad.lang.nim.loader.gl import OpenGLNimLoader
from glad.lang.nim.loader.glx import GLXNimLoader
from glad.lang.nim.loader.wgl import WGLNimLoader
from glad.lang.nim.generator import NimGenerator
# TODO finish converting the egl, glx & wgl loaders to Nim
_specs = {
# 'egl': EGLNimLoader,
'gl': OpenGLNimLoader
# 'glx': GLXNimLoader,
# 'wgl': WGLNimLoader
}
_generators = {
'nim': NimGenerator,
}
def get_generator(name, spec):
gen = _generators.get(name)
loader = _specs.get(spec)
return gen, loader

View file

@ -0,0 +1,530 @@
from itertools import chain
import os.path
import sys
from glad.lang.common.generator import Generator
from glad.lang.common.util import makefiledir
if sys.version_info >= (3, 0):
from io import StringIO
basestring = str
else:
from StringIO import StringIO
def _gl_types(gen, f):
f.write('''
GLdebugProc* = proc (
source: GLenum,
typ: GLenum,
id: GLuint,
severity: GLenum,
length: GLsizei,
message: ptr GLchar,
userParam: pointer) {.stdcall.}
GLdebugProcArb* = proc (
source: GLenum,
typ: GLenum,
id: GLuint,
severity: GLenum,
len: GLsizei,
message: ptr GLchar,
userParam: pointer) {.stdcall.}
GLdebugProcAmd* = proc (
id: GLuint,
category: GLenum,
severity: GLenum,
len: GLsizei,
message: ptr GLchar,
userParam: pointer) {.stdcall.}
GLdebugProcKhr* = proc (
source, typ: GLenum,
id: GLuint,
severity: GLenum,
length: GLsizei,
message: ptr GLchar,
userParam: pointer) {.stdcall.}
''')
# TODO finish converting the egl, glx & wgl loaders to Nim
# def _egl_types(gen, f):
# def _glx_types(gen, f):
# def _wgl_types(gen, f):
NIMTYPES = {
'__other': {
'gl': _gl_types
# 'egl': _egl_types,
# 'glx': _glx_types,
# 'wgl': _wgl_types
},
'gl': {
'GLbitfield': 'uint32',
'GLboolean': 'bool',
'GLbyte': 'int8',
'GLchar': 'char',
'GLcharARB': 'byte',
'GLclampd': 'float64',
'GLclampf': 'float32',
'GLclampx': 'int32',
'GLdouble': 'float64',
'GLeglImageOES': 'distinct pointer',
'GLenum': 'uint32',
'GLfixed': 'int32',
'GLfloat': 'float32',
'GLhalf': 'uint16',
'GLhalfARB': 'uint16',
'GLhalfNV': 'uint16',
'GLhandleARB': 'uint32',
'GLint': 'int32',
'GLint64': 'int64',
'GLint64EXT': 'int64',
'GLintptr': 'int32',
'GLintptrARB': 'int32',
'GLshort': 'int16',
'GLsizei': 'int32',
'GLsizeiptr': 'int32',
'GLsizeiptrARB': 'int32',
'GLubyte': 'uint8',
'GLuint': 'uint32',
'GLuint64': 'uint64',
'GLuint64EXT': 'uint64',
'GLushort': 'uint16',
'GLvdpauSurfaceNV': 'int32',
'GLvoid': 'pointer',
'GLsync': 'distinct pointer',
'ClContext': 'distinct pointer',
'ClEvent': 'distinct pointer'
},
'egl': {
'EGLAttrib': 'int32',
'EGLAttribKHR': 'int32',
'EGLBoolean': 'bool',
'EGLClientBuffer': 'distinct pointer',
'EGLConfig': 'distinct pointer',
'EGLContext': 'distinct pointer',
'EGLDeviceEXT': 'distinct pointer',
'EGLDisplay': 'distinct pointer',
'EGLImage': 'distinct pointer',
'EGLImageKHR': 'distinct pointer',
'EGLNativeFileDescriptorKHR': 'int32',
'EGLOutputLayerEXT': 'distinct pointer',
'EGLOutputPortEXT': 'distinct pointer',
'EGLStreamKHR': 'distinct pointer',
'EGLSurface': 'distinct pointer',
'EGLSync': 'distinct pointer',
'EGLSyncKHR': 'distinct pointer',
'EGLSyncNV': 'distinct pointer',
'EGLTimeKHR': 'uint64',
'EGLTime': 'uint64',
'EGLTimeNV': 'uint64',
'EGLenum': 'uint32',
'EGLint': 'int32',
'EGLsizeiANDROID': 'distinct pointer',
'EGLuint64KHR': 'uint64',
'EGLuint64MESA': 'uint64',
'EGLuint64NV': 'uint64',
# '__eglMustCastToProperFunctionPointerType': 'void function()'
},
'glx': {
'GLbitfield': 'uint32',
'GLboolean': 'uint8',
'GLenum': 'uint32',
'GLfloat': 'float32',
'GLint': 'int32',
'GLintptr': 'int32',
'GLsizei': 'int32',
'GLsizeiptr': 'int32',
'GLubyte': 'uint8',
'GLuint': 'uint32'
},
'wgl': {
'GLbitfield': 'uint32',
'GLboolean': 'uint8',
'GLenum': 'uint32',
'GLfloat': 'float32',
'GLint': 'int32',
'GLsizei': 'int32',
'GLuint': 'uint32',
'GLushort': 'uint16',
'INT32': 'int32',
'INT64': 'int64'
},
'SpecialNumbers': {
'gl': [
('GL_FALSE', '0', None),
('GL_INVALID_INDEX', '0xFFFFFFFF', 'uint32'),
('GL_NONE', '0', None),
('GL_NONE_OES', '0', None),
('GL_NO_ERROR', '0', None),
('GL_ONE', '1', None),
('GL_TIMEOUT_IGNORED', '0xFFFFFFFFFFFFFFFF', 'uint64'),
('GL_TIMEOUT_IGNORED_APPLE', '0xFFFFFFFFFFFFFFFF', 'uint64'),
('GL_TRUE', '1', None),
('GL_VERSION_ES_CL_1_0', '1', None),
('GL_VERSION_ES_CL_1_1', '1', None),
('GL_VERSION_ES_CM_1_1', '1', None),
('GL_ZERO', '0', None),
],
'egl': [
# ('EGL_DONT_CARE', '-1', 'int'), ('EGL_UNKNOWN', '-1', 'int'),
# ('EGL_NO_NATIVE_FENCE_FD_ANDROID', '-1', 'uint'),
# ('EGL_DEPTH_ENCODING_NONE_NV', '0', 'uint'),
# ('EGL_NO_CONTEXT', 'cast(EGLContext)0', 'EGLContext'),
# ('EGL_NO_DEVICE_EXT', 'cast(EGLDeviceEXT)0', 'EGLDeviceEXT'),
# ('EGL_NO_DISPLAY', 'cast(EGLDisplay)0', 'EGLDisplay'),
# ('EGL_NO_IMAGE', 'cast(EGLImage)0', 'EGLImage'),
# ('EGL_NO_IMAGE_KHR', 'cast(EGLImageKHR)0', 'EGLImageKHR'),
# ('EGL_DEFAULT_DISPLAY', 'cast(EGLNativeDisplayType)0', 'EGLNativeDisplayType'),
# ('EGL_NO_FILE_DESCRIPTOR_KHR', 'cast(EGLNativeFileDescriptorKHR)-1', 'EGLNativeFileDescriptorKHR'),
# ('EGL_NO_OUTPUT_LAYER_EXT', 'cast(EGLOutputLayerEXT)0', 'EGLOutputLayerEXT'),
# ('EGL_NO_OUTPUT_PORT_EXT', 'cast(EGLOutputPortEXT)0', 'EGLOutputPortEXT'),
# ('EGL_NO_STREAM_KHR', 'cast(EGLStreamKHR)0', 'EGLStreamKHR'),
# ('EGL_NO_SURFACE', 'cast(EGLSurface)0', 'EGLSurface'),
# ('EGL_NO_SYNC', 'cast(EGLSync)0', 'EGLSync'),
# ('EGL_NO_SYNC_KHR', 'cast(EGLSyncKHR)0', 'EGLSyncKHR'),
# ('EGL_NO_SYNC_NV', 'cast(EGLSyncNV)0', 'EGLSyncNV'),
# ('EGL_DISPLAY_SCALING', '10000', 'uint'),
# ('EGL_FOREVER', '0xFFFFFFFFFFFFFFFF', 'ulong'),
# ('EGL_FOREVER_KHR', '0xFFFFFFFFFFFFFFFF', 'ulong'),
# ('EGL_FOREVER_NV', '0xFFFFFFFFFFFFFFFF', 'ulong')
],
'glx': [
# ('GLX_DONT_CARE', '0xFFFFFFFF', 'uint'),
# ('GLX_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB', '0', 'uint')
],
'wgl': [
# ('WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB', '0', 'uint'),
# ('WGL_FONT_LINES', '0', 'uint'),
# ('WGL_FONT_POLYGONS', 1, 'uint')
]
},
'SpecialEnumNames': {
'gl': {
'GL_BYTE': 'cGL_BYTE',
'GL_SHORT': 'cGL_SHORT',
'GL_INT': 'cGL_INT',
'GL_FLOAT': 'cGL_FLOAT',
'GL_DOUBLE': 'cGL_DOUBLE',
'GL_FIXED': 'cGL_FIXED'
},
'egl': {},
'glx': {},
'wgl': {}
},
'SpecialFuncNames': {
'gl': {
'glGetTransformFeedbacki_v': 'glGetTransformFeedbacki_v2'
},
'egl': {},
'glx': {},
'wgl': {}
}
}
class NimGenerator(Generator):
NAME = 'nim'
NAME_LONG = 'Nim'
MODULE = 'glad'
FILE_EXTENSION = '.nim'
TYPE_DICT = NIMTYPES
LOAD_GL_PREFIX = 'glad'
EXT_PREFIX = 'GLAD_'
def open(self):
self._f_gl = open(self.make_path(self.spec.NAME), 'w')
def close(self):
self._f_gl.close()
def generate_header(self):
self._f_gl.write('#[')
self._f_gl.write(self.header)
self._f_gl.write(']#\n\n')
self._f_gl.write('import strutils\n\n')
self._f_gl.write('var glVersionMajor, glVersionMinor: int\n\n')
def generate_loader(self, features, extensions):
f = self._f_gl
rfeatures = features
if self.spec.NAME in ('egl', 'wgl'):
features = {'egl': [], 'wgl': []}
self.loader.write(f)
self.loader.write_has_ext(f, self.get_version())
written = set()
for api, version in self.api.items():
# core load procs
for feature in features[api]:
f.write('proc load_{}(load: proc) =\n'
.format(feature.name))
if self.spec.NAME == 'gl':
f.write(' if not {}{}: return\n\n'.format(self.EXT_PREFIX,
feature.name))
for func in feature.functions:
self.write_func_definition(f, func)
f.write('\n\n')
# extension load procs
for ext in extensions[api]:
if len(list(ext.functions)) == 0 or ext.name in written:
continue
f.write('proc load_{}(load: proc) =\n'
.format(ext.name))
if self.spec.NAME == 'gl':
f.write(' if not {}{}: return\n'.format(self.EXT_PREFIX,
ext.name))
for func in ext.functions:
# even if they were in written we need to load it
self.write_func_definition(f, func)
f.write('\n\n')
written.add(ext.name)
# findExtensions proc
f.write('proc findExtensions{}() =\n'.format(api.upper()))
if self.spec.NAME == 'gl':
for ext in extensions[api]:
f.write(' {0}{1} = hasExt("{1}")\n'.format(self.EXT_PREFIX,
ext.name))
f.write('\n\n')
# findCore proc
f.write('proc findCore{}(glVersion: string) =\n'.format(api.upper()))
self.loader.write_find_core(f)
if self.spec.NAME == 'gl':
for feature in features[api]:
f.write(' {}{} = (major == {num[0]} and minor >= {num[1]}) or'
' major > {num[0]}\n'.format(self.EXT_PREFIX, feature.name,
num=feature.number))
f.write('\n\n')
# main loader proc
loadername = 'Load' if self.LOAD_GL_PREFIX else 'load'
f.write('proc {}{}{}*(load: proc): bool =\n'
.format(self.LOAD_GL_PREFIX, loadername, api.upper()))
self.loader.write_begin_load(f)
f.write(' findCore{}($glVersion)\n\n'.format(api.upper()))
for feature in features[api]:
f.write(' load_{}(load)\n'.format(feature.name))
f.write('\n findExtensions{}()\n\n'.format(api.upper()))
for ext in extensions[api]:
if len(list(ext.functions)) == 0:
continue
f.write(' load_{}(load);\n'.format(ext.name))
self.loader.write_end_load(f)
f.write('\n')
def write_func_definition(self, fobj, func):
func_name = self.map_func_name(func)
fobj.write(' {} = cast['.format(func_name))
self.write_function_declaration(fobj, func)
fobj.write('](load("{}"))\n'.format(func_name))
def map_func_name(self, func):
name = func.proto.name
m = self.TYPE_DICT['SpecialFuncNames'][self.spec.NAME]
return m[name] if name in m else name
def generate_types(self, types):
f = self._f_gl
f.write('# Types\ntype\n')
for ogl, d in sorted(self.TYPE_DICT[self.spec.NAME].items()):
f.write(' {}* = {}\n'.format(ogl, d))
self.TYPE_DICT['__other'][self.spec.NAME](self, f)
f.write('\n')
def generate_features(self, features):
self.write_enums(features)
self.write_funcs(features)
def write_enums(self, features):
f = self._f_gl
f.write('\n# Enums\nconst\n')
for v in sorted(self.TYPE_DICT['SpecialNumbers'][self.spec.NAME]):
self.write_enum(f, *v)
f.write('\n')
written = set()
for feature in features:
for enum in feature.enums:
if enum.group == 'SpecialNumbers':
written.add(enum)
continue
if not enum in written:
self.write_enum(f, enum.name, enum.value)
written.add(enum)
f.write('\n')
def write_funcs(self, features):
f = self._f_gl
f.write('\n# Functions\nvar\n')
if self.spec.NAME == 'gl':
for feature in features:
self.write_boolean(f, feature.name)
f.write('\n')
# TODO
if self.spec.NAME in ('egl', 'wgl'):
for feature in features:
for func in feature.functions:
self.write_function_def(f, func) # TODO
f.write('\n')
else:
self.write_functions(f, set(), set(), features)
f.write('\n\n')
# TODO
def write_function_def(self, fobj, func):
fobj.write('{} {}('.format(func.proto.ret.to_nim(), self.map_func_name(func)))
fobj.write(', '.join(param.type.to_nim() for param in func.params))
fobj.write(');\n')
def generate_extensions(self, extensions, enums, functions):
f = self._f_gl
write = set()
written = set(enum.name for enum in enums) | \
set(function.proto.name for function in functions)
f.write('# Extensions\nvar\n')
for ext in extensions:
if self.spec.NAME == 'gl' and not ext.name in written:
self.write_boolean(f, ext.name)
for enum in ext.enums:
if not enum.name in written and not enum.group == 'SpecialNumbers':
type = (None if enum.group == 'TransformFeedbackTokenNV'
else 'GLenum')
self.write_enum(f, enum.name, enum.value, type)
written.add(enum.name)
written.add(ext.name)
f.write('\n')
self.write_functions(f, write, written, extensions)
f.write('\n\n')
def write_functions(self, f, write, written, extensions):
for ext in extensions:
for func in ext.functions:
if not func.proto.name in written:
self.write_function_var(f, func)
write.add(func)
written.add(func.proto.name)
def write_function_var(self, fobj, func):
fobj.write(' {}*: '.format(self.map_func_name(func)))
self.write_function_declaration(fobj, func)
fobj.write('\n')
def write_function_declaration(self, fobj, func):
fobj.write('proc ('.format(self.map_func_name(func)))
fobj.write(', '.join('{}: {}'.format(self.to_nim_param_name(param.name),
param.type.to_nim())
for param in func.params))
fobj.write(')')
ret = func.proto.ret.to_nim()
if (ret != 'void'):
fobj.write(': {}'.format(ret))
fobj.write(' {.cdecl.}')
# TODO
# def write_function_var(self, fobj, func):
# fobj.write(' {} = cast[proc ('.format(func.proto.name))
# fobj.write(', '.join('{}: {}'.format(self.to_nim_param_name(param.name),
# param.type.to_nim())
# for param in func.params))
# fobj.write(')')
#
# ret = func.proto.ret.to_nim()
# if (ret != 'void'):
# fobj.write(': {}'.format(ret))
#
# fobj.write(' {.cdecl.}]')
# fobj.write(' (getProcAddress("{}"))\n'.format(func.proto.name))
NIM_KEYWORDS = [ # as of Nim 0.13.0
'addr', 'and', 'as', 'asm', 'atomic',
'bind', 'block', 'break',
'case', 'cast', 'concept', 'const', 'continue', 'converter',
'defer', 'discard', 'distinct', 'div', 'do',
'elif', 'else', 'end', 'enum', 'except', 'export',
'finally', 'for', 'from', 'func',
'generic',
'if', 'import', 'in', 'include', 'interface', 'is', 'isnot', 'iterator',
'let',
'macro', 'method', 'mixin', 'mod',
'nil', 'not', 'notin',
'object', 'of', 'or', 'out',
'proc', 'ptr',
'raise', 'ref', 'return',
'shl', 'shr', 'static',
'template', 'try', 'tuple', 'type',
'using',
'var',
'when', 'while', 'with', 'without',
'xor',
'yield'
]
def to_nim_param_name(self, name):
return '`{}`'.format(name) if name in self.NIM_KEYWORDS else name
def make_path(self, name):
path = os.path.join(self.path, self.MODULE.split('.')[-1],
name.split('.')[-1] + self.FILE_EXTENSION)
makefiledir(path)
return path
def write_boolean(self, fobj, name):
fobj.write(' {}{}*: bool\n'.format(self.EXT_PREFIX, name))
def write_enum(self, fobj, name, value, type='GLenum'):
fobj.write(' {}*'.format(self.map_enum_name(name)))
if type:
fobj.write(': {0} = {0}({1})'.format(type, value))
else:
fobj.write(' = {}'.format(value))
fobj.write('\n')
def map_enum_name(self, name):
m = self.TYPE_DICT['SpecialEnumNames'][self.spec.NAME]
return m[name] if name in m else name
def get_version(self):
return self.api[self.spec.NAME]

View file

@ -0,0 +1,90 @@
LOAD_OPENGL_DLL = '''
version(Windows) {
private import std.c.windows.windows;
} else {
private import core.sys.posix.dlfcn;
}
version(Windows) {
private __gshared HMODULE libGL;
} else {
private __gshared void* libGL;
}
extern(System) private @nogc alias gladGetProcAddressPtrType = void* function(const(char)*);
private __gshared gladGetProcAddressPtrType gladGetProcAddressPtr;
%(pre)s
bool %(init)s() @nogc {
version(Windows) {
libGL = LoadLibraryA("opengl32.dll");
if(libGL !is null) {
gladGetProcAddressPtr = cast(typeof(gladGetProcAddressPtr))GetProcAddress(
libGL, "wglGetProcAddress");
return gladGetProcAddressPtr !is null;
}
return false;
} else {
version(OSX) {
enum const(char)*[] NAMES = [
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
];
} else {
enum const(char)*[] NAMES = ["libGL.so.1", "libGL.so"];
}
foreach(name; NAMES) {
libGL = dlopen(name, RTLD_NOW | RTLD_GLOBAL);
if(libGL !is null) {
version(OSX) {
return true;
} else {
gladGetProcAddressPtr = cast(typeof(gladGetProcAddressPtr))dlsym(libGL,
"glXGetProcAddressARB");
return gladGetProcAddressPtr !is null;
}
}
}
return false;
}
}
%(pre)s
void* %(proc)s(const(char)* namez) @nogc {
if(libGL is null) return null;
void* result;
if(gladGetProcAddressPtr !is null) {
result = gladGetProcAddressPtr(namez);
}
if(result is null) {
version(Windows) {
result = GetProcAddress(libGL, namez);
} else {
result = dlsym(libGL, namez);
}
}
return result;
}
%(pre)s
void %(terminate)s() @nogc {
version(Windows) {
if(libGL !is null) {
FreeLibrary(libGL);
libGL = null;
}
} else {
if(libGL !is null) {
dlclose(libGL);
libGL = null;
}
}
}
'''

View file

@ -0,0 +1,40 @@
from glad.lang.common.loader import BaseLoader
# TODO this is just a quick initial conversion of the D loader
_EGL_LOADER = '''
bool gladLoadEGL() {
return gladLoadEGL(x => eglGetProcAddress(x))
}
'''
_EGL_HAS_EXT = '''
private bool has_ext(const(char)* ext) @nogc {
return true
}
'''
class EGLNimLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
if not self.disabled:
fobj.write(_EGL_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write(' return true\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_EGL_HAS_EXT)

View file

@ -0,0 +1,147 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.nim.loader import LOAD_OPENGL_DLL
_OPENGL_LOADER = \
LOAD_OPENGL_DLL % {'pre':'private', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
bool gladLoadGL()
bool status = false
if(open_gl())
status = gladLoadGL(x => get_proc(x))
close_gl()
return status
'''
_OPENGL_HAS_EXT_LT3 = '''proc hasExt(extname: string): bool =
if extname == nil:
return false
var extensions = $cast[cstring](glGetString(GL_EXTENSIONS))
if extensions == nil:
return false
var
loc, terminatorLoc: int
terminator: char
while true:
loc = extensions.find(extname)
if loc < 0:
return false
terminatorLoc = loc + extname.len
terminator = extensions[terminatorLoc]
if (loc == 0 or extensions[loc - 1] == ' ') and
(terminator == ' ' or terminator == '\\0'):
return true
extensions = extensions[terminatorLoc..^1]
'''
_OPENGL_HAS_EXT_GTE3 = '''proc hasExt(extname: string): bool =
if extname == nil:
return false
if glVersionMajor < 3:
var extensions = $cast[cstring](glGetString(GL_EXTENSIONS))
if extensions == nil:
return false
var
loc, terminatorLoc: int
terminator: char
while true:
loc = extensions.find(extname)
if loc < 0:
return false
terminatorLoc = loc + extname.len
terminator = extensions[terminatorLoc]
if (loc == 0 or extensions[loc - 1] == ' ') and
(terminator == ' ' or terminator == '\\0'):
return true
extensions = extensions[terminatorLoc..^1]
else:
var
num: GLint
s: cstring
glGetIntegerv(GL_NUM_EXTENSIONS, num.addr)
for i in 0..num-1:
s = cast[cstring](glGetStringi(GL_EXTENSIONS, GLuint(i)))
if s == extname:
return true
'''
_FIND_VERSION = ''' # Thank you @elmindreda
# https://github.com/elmindreda/greg/blob/master/templates/greg.c.in#L176
# https://github.com/glfw/glfw/blob/master/src/context.c#L36
var prefixes = ["OpenGL ES-CM ", "OpenGL ES-CL ", "OpenGL ES "]
var version = glVersion
for p in prefixes:
if version.startsWith(p):
version = version.replace(p)
break
var major = ord(glVersion[0]) - ord('0')
var minor = ord(glVersion[2]) - ord('0')
glVersionMajor = major
glVersionMinor = minor
'''
_BEGIN_LOAD = ''' glGetString = cast[proc (name: GLenum): ptr GLubyte {.cdecl.}](load("glGetString"))
if glGetString == nil: return false
var glVersion = cast[cstring](glGetString(GL_VERSION))
if glVersion == nil: return false
'''
class OpenGLNimLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
pass
# TODO
# if not self.disabled and 'gl' in self.apis:
# fobj.write(_OPENGL_LOADER)
def write_begin_load(self, fobj):
fobj.write(_BEGIN_LOAD)
def write_end_load(self, fobj):
fobj.write('\n return glVersionMajor != 0 or glVersionMinor != 0\n')
def write_find_core(self, fobj):
fobj.write(_FIND_VERSION)
def write_has_ext(self, fobj, apiversion):
if apiversion.major == 1 and apiversion.minor == 0:
return
if apiversion.major < 3:
fobj.write(_OPENGL_HAS_EXT_LT3)
else:
fobj.write(_OPENGL_HAS_EXT_GTE3)

View file

@ -0,0 +1,51 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.nim.loader import LOAD_OPENGL_DLL
# TODO this is just a quick initial conversion of the D loader
_GLX_LOADER = \
LOAD_OPENGL_DLL % {'pre':'private', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
bool gladLoadGLX() {
bool status = false
if(open_gl()) {
status = gladLoadGLX(x => get_proc(x))
close_gl()
}
return status
}
'''
_GLX_HAS_EXT = '''
private bool has_ext(const(char)* name) @nogc {
return true
}
'''
class GLXNimLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('alias Loader = void* delegate(const(char)*)\n')
if not self.disabled:
fobj.write(_GLX_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write(' return true\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_GLX_HAS_EXT)

View file

@ -0,0 +1,38 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.nim.loader.glx import _GLX_LOADER
# TODO this is just a quick initial conversion of the D loader
_WGL_LOADER = _GLX_LOADER.replace('GLX', 'WGL')
_WGL_HAS_EXT = '''
private bool has_ext(const(char)* name) @nogc {
return true;
}
'''
class WGLNimLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('alias Loader = void* delegate(const(char)*);\n')
if not self.disabled:
fobj.write(_WGL_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write(' return true\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_WGL_HAS_EXT)

View file

@ -0,0 +1,25 @@
from glad.lang.volt.loader.egl import EGLVoltLoader
from glad.lang.volt.loader.gl import OpenGLVoltLoader
from glad.lang.volt.loader.glx import GLXVoltLoader
from glad.lang.volt.loader.wgl import WGLVoltLoader
from glad.lang.volt.generator import VoltGenerator
_specs = {
'egl': EGLVoltLoader,
'gl': OpenGLVoltLoader,
'glx': GLXVoltLoader,
'wgl': WGLVoltLoader
}
_generators = {
'volt': VoltGenerator,
}
def get_generator(name, spec):
gen = _generators.get(name)
loader = _specs.get(spec)
return gen, loader

View file

@ -0,0 +1,86 @@
import sys
from glad.lang.d.generator import DGenerator
if sys.version_info >= (3, 0):
basestring = str
class VoltGenerator(DGenerator):
NAME = 'volt'
NAME_LONG = 'Volt'
MODULE = 'amp'
LOADER = 'loader'
ENUMS = 'enums'
EXT = 'ext'
FUNCS = 'funcs'
TYPES = 'types'
FILE_EXTENSION = '.volt'
API = ''
LOAD_GL_NAME = 'load'
@property
def PACKAGE(self):
return 'package'
def write_module(self, fobj, name):
if name == 'package':
fobj.write('module {}.{};\n\n'.format(self.MODULE, self.spec.NAME))
else:
DGenerator.write_module(self, fobj, name)
def write_prototype_pre(self, fobj):
fobj.write('extern(System) @loadDynamic {\n')
def write_prototype_post(self, fobj):
fobj.write('}\n')
def write_function_pre(self, fobj):
pass
def write_function_post(self, fobj):
pass
def write_shared(self, fobj):
fobj.write('global {\n')
def write_shared_end(self, fobj):
fobj.write('}\n')
def write_function(self, fobj, func):
pass
def write_function_prototype(self, fobj, func):
fobj.write('{} {}('
.format(func.proto.ret.to_volt(), func.proto.name))
fobj.write(', '.join(param.type.to_volt() for param in func.params))
fobj.write(');\n')
def write_boolean(self, fobj, name, **kwargs):
fobj.write('global bool {};\n'.format(name))
def write_enum(self, fobj, name, value, type_='uint'):
if isinstance(value, basestring):
if value.startswith('0x') and type_.startswith('u'):
value += 'U'
if len(value) > 12 and type_.startswith('u'):
value += 'L'
try:
v = int(value)
if v < 0:
type_ = 'int'
except ValueError:
pass
if isinstance(value, basestring) and '"' in value:
type_ = 'const(char)*'
fobj.write('enum {} {} = {};\n'.format(type_, name, value))
def write_opaque_struct(self, fobj, name):
fobj.write('struct _{name} {{}}\nalias {name} = _{name}*;\n'.format(name=name))

View file

@ -0,0 +1,64 @@
LOAD_OPENGL_DLL = '''
private global Library libGL;
extern(System) private alias gladGetProcAddressPtrType = void* function(const(char)*);
private global gladGetProcAddressPtrType gladGetProcAddressPtr;
%(pre)s
bool %(init)s() {
version(Windows) {
libGL = Library.load("opengl32.dll");
} else version(OSX) {
libGL = Library.loads([
"../Frameworks/OpenGL.framework/OpenGL",
"/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/OpenGL",
"/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"
]);
} else {
libGL = Library.loads(["libGL.so.1", "libGL.so"]);
}
if(libGL !is null) {
version(Windows) {
string sym = "wglGetProcAddress";
} else {
string sym = "glXGetProcAddressARB";
}
// returns null on OSX, but that's fine
gladGetProcAddressPtr = cast(typeof(gladGetProcAddressPtr))libGL.symbol(sym);
return true;
}
return false;
}
private struct StructToDg {
void* instance;
void* func;
}
%(pre)s
void* %(proc)s(string name) {
if(libGL is null) return null;
void* result;
if(gladGetProcAddressPtr !is null) {
// TODO: name.ptr
result = gladGetProcAddressPtr(name.ptr);
}
if(result is null) {
result = libGL.symbol(name);
}
return result;
}
%(pre)s
void %(terminate)s() {
if(libGL !is null) {
libGL.free();
}
return;
}
'''

View file

@ -0,0 +1,48 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.d.loader.egl import _EGL_HAS_EXT as _D_EGL_HAS_EXT
_EGL_LOADER = '''
private struct StructToDg {
void* instance;
void* func;
}
private void* get_proc(string name) {
return eglGetProcAddress(arg.ptr);
}
bool gladLoadEGL() {
StructToDg structToDg;
structToDg.func = cast(void*)get_proc;
auto dg = *cast(Loader*)&structToDg;
return gladLoadEGL(dg);
}
'''
_EGL_HAS_EXT = _D_EGL_HAS_EXT
class EGLVoltLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('import watt.library;\n')
if not self.disabled:
fobj.write(_EGL_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write('\treturn true;')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_EGL_HAS_EXT)

View file

@ -0,0 +1,60 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.volt.loader import LOAD_OPENGL_DLL
from glad.lang.d.loader.gl import _OPENGL_HAS_EXT as _D_OPENGL_HAS_EXT
_OPENGL_LOADER = \
LOAD_OPENGL_DLL % {'pre':'private', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
bool gladLoadGL() {
StructToDg structToDg;
structToDg.func = cast(void*)get_proc;
auto dg = *cast(Loader*)&structToDg;
bool status = false;
if(open_gl()) {
status = gladLoadGL(dg);
close_gl();
}
return status;
}
'''
_OPENGL_HAS_EXT = (
'global int GL_MAJOR = 0;\nglobal int GL_MINOR = 0;' +
'\n'.join(l for l in _D_OPENGL_HAS_EXT.replace('@nogc', '').splitlines() if 'struct' not in l)
.replace('GLVersion.major', 'GL_MAJOR') +
'\n\n'
)
class OpenGLVoltLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('import watt.library;\n')
if not self.disabled and 'gl' in self.apis:
fobj.write(_OPENGL_LOADER)
def write_begin_load(self, fobj):
fobj.write('\tglGetString = cast(typeof(glGetString))load("glGetString");\n')
fobj.write('\tif(glGetString is null) { return false; }\n')
fobj.write('\tif(glGetString(GL_VERSION) is null) { return false; }\n\n')
def write_end_load(self, fobj):
fobj.write('\treturn GL_MAJOR != 0 || GL_MINOR != 0;\n')
def write_find_core(self, fobj):
fobj.write('\tconst(char)* v = cast(const(char)*)glGetString(GL_VERSION);\n')
fobj.write('\tint major = v[0] - \'0\';\n')
fobj.write('\tint minor = v[2] - \'0\';\n')
fobj.write('\tGL_MAJOR = major; GL_MINOR = minor;\n')
def write_has_ext(self, fobj):
fobj.write(_OPENGL_HAS_EXT)

View file

@ -0,0 +1,47 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.volt.loader import LOAD_OPENGL_DLL
_GLX_LOADER = \
LOAD_OPENGL_DLL % {'pre':'private', 'init':'open_gl',
'proc':'get_proc', 'terminate':'close_gl'} + '''
bool gladLoadGLX() {
StructToDg structToDg;
structToDg.func = cast(void*)get_proc;
auto dg = *cast(Loader*)&structToDg;
bool status = false;
if(open_gl()) {
status = gladLoadGLX(dg);
close_gl();
}
return status;
}
'''
_GLX_HAS_EXT = '''
private bool has_ext(const(char)* name) {
return true;
}
'''
class GLXVoltLoader(BaseLoader):
def write(self, fobj):
fobj.write('import watt.library;\n')
if not self.disabled:
fobj.write(_GLX_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write('\treturn true;\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_GLX_HAS_EXT)

View file

@ -0,0 +1,35 @@
from glad.lang.common.loader import BaseLoader
from glad.lang.volt.loader.glx import _GLX_LOADER
_WGL_LOADER = _GLX_LOADER.replace('GLX', 'WGL')
_WGL_HAS_EXT = '''
private bool has_ext(const(char)* name) {
return true;
}
'''
class WGLVoltLoader(BaseLoader):
def write_header_end(self, fobj):
pass
def write_header(self, fobj):
pass
def write(self, fobj):
fobj.write('import watt.library;\n')
if not self.disabled:
fobj.write(_WGL_LOADER)
def write_begin_load(self, fobj):
pass
def write_end_load(self, fobj):
fobj.write('\treturn true;\n')
def write_find_core(self, fobj):
pass
def write_has_ext(self, fobj):
fobj.write(_WGL_HAS_EXT)

View file

@ -0,0 +1,112 @@
from contextlib import closing
import logging
import sys
if sys.version_info >= (3, 0):
_is_py3 = True
from urllib.request import build_opener, ContentTooShortError
else:
_is_py3 = False
from urllib2 import build_opener
from urllib import FancyURLopener
logger = logging.getLogger('glad.opener')
def build_urllib_opener(user_agent, *args, **kwargs):
if _is_py3:
return None
class UrllibURLOpener(FancyURLopener):
version = user_agent
return UrllibURLOpener(*args, **kwargs)
def _urlretrieve_with_opener(opener, url, filename, data=None):
if not _is_py3:
raise SyntaxError('Only call this in Python 3 code.')
# borrowed from the original implementation at urllib.request.urlretrieve.
with closing(opener.open(url, data=data)) as src:
headers = src.info()
with open(filename, 'wb') as dest:
result = filename, headers
bs = 1024*8
size = -1
read = 0
blocknum = 0
if "content-length" in headers:
size = int(headers["Content-Length"])
while True:
block = src.read(bs)
if not block:
break
read += len(block)
dest.write(block)
blocknum += 1
if size >= 0 and read < size:
raise ContentTooShortError(
'retrieval incomplete: got only %i out of %i bytes'
% (read, size), result)
return result
class URLOpener(object):
"""
Class to download/find Khronos related files, like
the official specs and khrplatform.h.
Can also be used to download files, exists mainly because of
Python 2 and Python 3 incompatibilities.
"""
def __init__(self, user_agent='Mozilla/5.0'):
# the urllib2/urllib.request opener
self.opener = build_opener()
self.opener.addheaders = [('User-agent', user_agent)]
# the urllib opener (Python 2 only)
self.opener2 = build_urllib_opener(user_agent)
def urlopen(self, url, data=None, *args, **kwargs):
"""
Same as urllib2.urlopen or urllib.request.urlopen,
the only difference is that it links to the internal opener.
"""
logger.info('opening: \'%s\'', url)
if data is None:
return self.opener.open(url)
return self.opener.open(url, data)
def urlretrieve(self, url, filename, data=None):
"""
Similar to urllib.urlretrieve or urllib.request.urlretrieve
only that *filname* is required.
:param url: URL to download.
:param filename: Filename to save the content to.
:param data: Valid URL-encoded data.
:return: Tuple containing path and headers.
"""
logger.info('saving: \'%s\' to \'%s\'', url, filename)
if _is_py3:
return _urlretrieve_with_opener(self.opener, url, filename, data=data)
return self.opener2.retrieve(url, filename, data=data)
# just a singleton helper:
_default = None
@classmethod
def default(cls):
if cls._default is None:
cls._default = cls()
return cls._default

View file

@ -0,0 +1,356 @@
try:
from lxml import etree
from lxml.etree import ETCompatXMLParser as parser
def xml_fromstring(argument):
return etree.fromstring(argument, parser=parser())
def xml_frompath(path):
return etree.parse(path, parser=parser()).getroot()
except ImportError:
try:
import xml.etree.cElementTree as etree
except ImportError:
import xml.etree.ElementTree as etree
def xml_fromstring(argument):
return etree.fromstring(argument)
def xml_frompath(path):
return etree.parse(path).getroot()
from collections import defaultdict, OrderedDict
from contextlib import closing
from itertools import chain
import re
from glad.opener import URLOpener
_ARRAY_RE = re.compile(r'\[\d*\]')
class Spec(object):
API = 'https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/'
NAME = ''
def __init__(self, root):
self.root = root
self._types = None
self._groups = None
self._enums = None
self._commands = None
self._features = None
self._extensions = None
@classmethod
def from_url(cls, url, opener=None):
if opener is None:
opener = URLOpener.default()
with closing(opener.urlopen(url)) as f:
raw = f.read()
return cls(xml_fromstring(raw))
@classmethod
def from_svn(cls, opener=None):
return cls.from_url(cls.API + cls.NAME + '.xml', opener=opener)
@classmethod
def fromstring(cls, string):
return cls(xml_fromstring(string))
@classmethod
def from_file(cls, path):
return cls(xml_frompath(path))
@property
def comment(self):
return self.root.find('comment').text
@property
def types(self):
if self._types is None:
self._types = [Type(element) for element in
self.root.find('types').iter('type')]
return self._types
@property
def groups(self):
if self._groups is None:
self._groups = dict([(element.attrib['name'], Group(element))
for element in self.root.find('groups')])
return self._groups
@property
def commands(self):
if self._commands is None:
self._commands = dict([(element.find('proto').find('name').text,
Command(element, self))
for element in self.root.find('commands')])
return self._commands
@property
def enums(self):
if self._enums is not None:
return self._enums
self._enums = dict()
for element in self.root.iter('enums'):
namespace = element.attrib['namespace']
type_ = element.get('type')
group = element.get('group')
vendor = element.get('vendor')
comment = element.get('comment', '')
for enum in element:
if enum.tag == 'unused':
continue
assert enum.tag == 'enum'
name = enum.attrib['name']
self._enums[name] = Enum(name, enum.attrib['value'], namespace,
type_, group, vendor, comment)
return self._enums
@property
def features(self):
if self._features is not None:
return self._features
self._features = defaultdict(OrderedDict)
for element in self.root.iter('feature'):
num = tuple(map(int, element.attrib['number'].split('.')))
self._features[element.attrib['api']][num] = Feature(element, self)
return self._features
@property
def extensions(self):
if self._extensions is not None:
return self._extensions
self._extensions = defaultdict(dict)
for element in self.root.find('extensions'):
for api in element.attrib['supported'].split('|'):
self._extensions[api][element.attrib['name']] = Extension(element, self)
return self._extensions
class Type(object):
def __init__(self, element):
apientry = element.find('apientry')
if apientry is not None:
apientry.text = 'APIENTRY'
self.raw = ''.join(element.itertext())
self.api = element.get('api')
self.name = element.get('name') or element.find('name').text
@property
def is_preprocessor(self):
return '#' in self.raw
class Group(object):
def __init__(self, element):
self.name = element.attrib['name']
self.enums = [enum.attrib['name'] for enum in element]
class Enum(object):
def __init__(self, name, value, namespace, type_=None,
group=None, vendor=None, comment=''):
self.name = name
self.value = value
self.namespace = namespace
self.type = type_
self.group = group
self.vendor = vendor
self.comment = comment
def __hash__(self):
return hash(self.name)
def __str__(self):
return self.name
__repr__ = __str__
class Command(object):
def __init__(self, element, spec):
self.proto = Proto(element.find('proto'))
self.params = [Param(ele, spec) for ele in element.iter('param')]
def __hash__(self):
return hash(self.proto.name)
def __str__(self):
return '{self.proto.name}'.format(self=self)
__repr__ = __str__
class Proto(object):
def __init__(self, element):
self.name = element.find('name').text
self.ret = OGLType(element)
def __str__(self):
return '{self.ret} {self.name}'.format(self=self)
class Param(object):
def __init__(self, element, spec):
self.group = element.get('group')
self.type = OGLType(element)
self.name = element.find('name').text.strip('*')
def __str__(self):
return '{0!r} {1}'.format(self.type, self.name)
class OGLType(object):
def __init__(self, element):
self.element = element
self.raw = ''.join(element.itertext()).strip()
self.name = element.find('name').text
self.type = (self.raw.replace('const', '').replace('unsigned', '')
.replace('struct', '').strip().split(None, 1)[0]
if element.find('ptype') is None else element.find('ptype').text)
# 0 if no pointer, 1 if *, 2 if **
self.is_pointer = 0 if self.raw is None else self.raw.count('*')
# it can be a pointer to an array, or just an array
self.is_pointer += len(_ARRAY_RE.findall(self.raw))
self.is_const = False if self.raw is None else 'const' in self.raw
self.is_unsigned = False if self.raw is None else 'unsigned' in self.raw
if 'struct' in self.raw and 'struct' not in self.type:
self.type = 'struct {}'.format(self.type)
ptype = element.find('ptype')
self.ptype = ptype.text if ptype is not None else None
def to_d(self):
if self.is_pointer > 1 and self.is_const:
s = 'const({}{}*)'.format('u' if self.is_unsigned else '', self.type)
s += '*' * (self.is_pointer - 1)
else:
t = '{}{}'.format('u' if self.is_unsigned else '', self.type)
s = 'const({})'.format(t) if self.is_const else t
s += '*' * self.is_pointer
return s.replace('struct ', '')
to_volt = to_d
def to_c(self):
result = ''
for text in self.element.itertext():
if text == self.name:
# yup * is sometimes part of the name
result += '*' * text.count('*')
else:
result += text
result = _ARRAY_RE.sub('*', result)
return result.strip()
NIM_POINTER_MAP = {
'void': 'pointer',
'GLchar': 'cstring',
'struct _cl_context': 'ClContext',
'struct _cl_event': 'ClEvent'
}
def to_nim(self):
if self.is_pointer == 2:
s = 'cstringArray' if self.type == 'GLchar' else 'ptr pointer'
else:
s = self.type
if self.is_pointer == 1:
default = 'ptr ' + s
s = self.NIM_POINTER_MAP.get(s, default)
return s
__str__ = to_d
__repr__ = __str__
class Extension(object):
def __init__(self, element, spec):
self.name = element.attrib['name']
self.require = []
for required in chain.from_iterable(element.findall('require')):
if required.tag == 'type':
continue
data = {'enum': spec.enums, 'command': spec.commands}[required.tag]
try:
self.require.append(data[required.attrib['name']])
except KeyError:
pass # TODO
@property
def enums(self):
for r in self.require:
if isinstance(r, Enum):
yield r
@property
def functions(self):
for r in self.require:
if isinstance(r, Command):
yield r
def __hash__(self):
return hash(self.name)
def __str__(self):
return self.name
__repr__ = __str__
class Feature(Extension):
def __init__(self, element, spec):
Extension.__init__(self, element, spec)
self.spec = spec
# not every spec has a ._remove member, but there shouldn't be a remove
# tag without that member, if there is, blame me!
for removed in chain.from_iterable(element.findall('remove')):
if removed.tag == 'type':
continue
data = {'enum': spec.enums, 'command': spec.commands}[removed.tag]
try:
spec._remove.add(data[removed.attrib['name']])
except KeyError:
pass # TODO
self.number = tuple(map(int, element.attrib['number'].split('.')))
self.api = element.attrib['api']
def __str__(self):
return '{self.name}@{self.number!r}'.format(self=self)
@property
def enums(self):
for enum in super(Feature, self).enums:
if enum not in getattr(self.spec, 'removed', []):
yield enum
@property
def functions(self):
for func in super(Feature, self).functions:
if func not in getattr(self.spec, 'removed', []):
yield func
__repr__ = __str__

View file

@ -0,0 +1,54 @@
from glad.parse import Spec
class EGLSpec(Spec):
API = 'https://raw.githubusercontent.com/KhronosGroup/EGL-Registry/master/api/'
NAME = 'egl'
class GLSpec(Spec):
API = 'https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/master/xml/'
NAME = 'gl'
def __init__(self, root):
Spec.__init__(self, root)
self._profile = 'compatibility'
self._remove = set()
@property
def profile(self):
return self._profile
@profile.setter
def profile(self, value):
if value not in ('core', 'compatibility'):
raise ValueError('profile must either be core or compatibility')
self._profile = value
@property
def removed(self):
if self._profile == 'core':
return frozenset(self._remove)
return frozenset()
class GLXSpec(Spec):
API = 'https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/master/xml/'
NAME = 'glx'
class WGLSpec(Spec):
API = 'https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry/master/xml/'
NAME = 'wgl'
SPECS = dict()
# reflection to fill SPECS
import sys
import inspect
for name, cls in inspect.getmembers(sys.modules[__name__], inspect.isclass):
if issubclass(cls, Spec):
SPECS[cls.NAME] = cls

View file

@ -0,0 +1,14 @@
_API_NAMES = {
'egl': 'EGL',
'gl': 'OpenGL',
'gles1': 'OpenGL ES',
'gles2': 'OpenGL ES',
'glx': 'GLX',
'wgl': 'WGL',
}
def api_name(api):
api = api.lower()
return _API_NAMES[api]