Created
May 14, 2013 20:12
-
-
Save rubber-duck/5579103 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import xml.etree.ElementTree as ET | |
import string | |
core_3_0 = [ | |
"VERSION_1_0", | |
"VERSION_1_1", | |
"VERSION_1_2", | |
"VERSION_1_3", | |
"VERSION_1_4", | |
"VERSION_1_5", | |
"VERSION_2_0", | |
"VERSION_2_1", | |
"VERSION_3_0", | |
"ARB_vertex_array_object", | |
"ARB_texture_rg", | |
"ARB_texture_compression_rgtc", | |
"ARB_map_buffer_range", | |
"ARB_half_float_vertex", | |
"ARB_framebuffer_sRGB", | |
"ARB_framebuffer_object", | |
"ARB_depth_buffer_float"] | |
core_3_1 = [ | |
"VERSION_3_1", | |
"ARB_uniform_buffer_object", | |
"ARB_copy_buffer"] | |
core_3_2 = [ | |
"VERSION_3_2", | |
"ARB_depth_clamp", | |
"ARB_draw_elements_base_vertex", | |
"ARB_fragment_coord_conventions", | |
"ARB_provoking_vertex", | |
"ARB_seamless_cube_map", | |
"ARB_sync", | |
"ARB_texture_multisample", | |
"ARB_vertex_array_bgra"] | |
core_3_3 = [ | |
"VERSION_3_3", | |
"ARB_texture_rgb10_a2ui", | |
"ARB_texture_swizzle", | |
"ARB_timer_query", | |
"ARB_vertex_type_2_10_10_10_rev", | |
"ARB_blend_func_extended", | |
"ARB_occlusion_query2", | |
"ARB_sampler_objects"] | |
core_4_0 = [ | |
"VERSION_4_0", | |
"ARB_draw_indirect", | |
"ARB_gpu_shader5", | |
"ARB_gpu_shader_fp64", | |
"ARB_shader_subroutine", | |
"ARB_tessellation_shader", | |
"ARB_transform_feedback2", | |
"ARB_transform_feedback3"] | |
core_4_1 = [ | |
"VERSION_4_1", | |
"ARB_ES2_compatibility", | |
"ARB_get_program_binary", | |
"ARB_separate_shader_objects", | |
"ARB_vertex_attrib_64bit", | |
"ARB_viewport_array"] | |
core_4_2 = [ | |
"VERSION_4_2", | |
"ARB_base_instance", | |
"ARB_shading_language_420pack", | |
"ARB_transform_feedback_instanced", | |
"ARB_compressed_texture_pixel_storage", | |
"ARB_conservative_depth", | |
"ARB_internalformat_query", | |
"ARB_map_buffer_alignment", | |
"ARB_shader_atomic_counters", | |
"ARB_shader_image_load_store", | |
"ARB_shading_language_packing", | |
"ARB_texture_storage"] | |
core_4_3 = [ | |
"VERSION_4_3", | |
"KHR_debug", | |
"ARB_arrays_of_arrays", | |
"ARB_clear_buffer_object", | |
"ARB_compute_shader", | |
"ARB_copy_image", | |
"ARB_ES3_compatibility", | |
"ARB_explicit_uniform_location", | |
"ARB_fragment_layer_viewport", | |
"ARB_framebuffer_no_attachments", | |
"ARB_internalformat_query2", | |
"ARB_invalidate_subdata", | |
"ARB_multi_draw_indirect", | |
"ARB_program_interface_query", | |
"ARB_shader_image_size", | |
"ARB_shader_storage_buffer_object", | |
"ARB_stencil_texturing", | |
"ARB_texture_buffer_range", | |
"ARB_texture_query_levels", | |
"ARB_texture_storage_multisample", | |
"ARB_texture_view", | |
"ARB_vertex_attrib_binding"] | |
core_profile = reduce(lambda a, b: a + b, [core_3_0, core_3_1, core_3_2, core_3_3, core_4_0, core_4_1, core_4_2, core_4_3]) | |
dtypemap = { | |
"GLenum" : "uint", | |
"GLboolean" : "ubyte", | |
"GLbitfield" : "uint", | |
"GLbyte" : "byte", | |
"GLshort" : "short", | |
"GLint" : "int", | |
"GLsizei" : "int", | |
"GLubyte" : "ubyte", | |
"GLushort" : "ushort", | |
"GLuint" : "uint", | |
"GLfloat" : "float", | |
"GLclampf" : "float", | |
"GLdouble" : "double", | |
"GLclampd" : "double", | |
"GLvoid" : "void", | |
"GLchar" : "char", | |
"GLintptr" : "ptrdiff_t", | |
"GLsizeiptr" : "ptrdiff_t", | |
"GLintptrARB" : "ptrdiff_t", | |
"GLsizeiptrARB" : "ptrdiff_t", | |
"GLcharARB" : "char", | |
"GLhandleARB" : "uint", | |
"GLhalfARB" : "ushort", | |
"GLhalfNV" : "ushort", | |
"GLint64EXT" : "long", | |
"GLuint64EXT" : "ulont", | |
"GLint64" : "long", | |
"GLuint64" : "ulong", | |
"GLsync" : "void*", | |
"struct _cl_context " : "void", | |
"struct _cl_event " : "void", | |
"_GLfuncptr" : "void", | |
"GLchar* const" : "char*", | |
"GLvoid* const" : "void*", | |
"const GLubyte " : "ubyte", | |
"GLDEBUGPROCAMD" : "DebugProcAmd", | |
"GLDEBUGPROCARB" : "DebugProcArb", | |
"GLDEBUGPROC" : "DebugProc", | |
"GLvdpauSurfaceNV" : "void", | |
"void" : "void"} | |
def to_dtype(spec_type): | |
ptr_type = spec_type[-1] == "*" | |
if ptr_type: | |
return dtypemap[spec_type[:-1]] + "*" | |
else: | |
return dtypemap[spec_type] | |
def to_cfunction(name): | |
"Convert spec function name to c style function name (add gl prefix)" | |
return "gl" + name | |
def to_dfunction(name): | |
"Convert spec function name to d style function name (camelCase, no gl prefix)" | |
return name[0].lower() + name[1:] | |
def to_dconst(name): | |
"Convert spec constant name to d style const name (camelCase)" | |
return name | |
class FunctionArgument: | |
def __init__(self, node): | |
"Read function argument definition from XML spec param node" | |
self.name = node.attrib["name"] | |
self.name = self.name if self.name != "ref" else "refp" | |
self.kind = node.attrib["kind"] | |
self.dtype = to_dtype(node.attrib["type"]) | |
self.is_input = node.attrib["input"] | |
def d_declaration_str(self): | |
"Return D argument function declaration string for this argument" | |
arg_const = "const" if self.is_input and self.kind == "array" else "" | |
arg_ptr = "*" if self.kind == "array" or self.kind == "reference" else "" | |
return ("%s %s%s %s" % (arg_const, self.dtype, arg_ptr, self.name)).strip() | |
class Function: | |
def __init__(self, node): | |
self.name = node.attrib["name"] | |
self.dname = to_dfunction(self.name) | |
self.cname = to_cfunction(self.name) | |
self.return_dtype = to_dtype(node.attrib["return"]) | |
self.removed = node.get("removed") | |
self.version = node.get("version") | |
self.category = node.attrib["category"] | |
self.profile = node.get("profile") | |
self.args = [] | |
for arg in node: | |
assert arg.tag == "param" | |
self.args.append(FunctionArgument(arg)) | |
def d_declaration_str(self): | |
"Return D function declaration string" | |
return "%s function (%s) %s;" % (self.return_dtype, ", ".join([a.d_declaration_str() for a in self.args]), self.dname) | |
def d_load_str(self): | |
"Return D statement that loads this function in to global delegate" | |
return "bindFunc(%s, `%s`);" % (self.dname, self.cname) | |
class Enum: | |
def __init__(self, node): | |
self.name = node.attrib["name"] | |
self.dname = to_dconst(self.name) | |
self.ref = node.get("ref") | |
self.version = node.get("version") | |
if self.ref == None: | |
self.value = node.attrib["value"] | |
self.value = "0xFFFFFFFF" if self.value == "0xFFFFFFFFFFFFFFFF" else self.value | |
else: | |
self.value = None | |
self.removed = node.get("removed") | |
def d_declaration_str(self, enum_map): | |
return "%s = %s" % ((self.dname, self.value) if self.ref == None else (self.dname, enum_map[self.ref].value)) | |
class Spec: | |
def __init__(self, source): | |
spec = ET.parse(source).getroot() | |
for td in spec.find("typemap"): | |
if td.attrib["typename"] == "void" or td.attrib["C-lang"][:3] == "GLU": | |
continue | |
dtypemap[td.attrib["typename"]] = to_dtype(td.attrib["C-lang"]) | |
self.enums = dict((e.name, e) for e in [Enum(e) for e in spec.find("enumerations")]) | |
self.functions = [Function(f) for f in spec.find("functions").find("function-defs")] | |
def write_core_d_module(self, target): | |
# module header | |
target.write("module toybox.render.gl.gl;\nimport toybox.platform;\n\n\n") | |
# write debugging | |
target.write("/* Debugging callback type */\n") | |
target.write("alias extern(System) void function(uint source, uint type, uint id, uint severity, int length, const char* message, void* userParam) DebugProc;\n\n\n") | |
# write enum constants | |
target.write("/* Core profile constants (removed constants removed in 3.1 and extension constants are in glext) */\n") | |
target.write("enum : uint\n{\n") | |
enums_len = len(self.enums) | |
for enum in self.enums.values(): | |
# only generating 3.1 core profile (ignore ext and removed enums) | |
if enum.removed == "3.1" or enum.version == None: | |
continue | |
target.write("\t") | |
target.write(enum.d_declaration_str(self.enums)) | |
target.write(",\n") | |
target.write("\n};\n\n") | |
# group functions by category | |
fncategories = {} | |
for fn in self.functions: | |
if not fn.category in fncategories: | |
fncategories[fn.category] = [] | |
# skip compatibility profile and non core extensions | |
if fn.profile == "compatibility" or fn.version == None or not fn.category in core_profile: | |
continue | |
fncategories[fn.category].append(fn) | |
# write functions | |
target.write("/* GL functions */\n") | |
target.write("__gshared \n{\n\textern (C)\n\t{\n"); | |
for cat, fns in fncategories.items(): | |
if len(fns) > 0: | |
target.write("\t\t/*%s*/\n" % cat) | |
for fn in fns: | |
target.write("\t\t") | |
target.write(fn.d_declaration_str()) | |
target.write("\n") | |
target.write("\t};\n};\n\n") | |
# write function loader | |
target.write("void loadLibrary(int profile)\n{\n\tassert(profile > 30 && profile < 43);\n") | |
profile_map = [ | |
("30", core_3_0), | |
("31", core_3_1), | |
("32", core_3_2), | |
("33", core_3_3), | |
("40", core_4_0), | |
("41", core_4_1), | |
("42", core_4_2), | |
("43", core_4_3) | |
] | |
for profile, categories in profile_map: | |
target.write("\tif(profile >= %s)\n\t{\n" % profile) | |
for category in categories: | |
if not category in fncategories: | |
continue | |
target.write("\t\t/*%s*/\n" % category) | |
for function in fncategories[category]: | |
target.write("\t\t") | |
target.write(function.d_load_str()) | |
target.write("\n") | |
target.write("\t};\n") | |
target.write("}") | |
Spec("opengl.xml").write_core_d_module(file("gl.d", "w")) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment