import xml.etree.ElementTree as et from argparse import ArgumentParser from datetime import datetime #--------------------------------------------------------------- #NOTE: get args #--------------------------------------------------------------- parser = ArgumentParser() parser.add_argument("-s", "--spec") parser.add_argument("-d", "--directory") args = parser.parse_args() apiName = 'gl_api' loaderName = 'gl_loader' apiPath = args.directory + '/' + apiName + '.h' loaderHeaderPath = args.directory + '/' + loaderName + '.h' loaderCPath = args.directory + '/' + loaderName + '.c' #--------------------------------------------------------------- #NOTE: gather all GL functions in GL 4.1, 4.3, and GLES 3.0 and 3.1 #--------------------------------------------------------------- def gather_api(tree, api, version): procs = [] for feature in tree.iterfind('feature[@api="'+ api +'"]'): if float(feature.get('number')) > version: break for require in feature.iter('require'): if require.get('profile') == 'compatibility': continue for command in require.iter('command'): procs.append(command.get('name')) for remove in feature.iter('remove'): for command in remove.iter('command'): procs.remove(command.get('name')) return(procs) tree = et.parse(args.spec) gl41 = gather_api(tree, 'gl', 4.1) gl43 = gather_api(tree, 'gl', 4.3) gl44 = gather_api(tree, 'gl', 4.4) gles30 = gather_api(tree, 'gles2', 3.1) gles31 = gather_api(tree, 'gles2', 3.2) glall = list(set().union(gl41, gl43, gl44, gles30, gles31)) #--------------------------------------------------------------- # helpers #--------------------------------------------------------------- def emit_doc(f, name, ext): f.write("/********************************************************\n") f.write("*\n") f.write("*\t@file: " + name + ext + '\n') f.write("*\t@note: auto-generated by glapi.py from gl.xml\n") f.write("*\t@date: %s\n" % datetime.now().strftime("%d/%m%Y")) f.write("*\n") f.write("*********************************************************/\n") def emit_begin_guard(f, name): guard = '__' + name.upper() + '_H__' f.write("#ifndef " + guard + "\n") f.write("#define " + guard + "\n\n") def emit_end_guard(f, name): guard = '__' + name.upper() + '_H__' f.write("#endif // " + guard + "\n") def remove_prefix(s, prefix): if s.startswith(prefix): return s[len(prefix):] #--------------------------------------------------------------- # Generate GL API header file #--------------------------------------------------------------- f = open(apiPath, 'w') emit_doc(f, apiName, '.h') emit_begin_guard(f, apiName) f.write('#include"GL/glcorearb.h"\n') f.write('#include"GLES3/gl32.h"\n\n') # generate interface struct f.write('typedef struct mg_gl_api\n{\n') for func in glall: f.write('\t' + 'PFN' + func.upper() + 'PROC ' + remove_prefix(func, 'gl') + ';\n') f.write('} mg_gl_api;\n\n') # generate interface macros # TODO guard for different api/versions and only #define functions present in desired version f.write("MP_API mg_gl_api* mg_gl_get_api(void);\n\n") for func in glall: f.write('#define ' + func + ' mg_gl_get_api()->' + remove_prefix(func, 'gl') + '\n') emit_end_guard(f, apiName) f.close() #--------------------------------------------------------------- # Generate GL loader header #--------------------------------------------------------------- f = open(loaderHeaderPath, 'w') emit_doc(f, loaderName, '.h') emit_begin_guard(f, loaderName) f.write('#include"gl_api.h"\n\n') f.write("typedef void*(*mg_gl_load_proc)(const char* name);\n\n") f.write("void mg_gl_load_gl41(mg_gl_api* api, mg_gl_load_proc loadProc);\n") f.write("void mg_gl_load_gl43(mg_gl_api* api, mg_gl_load_proc loadProc);\n") f.write("void mg_gl_load_gl44(mg_gl_api* api, mg_gl_load_proc loadProc);\n") f.write("void mg_gl_load_gles30(mg_gl_api* api, mg_gl_load_proc loadProc);\n") f.write("void mg_gl_load_gles31(mg_gl_api* api, mg_gl_load_proc loadProc);\n\n") f.write("void mg_gl_select_api(mg_gl_api* api);\n\n") emit_end_guard(f, loaderName) f.close() #--------------------------------------------------------------- # Generate GL loader code #--------------------------------------------------------------- def emit_loader(f, name, procs): f.write('void mg_gl_load_'+ name +'(mg_gl_api* api, mg_gl_load_proc loadProc)\n') f.write("{\n") for proc in procs: f.write('\tapi->' + remove_prefix(proc, 'gl') + ' = loadProc("' + proc + '");\n') f.write("}\n\n") f = open(loaderCPath, 'w') emit_doc(f, loaderName, '.c') f.write('#include"' + loaderName + '.h"\n') f.write('#include"platform.h"\n\n') f.write("mp_thread_local mg_gl_api* __mgGLAPI = 0;\n\n") emit_loader(f, 'gl41', gl41) emit_loader(f, 'gl43', gl43) emit_loader(f, 'gl44', gl44) emit_loader(f, 'gles30', gles30) emit_loader(f, 'gles31', gles31) f.write("void mg_gl_select_api(mg_gl_api* api){ __mgGLAPI = api; }\n") f.write("mg_gl_api* mg_gl_get_api(void) { return(__mgGLAPI); }\n\n") f.close()