From 587b88ea9730cee089428b6491b9b166a1793173 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Tue, 21 Nov 2017 22:13:23 +0200 Subject: [PATCH] Be much more strict about extension support OpenGL ES has added bits and pieces of full OpenGL functionality, an the extension generator was thinking an extension was supported when really only a few tokens from it were. Now all tokens must be either supported or explicitly marked as optional for the extension to be made available. Some features may be temporarily unavailable on OpenGL ES builds as I go over the extensions and decide how to fix them. --- extensions/arb_depth_texture.glext | 2 + extensions/arb_geometry_shader4.glext | 12 +- extensions/arb_shader_objects.glext | 10 + extensions/arb_shadow.glext | 3 + extensions/arb_texture_cube_map.glext | 4 +- extensions/arb_texture_float.glext | 12 +- extensions/arb_vertex_buffer_object.glext | 11 +- extensions/arb_vertex_shader.glext | 5 +- extensions/ext_bgra.glext | 1 - extensions/ext_blend_minmax.glext | 1 + extensions/ext_blend_subtract.glext | 1 + extensions/ext_framebuffer_blit.glext | 1 - extensions/ext_framebuffer_multisample.glext | 1 - extensions/ext_framebuffer_object.glext | 3 + extensions/ext_gpu_shader4.glext | 7 + extensions/ext_texture3d.glext | 1 - extensions/ext_texture_array.glext | 3 +- extensions/ext_texture_srgb.glext | 12 + extensions/ext_unpack_subimage.glext | 2 +- extensions/msp_texture1d.glext | 1 - extensions/nv_non_square_matrices.glext | 2 +- gl.fixes.xml | 221 +++----------- gl.msp.xml | 132 ++++++++ scripts/extgen.py | 306 +++++++++++-------- source/framebuffer.h | 4 +- 25 files changed, 430 insertions(+), 328 deletions(-) create mode 100644 gl.msp.xml diff --git a/extensions/arb_depth_texture.glext b/extensions/arb_depth_texture.glext index 03a9725a..8b72d003 100644 --- a/extensions/arb_depth_texture.glext +++ b/extensions/arb_depth_texture.glext @@ -1 +1,3 @@ extension ARB_depth_texture +# Deprecated and not particularly useful +ignore GL_DEPTH_TEXTURE_MODE_ARB diff --git a/extensions/arb_geometry_shader4.glext b/extensions/arb_geometry_shader4.glext index 801f39b5..bc5bc77b 100644 --- a/extensions/arb_geometry_shader4.glext +++ b/extensions/arb_geometry_shader4.glext @@ -1,3 +1,13 @@ extension ARB_geometry_shader4 -backport none +# We use the version from EXT_texture_array ignore glFramebufferTextureLayerARB +# Not promoted to core +ignore glFramebufferTextureFaceARB +ignore GL_MAX_GEOMETRY_VARYING_COMPONENTS_ARB +ignore GL_MAX_VERTEX_VARYING_COMPONENTS_ARB +# Not promoted but required to support the extension flavor of geometry shaders +optional GL_GEOMETRY_INPUT_TYPE_ARB +optional GL_GEOMETRY_OUTPUT_TYPE_ARB +optional GL_GEOMETRY_VERTICES_OUT_ARB +optional glProgramParameteriARB +optional GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB diff --git a/extensions/arb_shader_objects.glext b/extensions/arb_shader_objects.glext index 7d0ba645..96d3fc28 100644 --- a/extensions/arb_shader_objects.glext +++ b/extensions/arb_shader_objects.glext @@ -1 +1,11 @@ extension ARB_shader_objects +# Not promoted to core +ignore glGetHandleARB +ignore glGetObjectParameterfvARB +ignore GL_PROGRAM_OBJECT_ARB +ignore GL_SHADER_OBJECT_ARB +ignore GL_OBJECT_TYPE_ARB +ignore GL_OBJECT_SUBTYPE_ARB +# Rectangular textures have their own extension +optional GL_SAMPLER_2D_RECT_ARB +optional GL_SAMPLER_2D_RECT_SHADOW_ARB diff --git a/extensions/arb_shadow.glext b/extensions/arb_shadow.glext index 24e32e2e..477b7ba7 100644 --- a/extensions/arb_shadow.glext +++ b/extensions/arb_shadow.glext @@ -1 +1,4 @@ extension ARB_shadow +# The name got changed in OpenGL 3.0; mark as optional to circumvent the +# deprecation +optional GL_COMPARE_R_TO_TEXTURE_ARB diff --git a/extensions/arb_texture_cube_map.glext b/extensions/arb_texture_cube_map.glext index 892b8393..5423ecfe 100644 --- a/extensions/arb_texture_cube_map.glext +++ b/extensions/arb_texture_cube_map.glext @@ -1,2 +1,4 @@ extension ARB_texture_cube_map -backport none +# Deprecated; related to texture coordinate generation which we don't use +ignore GL_NORMAL_MAP_ARB +ignore GL_REFLECTION_MAP_ARB diff --git a/extensions/arb_texture_float.glext b/extensions/arb_texture_float.glext index 4eea1fc1..ddfb06e3 100644 --- a/extensions/arb_texture_float.glext +++ b/extensions/arb_texture_float.glext @@ -1,2 +1,12 @@ extension ARB_texture_float -backport none +# Alpha, luminance and intensity formats were replaced with R and RG formats +ignore GL_ALPHA16F_ARB +ignore GL_LUMINANCE16F_ARB +ignore GL_LUMINANCE_ALPHA16F_ARB +ignore GL_INTENSITY16F_ARB +ignore GL_ALPHA32F_ARB +ignore GL_LUMINANCE32F_ARB +ignore GL_LUMINANCE_ALPHA32F_ARB +ignore GL_INTENSITY32F_ARB +ignore GL_TEXTURE_LUMINANCE_TYPE_ARB +ignore GL_TEXTURE_INTENSITY_TYPE_ARB diff --git a/extensions/arb_vertex_buffer_object.glext b/extensions/arb_vertex_buffer_object.glext index e8962591..16d804f3 100644 --- a/extensions/arb_vertex_buffer_object.glext +++ b/extensions/arb_vertex_buffer_object.glext @@ -1,2 +1,11 @@ extension ARB_vertex_buffer_object -backport none +# Fixed-function arrays are deprecated and we don't query the bindings +ignore GL_COLOR_ARRAY_BUFFER_BINDING_ARB +ignore GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB +ignore GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB +ignore GL_INDEX_ARRAY_BUFFER_BINDING_ARB +ignore GL_NORMAL_ARRAY_BUFFER_BINDING_ARB +ignore GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB +ignore GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB +ignore GL_VERTEX_ARRAY_BUFFER_BINDING_ARB +ignore GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB diff --git a/extensions/arb_vertex_shader.glext b/extensions/arb_vertex_shader.glext index 951fbaae..efd91b83 100644 --- a/extensions/arb_vertex_shader.glext +++ b/extensions/arb_vertex_shader.glext @@ -1,3 +1,4 @@ extension ARB_vertex_shader -secondary ARB_vertex_program -backport none +# Deprecated fixed-function interop tokens +ignore GL_MAX_TEXTURE_COORDS_ARB +ignore GL_VERTEX_PROGRAM_TWO_SIDE_ARB diff --git a/extensions/ext_bgra.glext b/extensions/ext_bgra.glext index bda98696..b6f40edc 100644 --- a/extensions/ext_bgra.glext +++ b/extensions/ext_bgra.glext @@ -1,2 +1 @@ extension EXT_bgra -backport none diff --git a/extensions/ext_blend_minmax.glext b/extensions/ext_blend_minmax.glext index 62606988..4a2d1026 100644 --- a/extensions/ext_blend_minmax.glext +++ b/extensions/ext_blend_minmax.glext @@ -1,2 +1,3 @@ extension EXT_blend_minmax +# Prevent autodetection of ARB_imaging as backport extension backport none diff --git a/extensions/ext_blend_subtract.glext b/extensions/ext_blend_subtract.glext index e8af79ad..bf6c2821 100644 --- a/extensions/ext_blend_subtract.glext +++ b/extensions/ext_blend_subtract.glext @@ -1,2 +1,3 @@ extension EXT_blend_subtract +# Prevent autodetection of ARB_imaging as backport extension backport none diff --git a/extensions/ext_framebuffer_blit.glext b/extensions/ext_framebuffer_blit.glext index cdc1801b..4c78ba51 100644 --- a/extensions/ext_framebuffer_blit.glext +++ b/extensions/ext_framebuffer_blit.glext @@ -1,2 +1 @@ extension EXT_framebuffer_blit -backport ARB_framebuffer_object diff --git a/extensions/ext_framebuffer_multisample.glext b/extensions/ext_framebuffer_multisample.glext index 272ca3ae..91f26a7f 100644 --- a/extensions/ext_framebuffer_multisample.glext +++ b/extensions/ext_framebuffer_multisample.glext @@ -1,2 +1 @@ extension EXT_framebuffer_multisample -backport ARB_framebuffer_object diff --git a/extensions/ext_framebuffer_object.glext b/extensions/ext_framebuffer_object.glext index 6d5465df..88f41cb1 100644 --- a/extensions/ext_framebuffer_object.glext +++ b/extensions/ext_framebuffer_object.glext @@ -1 +1,4 @@ extension EXT_framebuffer_object +# Not promoted; keep them around for more accurate error checking +optional GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT +optional GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT diff --git a/extensions/ext_gpu_shader4.glext b/extensions/ext_gpu_shader4.glext index 54d1360e..15875359 100644 --- a/extensions/ext_gpu_shader4.glext +++ b/extensions/ext_gpu_shader4.glext @@ -1 +1,8 @@ extension EXT_gpu_shader4 +# Buffer textures have their own extension +optional GL_SAMPLER_BUFFER_EXT +optional GL_INT_SAMPLER_BUFFER_EXT +optional GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT +# Ditto for rectangular textures +optional GL_INT_SAMPLER_2D_RECT_EXT +optional GL_UNSIGNED_INT_SAMPLER_2D_RECT_EXT diff --git a/extensions/ext_texture3d.glext b/extensions/ext_texture3d.glext index c1516184..e9bc90bb 100644 --- a/extensions/ext_texture3d.glext +++ b/extensions/ext_texture3d.glext @@ -1,2 +1 @@ extension EXT_texture3D -backport none diff --git a/extensions/ext_texture_array.glext b/extensions/ext_texture_array.glext index 7051d8eb..a70989aa 100644 --- a/extensions/ext_texture_array.glext +++ b/extensions/ext_texture_array.glext @@ -1,2 +1,3 @@ extension EXT_texture_array -backport none +# We use the version from ARB_shadow +ignore GL_COMPARE_REF_DEPTH_TO_TEXTURE_EXT diff --git a/extensions/ext_texture_srgb.glext b/extensions/ext_texture_srgb.glext index 32fddfbd..a592cdfa 100644 --- a/extensions/ext_texture_srgb.glext +++ b/extensions/ext_texture_srgb.glext @@ -1 +1,13 @@ extension EXT_texture_sRGB +# Specific compressed formats were not promoted to core +ignore GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT +ignore GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT +ignore GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT +ignore GL_COMPRESSED_SRGB_S3TC_DXT1_EXT +# Luminance formats are deprecated +ignore GL_COMPRESSED_SLUMINANCE_EXT +ignore GL_COMPRESSED_SLUMINANCE_ALPHA_EXT +optional GL_SLUMINANCE_EXT +optional GL_SLUMINANCE_ALPHA_EXT +optional GL_SLUMINANCE8_EXT +optional GL_SLUMINANCE8_ALPHA8_EXT diff --git a/extensions/ext_unpack_subimage.glext b/extensions/ext_unpack_subimage.glext index c366e604..59318fac 100644 --- a/extensions/ext_unpack_subimage.glext +++ b/extensions/ext_unpack_subimage.glext @@ -1 +1 @@ -extension EXT_unpack_subimage +extension gles2.EXT_unpack_subimage diff --git a/extensions/msp_texture1d.glext b/extensions/msp_texture1d.glext index fd77cdc9..00cd9120 100644 --- a/extensions/msp_texture1d.glext +++ b/extensions/msp_texture1d.glext @@ -1,2 +1 @@ extension MSP_texture1D -core_version gl 1.1 diff --git a/extensions/nv_non_square_matrices.glext b/extensions/nv_non_square_matrices.glext index 9833f47d..c4f2aa13 100644 --- a/extensions/nv_non_square_matrices.glext +++ b/extensions/nv_non_square_matrices.glext @@ -1 +1 @@ -extension NV_non_square_matrices +extension gles2.NV_non_square_matrices diff --git a/gl.fixes.xml b/gl.fixes.xml index a2271d30..e6e14b38 100644 --- a/gl.fixes.xml +++ b/gl.fixes.xml @@ -9,29 +9,30 @@ Since we use GL-generated names, it's safe to alias them. --> glBindFramebufferEXT - + glBindRenderbufferEXT - + + core. The ARB versions can be used to operate on either shaders or + programs, but we use the core names so this is safe. --> glDeleteObjectARB - - + + glGetInfoLogARB - - + + glGetObjectParameterivARB - - + + glGetAttachedObjectsARB - + + + + + + glBindVertexArrayAPPLE + - - - + + + + + + + + + + + + + + + - - - - - - - - + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/gl.msp.xml b/gl.msp.xml new file mode 100644 index 00000000..cea6395b --- /dev/null +++ b/gl.msp.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/scripts/extgen.py b/scripts/extgen.py index f5df83f2..4c3565e8 100755 --- a/scripts/extgen.py +++ b/scripts/extgen.py @@ -43,6 +43,12 @@ class Version: return self.major>other.major return self.minor>other.minor + def __eq__(self, other): + if other is None: + return False + + return (self.major==other.major and self.minor==other.minor) + class Thing: FUNCTION = 1 @@ -145,9 +151,7 @@ def get_or_create(map, name, type, *args): class GlXmlParser: - def __init__(self, host_api_name, target_ext_name): - self.host_api_name = host_api_name - self.target_ext_name = target_ext_name + def __init__(self): self.apis = {} self.things = {} @@ -177,10 +181,12 @@ class GlXmlParser: enum.value = int(en.getAttribute("value"), 16) + alias = en.getAttribute("alias") + if alias: + enum.aliases.append(alias) + def parse_feature(self, feat): api_name = feat.getAttribute("api") - if not api_name: - api_name = self.host_api_name api = get_or_create(self.apis, api_name, Api) version = feat.getAttribute("number") @@ -204,7 +210,6 @@ class GlXmlParser: removes = get_nested_elements(feat, "remove") for rem in removes: - profile = rem.getAttribute("profile") commands = get_nested_elements(rem, "command") enums = get_nested_elements(rem, "enum") @@ -212,15 +217,8 @@ class GlXmlParser: name = t.getAttribute("name") thing = self.things.get(name) if thing: - if profile!="core": - if thing.name in api.core_things: - del api.core_things[thing.name] - for s in thing.api_support.itervalues(): - for e in s.extensions: - del e.things[thing.name] - else: - supp = thing.get_or_create_api_support(api.name) - supp.deprecated_version = version + supp = thing.get_or_create_api_support(api.name) + supp.deprecated_version = version def parse_extension(self, ext): ext_things_by_api = {} @@ -276,6 +274,9 @@ class GlXmlParser: def check_backport_extensions(self, api): for e in api.extensions.itervalues(): + if e.ext_type!="ARB": + continue + e.backport = True for t in e.things.itervalues(): if t.name.endswith(e.ext_type): @@ -283,9 +284,6 @@ class GlXmlParser: break def resolve_enum_aliases(self, api): - core_enums = filter((lambda t: t.kind==Thing.ENUM), api.core_things.itervalues()) - core_enums_by_value = dict((e.value, None) for e in core_enums) - for e in api.extensions.itervalues(): ext_enums = filter((lambda t: t.kind==Thing.ENUM), e.things.itervalues()) enum_suffix = "_"+e.ext_type @@ -297,13 +295,6 @@ class GlXmlParser: if name.endswith(enum_suffix): name = name[:-len(enum_suffix)] ce = api.core_things.get(name) - if not ce and n.value in core_enums_by_value: - if core_enums_by_value[n.value] is None: - core_enums_by_value[n.value] = filter((lambda e: e.value==n.value), core_enums) - for c in core_enums_by_value[n.value]: - if c.bitmask==n.bitmask: - ce = c - break if ce and ce.value==n.value and ce.name not in n.aliases: n.aliases.append(ce.name) @@ -321,10 +312,6 @@ class GlXmlParser: sources.append(t) def sort_extensions(self): - for a in self.apis.itervalues(): - e = a.extensions.get(self.target_ext_name) - if e: - e.preference = 3 for t in self.things.itervalues(): for s in t.api_support.itervalues(): s.extensions.sort(key=(lambda e: e.preference), reverse=True) @@ -338,22 +325,35 @@ class GlXmlParser: def detect_core_version(host_api, things): - candidates = {} + max_version = Version(1, 0) + max_count = 0 + lower_count = 0 + missing = [] for t in things: supp = t.api_support.get(host_api.name) if supp and supp.core_version: - candidates[supp.core_version] = candidates.get(supp.core_version, 0)+1 + if supp.core_version>max_version: + max_version = supp.core_version + lower_count += max_count + max_count = 1 + elif supp.core_version==max_version: + max_count += 1 + else: + lower_count += 1 + else: + missing.append(t) - if candidates: - candidates = list((v, k) for k, v in candidates.items()) - if len(candidates)>1: - candidates.sort(reverse=True) - if candidates[1][0]+1>=candidates[0][0]: - print "Warning: multiple likely core version candidates: %s %s"%(candidates[0][1], candidates[1][1]) - return candidates[0][1] + if lower_count>max_count or (missing and len(missing)*21: - print "Warning: multiple backport extension candidates: %s"%(" ".join(e.name for e in candidates)) - + total_count = len(things) + best_ext = None + best_count = 0 for e in candidates: - if e.base_name==target_ext.base_name: + things_in_ext = filter((lambda t: t.name in e.things), things) + count = len(things_in_ext) + if count==total_count: return e + elif count>best_count: + best_ext = e + best_count = count - if len(candidates)==1: - print "Warning: potential backport extension has mismatched name: %s"%candidates[0].name + if best_count*2>=total_count: + print "Warning: Inconsistent backport extension %s"%best_ext.name def collect_extensions(thing, api, exts): supp = thing.api_support.get(api) @@ -391,16 +398,13 @@ def collect_extensions(thing, api, exts): return for e in supp.extensions: - if not e.backport and e not in exts: + if not e.backport and e.ext_type!="MSP" and e not in exts: exts.append(e) for s in supp.sources: collect_extensions(s, api, exts) -def detect_source_extension(host_api, target_ext, things): - if target_ext.name in host_api.extensions: - return target_ext - +def detect_source_extension(host_api, things): things_by_ext = {} for t in things: exts = [] @@ -408,37 +412,63 @@ def detect_source_extension(host_api, target_ext, things): for e in exts: things_by_ext.setdefault(e, []).append(t) - largest_ext = None - largest_count = 0 - for e, t in things_by_ext.iteritems(): - count = len(t) - if count>largest_count: - largest_ext = e - largest_count = count + extensions = [] + missing = set(things) + while missing and things_by_ext: + largest_ext = None + largest_count = 0 + for e, t in things_by_ext.iteritems(): + count = len(t) + if count>largest_count: + largest_ext = e + largest_count = count + elif count==largest_count and e.preference>largest_ext.preference: + largest_ext = e + + extensions.append(largest_ext) + for t in things_by_ext[largest_ext]: + missing.remove(t) + if not missing: + break + + del things_by_ext[largest_ext] + for e in things_by_ext.keys(): + unseen = filter((lambda t: t in missing), things_by_ext[e]) + if unseen: + things_by_ext[e] = unseen + else: + del things_by_ext[e] + + if missing: + return None - return largest_ext + return extensions class SourceGenerator: - def __init__(self, host_api, target_ext, things): + def __init__(self, host_api, ext_name, things, optional_things): self.host_api = host_api self.api_prefix = "GL" if self.host_api.name=="gles2": self.api_prefix = "GL_ES" - self.target_ext = target_ext - self.funcs = filter((lambda t: t.kind==Thing.FUNCTION), things) + self.ext_name = ext_name + all_things = things+optional_things + self.funcs = filter((lambda t: t.kind==Thing.FUNCTION), all_things) self.funcs.sort(key=(lambda f: f.name)) self.func_typedefs = dict((f.name, "FPtr_"+f.name) for f in self.funcs) - self.enums = filter((lambda t: t.kind==Thing.ENUM), things) + self.enums = filter((lambda t: t.kind==Thing.ENUM), all_things) self.enums.sort(key=(lambda e: e.value)) self.core_version = detect_core_version(host_api, things) self.deprecated_version = detect_deprecated_version(host_api, things) - self.backport_ext = detect_backport_extension(host_api, target_ext, things); - self.source_ext = detect_source_extension(host_api, target_ext, things) + self.backport_ext = detect_backport_extension(host_api, things); + self.source_exts = detect_source_extension(host_api, things) + + if not self.core_version and not self.backport_ext and not self.source_exts: + print "Warning: Not supportable on host API" def write_header_intro(self, out): - out.write("#ifndef MSP_GL_%s_\n"%self.target_ext.name.upper()) - out.write("#define MSP_GL_%s_\n"%self.target_ext.name.upper()) + out.write("#ifndef MSP_GL_%s_\n"%self.ext_name.upper()) + out.write("#define MSP_GL_%s_\n"%self.ext_name.upper()) out.write(""" #include @@ -486,7 +516,7 @@ namespace GL { """) def write_source_intro(self, out): - out.write("#include \"%s.h\"\n"%self.target_ext.name.lower()) + out.write("#include \"%s.h\"\n"%self.ext_name.lower()) if self.funcs: out.write(""" #ifdef __APPLE__ @@ -512,9 +542,9 @@ namespace GL { out.write("%s %s = 0;\n"%(self.func_typedefs[f.name], f.name)) def write_init_function(self, out): - out.write("\nExtension::SupportLevel init_%s()\n{\n"%self.target_ext.name.lower()) + out.write("\nExtension::SupportLevel init_%s()\n{\n"%self.ext_name.lower()) if self.core_version: - out.write("\tif(is_disabled(\"GL_%s\"))\n\t\treturn Extension::UNSUPPORTED;\n"%self.target_ext.name) + out.write("\tif(is_disabled(\"GL_%s\"))\n\t\treturn Extension::UNSUPPORTED;\n"%self.ext_name) out.write("#if !defined(__APPLE__) || defined(%s_%s)\n"%(self.api_prefix, self.core_version.as_define())) out.write("\tif(") if self.backport_ext: @@ -524,34 +554,32 @@ namespace GL { out.write(", %r"%self.deprecated_version) out.write("))\n\t{\n") for f in self.funcs: - supp = f.api_support.get(self.host_api.name) - if supp: - gpa_suffix = "" - if supp.core_version is not None and supp.core_version<=Version(1, 1): - gpa_suffix = "_1_1" - out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS%s(%s));\n"%(f.name, self.func_typedefs[f.name], gpa_suffix, f.name)) + supp = f.api_support[self.host_api.name] + gpa_suffix = "" + if supp.core_version is not None and supp.core_version<=Version(1, 1): + gpa_suffix = "_1_1" + out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS%s(%s));\n"%(f.name, self.func_typedefs[f.name], gpa_suffix, f.name)) out.write("\t\treturn Extension::CORE;\n") out.write("\t}\n") out.write("#endif\n") - if self.source_ext and self.source_ext!=self.backport_ext: - out.write("#if !defined(__APPLE__) || defined(GL_%s)\n"%self.target_ext.name) - out.write("\tif(is_supported(\"GL_%s\"))\n\t{\n"%(self.source_ext.name)) + if self.source_exts: + out.write("#if !defined(__APPLE__) || defined(GL_%s)\n"%self.ext_name) + out.write("\tif(%s)\n\t{\n"%" && ".join("is_supported(\"GL_%s\")"%s.name for s in self.source_exts)) for f in self.funcs: - supp = f.api_support.get(self.host_api.name) - if supp and supp.sources: + supp = f.api_support[self.host_api.name] + if supp.sources: src = None - for s in supp.sources: - if s.name.endswith(self.source_ext.ext_type): - src = s + for e in self.source_exts: + for s in supp.sources: + if s.name in e.things: + src = s + break + if src: break - if not src: - src = supp.sources[0] else: src = f - if self.host_api.name in src.api_support: - if not src.name.endswith(self.source_ext.ext_type): - print "Warning: %s does not match extension type %s"%(src.name, self.source_ext.ext_type) + if src: out.write("\t\t%s = reinterpret_cast<%s>(GET_PROC_ADDRESS(%s));\n"%(f.name, self.func_typedefs[f.name], src.name)) out.write("\t\treturn Extension::EXTENSION;\n") out.write("\t}\n") @@ -570,7 +598,7 @@ namespace GL { self.write_header_intro(out) self.write_enum_definitions(out) self.write_function_pointer_declarations(out) - out.write("extern Extension %s;\n"%self.target_ext.name) + out.write("extern Extension %s;\n"%self.ext_name) self.write_header_outro(out) def write_source(self, fn): @@ -578,8 +606,7 @@ namespace GL { self.write_source_intro(out) self.write_function_pointer_definitions(out) self.write_init_function(out) - ext_name = self.target_ext.name - out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(ext_name, ext_name, ext_name.lower())) + out.write("\nExtension %s(\"GL_%s\", init_%s);\n"%(self.ext_name, self.ext_name, self.ext_name.lower())) self.write_source_outro(out) @@ -589,9 +616,9 @@ class ExtensionParser: self.target_ext = None self.core_version = None self.deprecated_version = None - self.secondary_exts = [] self.backport_ext = None self.ignore_things = [] + self.optional_things = [] def parse(self, fn): for line in open(fn): @@ -600,56 +627,64 @@ class ExtensionParser: continue parts = line.split() + api = None keyword = parts[0] + if ":" in keyword: + api, keyword = keyword.split(":") + + if api is not None and api!=self.host_api: + continue if keyword=="extension": self.target_ext = parts[1] elif keyword=="core_version": - if parts[1]==self.host_api: - self.core_version = Version(*map(int, parts[2].split('.'))) + self.core_version = Version(*map(int, parts[1].split('.'))) elif keyword=="deprecated": - if parts[1]==self.host_api: - self.deprecated_version = Version(*map(int, parts[2].split('.'))) - elif keyword=="secondary": - self.secondary_exts.append(parts[1]) + self.deprecated_version = Version(*map(int, parts[1].split('.'))) elif keyword=="backport": self.backport_ext = parts[1] elif keyword=="ignore": self.ignore_things.append(parts[1]) + elif keyword=="optional": + self.optional_things.append(parts[1]) + else: + print "Unknown keyword "+keyword + return False + + return True def get_extension(api_map, ext_name): - main_api = api_map["gl"] - ext = main_api.extensions.get(ext_name) - if ext: - return ext + if "." in ext_name: + ext_api_name, ext_name = ext_name.split(".") + else: + ext_api_name = "gl" + + return api_map[ext_api_name].extensions[ext_name] + +def resolve_things(api, things): + rthings = [] + for t in things: + ct = filter(None, map(api.core_things.get, t.aliases)) + if ct: + rthings += ct + else: + rthings.append(t) - for a in api_map.itervalues(): - ext = a.extensions.get(ext_name) - if ext: - return ext + return rthings -def collect_things(host_api, target_ext, secondary, ignore): +def collect_extension_things(host_api, target_ext, ignore): ext_things = [t for n, t in target_ext.things.iteritems() if n not in ignore] - core_things = target_ext.api.core_things + return resolve_things(target_ext.api, ext_things) +def collect_optional_things(target_ext, names): things = [] - for t in ext_things: - found_in_core = False - for a in t.aliases: - if a in core_things: - things.append(core_things[a]) - found_in_core = True - if not found_in_core: - things.append(t) - - for s in secondary: - for t in s.things.itervalues(): - for a in t.aliases: - if a in core_things and core_things[a] not in things: - things.append(core_things[a]) - - return things + for t in names: + if t in target_ext.things: + things.append(target_ext.things[t]) + else: + things.append(target_ext.api.core_things[t]) + return resolve_things(target_ext.api, things) def main(): if len(sys.argv)<2: @@ -660,7 +695,7 @@ Reads gl.xml and generates C++ source files to use an OpenGL extension described in . If is absent, the extension's lowercased name is used. Anything after the last dot in is removed and replaced with cpp and h.""" - sys.exit(0) + sys.exit(1) host_api_name = "gl" @@ -670,7 +705,8 @@ replaced with cpp and h.""" i += 1 ext_parser = ExtensionParser(host_api_name) - ext_parser.parse(sys.argv[i]) + if not ext_parser.parse(sys.argv[i]): + sys.exit(1) i += 1 if i