From: Emil Velikov Date: Sun, 9 Dec 2018 19:51:15 +0000 (+0000) Subject: mapi: move genCommon.py to src/mapi/new X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cd0f11bac55b14728cf70e39cd269a70aeb2b5d4;p=mesa.git mapi: move genCommon.py to src/mapi/new The helper will also be used by the new Khronos gl.xml aware generator. v2: Move existing one, instead of duplicating it. v3: Correct genCommon.py references in meson [Erik] v4: Drop the file from the EGL EXTRA_DIST [Erik] Suggested-by: Kyle Brenneman Signed-off-by: Emil Velikov --- diff --git a/src/egl/Makefile.am b/src/egl/Makefile.am index ff928525e6c..de4a754a2db 100644 --- a/src/egl/Makefile.am +++ b/src/egl/Makefile.am @@ -136,10 +136,18 @@ libEGL_common_la_LIBADD += \ $(LIBDRM_LIBS) \ $(CLOCK_LIB) -GLVND_GEN_DEPS = generate/gen_egl_dispatch.py \ - generate/egl.xml generate/eglFunctionList.py generate/genCommon.py \ +# dummy rule to keep dist happy +$(top_scrdir)/src/mapi/new/genCommon.py: + +GLVND_GEN_EGL_DEPS = \ + generate/gen_egl_dispatch.py \ + generate/eglFunctionList.py \ + generate/egl.xml \ generate/egl_other.xml +GLVND_GEN_DEPS = $(top_scrdir)/src/mapi/new/genCommon.py \ + $(GLVND_GEN_EGL_DEPS) + PYTHON_GEN = $(AM_V_GEN)$(PYTHON) $(PYTHON_FLAGS) g_egldispatchstubs.c: $(GLVND_GEN_DEPS) $(PYTHON_GEN) $(top_srcdir)/src/egl/generate/gen_egl_dispatch.py source \ @@ -226,6 +234,6 @@ EXTRA_DIST = \ drivers/haiku \ main/egl.def \ main/README.txt \ - $(GLVND_GEN_DEPS) \ + $(GLVND_GEN_EGL_DEPS) \ main/50_mesa.json \ meson.build diff --git a/src/egl/generate/genCommon.py b/src/egl/generate/genCommon.py deleted file mode 100644 index b0925d80151..00000000000 --- a/src/egl/generate/genCommon.py +++ /dev/null @@ -1,223 +0,0 @@ -#!/usr/bin/env python - -# (C) Copyright 2015, NVIDIA CORPORATION. -# All Rights Reserved. -# -# Permission is hereby granted, free of charge, to any person obtaining a -# copy of this software and associated documentation files (the "Software"), -# to deal in the Software without restriction, including without limitation -# on the rights to use, copy, modify, merge, publish, distribute, sub -# license, and/or sell copies of the Software, and to permit persons to whom -# the Software is furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice (including the next -# paragraph) shall be included in all copies or substantial portions of the -# Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL -# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# -# Authors: -# Kyle Brenneman - -import collections -import re -import sys -import xml.etree.cElementTree as etree - -MAPI_TABLE_NUM_DYNAMIC = 4096 - -_LIBRARY_FEATURE_NAMES = { - # libGL and libGLdiapatch both include every function. - "gl" : None, - "gldispatch" : None, - "opengl" : frozenset(( "GL_VERSION_1_0", "GL_VERSION_1_1", - "GL_VERSION_1_2", "GL_VERSION_1_3", "GL_VERSION_1_4", "GL_VERSION_1_5", - "GL_VERSION_2_0", "GL_VERSION_2_1", "GL_VERSION_3_0", "GL_VERSION_3_1", - "GL_VERSION_3_2", "GL_VERSION_3_3", "GL_VERSION_4_0", "GL_VERSION_4_1", - "GL_VERSION_4_2", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5", - )), - "glesv1" : frozenset(("GL_VERSION_ES_CM_1_0", "GL_OES_point_size_array")), - "glesv2" : frozenset(("GL_ES_VERSION_2_0", "GL_ES_VERSION_3_0", - "GL_ES_VERSION_3_1", "GL_ES_VERSION_3_2", - )), -} - -def getFunctions(xmlFiles): - """ - Reads an XML file and returns all of the functions defined in it. - - xmlFile should be the path to Khronos's gl.xml file. The return value is a - sequence of FunctionDesc objects, ordered by slot number. - """ - roots = [ etree.parse(xmlFile).getroot() for xmlFile in xmlFiles ] - return getFunctionsFromRoots(roots) - -def getFunctionsFromRoots(roots): - functions = {} - for root in roots: - for func in _getFunctionList(root): - functions[func.name] = func - functions = functions.values() - - # Sort the function list by name. - functions = sorted(functions, key=lambda f: f.name) - - # Assign a slot number to each function. This isn't strictly necessary, - # since you can just look at the index in the list, but it makes it easier - # to include the slot when formatting output. - for i in range(len(functions)): - functions[i] = functions[i]._replace(slot=i) - - return functions - -def getExportNamesFromRoots(target, roots): - """ - Goes through the tags from gl.xml and returns a set of OpenGL - functions that a library should export. - - target should be one of "gl", "gldispatch", "opengl", "glesv1", or - "glesv2". - """ - featureNames = _LIBRARY_FEATURE_NAMES[target] - if featureNames is None: - return set(func.name for func in getFunctionsFromRoots(roots)) - - names = set() - for root in roots: - features = [] - for featElem in root.findall("feature"): - if featElem.get("name") in featureNames: - features.append(featElem) - for featElem in root.findall("extensions/extension"): - if featElem.get("name") in featureNames: - features.append(featElem) - for featElem in features: - for commandElem in featElem.findall("require/command"): - names.add(commandElem.get("name")) - return names - -class FunctionArg(collections.namedtuple("FunctionArg", "type name")): - @property - def dec(self): - """ - Returns a "TYPE NAME" string, suitable for a function prototype. - """ - rv = str(self.type) - if not rv.endswith("*"): - rv += " " - rv += self.name - return rv - -class FunctionDesc(collections.namedtuple("FunctionDesc", "name rt args slot")): - def hasReturn(self): - """ - Returns true if the function returns a value. - """ - return (self.rt != "void") - - @property - def decArgs(self): - """ - Returns a string with the types and names of the arguments, as you - would use in a function declaration. - """ - if not self.args: - return "void" - else: - return ", ".join(arg.dec for arg in self.args) - - @property - def callArgs(self): - """ - Returns a string with the names of the arguments, as you would use in a - function call. - """ - return ", ".join(arg.name for arg in self.args) - - @property - def basename(self): - assert self.name.startswith("gl") - return self.name[2:] - -def _getFunctionList(root): - for elem in root.findall("commands/command"): - yield _parseCommandElem(elem) - -def _parseCommandElem(elem): - protoElem = elem.find("proto") - (rt, name) = _parseProtoElem(protoElem) - - args = [] - for ch in elem.findall("param"): - # tags have the same format as a tag. - args.append(FunctionArg(*_parseProtoElem(ch))) - func = FunctionDesc(name, rt, tuple(args), slot=None) - - return func - -def _parseProtoElem(elem): - # If I just remove the tags and string the text together, I'll get valid C code. - text = _flattenText(elem) - text = text.strip() - m = re.match(r"^(.+)\b(\w+)(?:\s*\[\s*(\d*)\s*\])?$", text, re.S) - if m: - typename = _fixupTypeName(m.group(1)) - name = m.group(2) - if m.group(3): - # HACK: glPathGlyphIndexRangeNV defines an argument like this: - # GLuint baseAndCount[2] - # Convert it to a pointer and hope for the best. - typename += "*" - return (typename, name) - else: - raise ValueError("Can't parse element %r -> %r" % (elem, text)) - -def _flattenText(elem): - """ - Returns the text in an element and all child elements, with the tags - removed. - """ - text = "" - if elem.text is not None: - text = elem.text - for ch in elem: - text += _flattenText(ch) - if ch.tail is not None: - text += ch.tail - return text - -def _fixupTypeName(typeName): - """ - Converts a typename into a more consistent format. - """ - - rv = typeName.strip() - - # Replace "GLvoid" with just plain "void". - rv = re.sub(r"\bGLvoid\b", "void", rv) - - # Remove the vendor suffixes from types that have a suffix-less version. - rv = re.sub(r"\b(GLhalf|GLintptr|GLsizeiptr|GLint64|GLuint64)(?:ARB|EXT|NV|ATI)\b", r"\1", rv) - - rv = re.sub(r"\bGLvoid\b", "void", rv) - - # Clear out any leading and trailing whitespace. - rv = rv.strip() - - # Remove any whitespace before a '*' - rv = re.sub(r"\s+\*", r"*", rv) - - # Change "foo*" to "foo *" - rv = re.sub(r"([^\*])\*", r"\1 *", rv) - - # Condense all whitespace into a single space. - rv = re.sub(r"\s+", " ", rv) - - return rv - diff --git a/src/egl/generate/gen_egl_dispatch.py b/src/egl/generate/gen_egl_dispatch.py index d556a7782c9..fe901fdd5b6 100644 --- a/src/egl/generate/gen_egl_dispatch.py +++ b/src/egl/generate/gen_egl_dispatch.py @@ -38,6 +38,9 @@ import eglFunctionList import sys import textwrap +import os +NEWAPI = os.path.join(os.path.dirname(__file__), "..", "..", "mapi", "new") +sys.path.insert(0, NEWAPI) import genCommon def main(): diff --git a/src/egl/meson.build b/src/egl/meson.build index 461892f5ae8..a23cc36fc2b 100644 --- a/src/egl/meson.build +++ b/src/egl/meson.build @@ -1,4 +1,4 @@ -# Copyright © 2017 Intel Corporation +# Copyright © 2017 Intel Corporation # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -69,7 +69,7 @@ g_egldispatchstubs_c = custom_target( command : [ prog_python, '@INPUT0@', 'source', '@INPUT1@', '@INPUT2@', ], - depend_files : files('generate/eglFunctionList.py', 'generate/genCommon.py'), + depend_files : [ files('generate/eglFunctionList.py'), genCommon_py, ], capture : true, ) @@ -83,7 +83,7 @@ g_egldispatchstubs_h = custom_target( command : [ prog_python, '@INPUT0@', 'header', '@INPUT1@', '@INPUT2@', ], - depend_files : files('generate/eglFunctionList.py', 'generate/genCommon.py'), + depend_files : [ files('generate/eglFunctionList.py'), genCommon_py, ], capture : true, ) diff --git a/src/mapi/Makefile.am b/src/mapi/Makefile.am index 97ebdeb1d7f..b46ed814700 100644 --- a/src/mapi/Makefile.am +++ b/src/mapi/Makefile.am @@ -31,6 +31,7 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = EXTRA_DIST = \ + new/genCommon.py \ es1api/ABI-check \ es2api/ABI-check \ mapi_abi.py \ diff --git a/src/mapi/meson.build b/src/mapi/meson.build index 798586bfb0c..24013c65542 100644 --- a/src/mapi/meson.build +++ b/src/mapi/meson.build @@ -25,6 +25,7 @@ files_mapi_util = files( 'u_execmem.h', ) +genCommon_py = files('new/genCommon.py') mapi_abi_py = files('mapi_abi.py') subdir('glapi') diff --git a/src/mapi/new/genCommon.py b/src/mapi/new/genCommon.py new file mode 100644 index 00000000000..b0925d80151 --- /dev/null +++ b/src/mapi/new/genCommon.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python + +# (C) Copyright 2015, NVIDIA CORPORATION. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL +# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Authors: +# Kyle Brenneman + +import collections +import re +import sys +import xml.etree.cElementTree as etree + +MAPI_TABLE_NUM_DYNAMIC = 4096 + +_LIBRARY_FEATURE_NAMES = { + # libGL and libGLdiapatch both include every function. + "gl" : None, + "gldispatch" : None, + "opengl" : frozenset(( "GL_VERSION_1_0", "GL_VERSION_1_1", + "GL_VERSION_1_2", "GL_VERSION_1_3", "GL_VERSION_1_4", "GL_VERSION_1_5", + "GL_VERSION_2_0", "GL_VERSION_2_1", "GL_VERSION_3_0", "GL_VERSION_3_1", + "GL_VERSION_3_2", "GL_VERSION_3_3", "GL_VERSION_4_0", "GL_VERSION_4_1", + "GL_VERSION_4_2", "GL_VERSION_4_3", "GL_VERSION_4_4", "GL_VERSION_4_5", + )), + "glesv1" : frozenset(("GL_VERSION_ES_CM_1_0", "GL_OES_point_size_array")), + "glesv2" : frozenset(("GL_ES_VERSION_2_0", "GL_ES_VERSION_3_0", + "GL_ES_VERSION_3_1", "GL_ES_VERSION_3_2", + )), +} + +def getFunctions(xmlFiles): + """ + Reads an XML file and returns all of the functions defined in it. + + xmlFile should be the path to Khronos's gl.xml file. The return value is a + sequence of FunctionDesc objects, ordered by slot number. + """ + roots = [ etree.parse(xmlFile).getroot() for xmlFile in xmlFiles ] + return getFunctionsFromRoots(roots) + +def getFunctionsFromRoots(roots): + functions = {} + for root in roots: + for func in _getFunctionList(root): + functions[func.name] = func + functions = functions.values() + + # Sort the function list by name. + functions = sorted(functions, key=lambda f: f.name) + + # Assign a slot number to each function. This isn't strictly necessary, + # since you can just look at the index in the list, but it makes it easier + # to include the slot when formatting output. + for i in range(len(functions)): + functions[i] = functions[i]._replace(slot=i) + + return functions + +def getExportNamesFromRoots(target, roots): + """ + Goes through the tags from gl.xml and returns a set of OpenGL + functions that a library should export. + + target should be one of "gl", "gldispatch", "opengl", "glesv1", or + "glesv2". + """ + featureNames = _LIBRARY_FEATURE_NAMES[target] + if featureNames is None: + return set(func.name for func in getFunctionsFromRoots(roots)) + + names = set() + for root in roots: + features = [] + for featElem in root.findall("feature"): + if featElem.get("name") in featureNames: + features.append(featElem) + for featElem in root.findall("extensions/extension"): + if featElem.get("name") in featureNames: + features.append(featElem) + for featElem in features: + for commandElem in featElem.findall("require/command"): + names.add(commandElem.get("name")) + return names + +class FunctionArg(collections.namedtuple("FunctionArg", "type name")): + @property + def dec(self): + """ + Returns a "TYPE NAME" string, suitable for a function prototype. + """ + rv = str(self.type) + if not rv.endswith("*"): + rv += " " + rv += self.name + return rv + +class FunctionDesc(collections.namedtuple("FunctionDesc", "name rt args slot")): + def hasReturn(self): + """ + Returns true if the function returns a value. + """ + return (self.rt != "void") + + @property + def decArgs(self): + """ + Returns a string with the types and names of the arguments, as you + would use in a function declaration. + """ + if not self.args: + return "void" + else: + return ", ".join(arg.dec for arg in self.args) + + @property + def callArgs(self): + """ + Returns a string with the names of the arguments, as you would use in a + function call. + """ + return ", ".join(arg.name for arg in self.args) + + @property + def basename(self): + assert self.name.startswith("gl") + return self.name[2:] + +def _getFunctionList(root): + for elem in root.findall("commands/command"): + yield _parseCommandElem(elem) + +def _parseCommandElem(elem): + protoElem = elem.find("proto") + (rt, name) = _parseProtoElem(protoElem) + + args = [] + for ch in elem.findall("param"): + # tags have the same format as a tag. + args.append(FunctionArg(*_parseProtoElem(ch))) + func = FunctionDesc(name, rt, tuple(args), slot=None) + + return func + +def _parseProtoElem(elem): + # If I just remove the tags and string the text together, I'll get valid C code. + text = _flattenText(elem) + text = text.strip() + m = re.match(r"^(.+)\b(\w+)(?:\s*\[\s*(\d*)\s*\])?$", text, re.S) + if m: + typename = _fixupTypeName(m.group(1)) + name = m.group(2) + if m.group(3): + # HACK: glPathGlyphIndexRangeNV defines an argument like this: + # GLuint baseAndCount[2] + # Convert it to a pointer and hope for the best. + typename += "*" + return (typename, name) + else: + raise ValueError("Can't parse element %r -> %r" % (elem, text)) + +def _flattenText(elem): + """ + Returns the text in an element and all child elements, with the tags + removed. + """ + text = "" + if elem.text is not None: + text = elem.text + for ch in elem: + text += _flattenText(ch) + if ch.tail is not None: + text += ch.tail + return text + +def _fixupTypeName(typeName): + """ + Converts a typename into a more consistent format. + """ + + rv = typeName.strip() + + # Replace "GLvoid" with just plain "void". + rv = re.sub(r"\bGLvoid\b", "void", rv) + + # Remove the vendor suffixes from types that have a suffix-less version. + rv = re.sub(r"\b(GLhalf|GLintptr|GLsizeiptr|GLint64|GLuint64)(?:ARB|EXT|NV|ATI)\b", r"\1", rv) + + rv = re.sub(r"\bGLvoid\b", "void", rv) + + # Clear out any leading and trailing whitespace. + rv = rv.strip() + + # Remove any whitespace before a '*' + rv = re.sub(r"\s+\*", r"*", rv) + + # Change "foo*" to "foo *" + rv = re.sub(r"([^\*])\*", r"\1 *", rv) + + # Condense all whitespace into a single space. + rv = re.sub(r"\s+", " ", rv) + + return rv +