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,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)