mapi: move genCommon.py to src/mapi/new
authorEmil Velikov <emil.velikov@collabora.com>
Sun, 9 Dec 2018 19:51:15 +0000 (19:51 +0000)
committerEmil Velikov <emil.l.velikov@gmail.com>
Thu, 24 Jan 2019 18:13:25 +0000 (18:13 +0000)
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 <kbrenneman@nvidia.com>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
src/egl/Makefile.am
src/egl/generate/genCommon.py [deleted file]
src/egl/generate/gen_egl_dispatch.py
src/egl/meson.build
src/mapi/Makefile.am
src/mapi/meson.build
src/mapi/new/genCommon.py [new file with mode: 0644]

index ff928525e6ce257c3a7511819089cfe56be11e4d..de4a754a2dbde1628daff059f431aed3dc871d17 100644 (file)
@@ -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 (file)
index b0925d8..0000000
+++ /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 <kbrenneman@nvidia.com>
-
-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 <feature> 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"):
-        # <param> tags have the same format as a <proto> 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
-
index d556a7782c9438f416213ca5e99b5f66eda8c2fe..fe901fdd5b6c95f0792d4a944ecc4353c534f1fe 100644 (file)
@@ -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():
index 461892f5ae8c02c9bef529ae1f96cfc041f9172f..a23cc36fc2b8b1ead88c0cb299ea4875cc8d3061 100644 (file)
@@ -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,
 )
 
index 97ebdeb1d7f4796559e6417df55a2e40f22eeb57..b46ed814700ffca06981b57848e77592fad7437e 100644 (file)
@@ -31,6 +31,7 @@ pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA =
 
 EXTRA_DIST = \
+       new/genCommon.py \
        es1api/ABI-check \
        es2api/ABI-check \
        mapi_abi.py \
index 798586bfb0cc80eb5ed6ce9eb01ded40cf1fa552..24013c6554270047b989d81a626fe0f3bc4d1c77 100644 (file)
@@ -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 (file)
index 0000000..b0925d8
--- /dev/null
@@ -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 <kbrenneman@nvidia.com>
+
+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 <feature> 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"):
+        # <param> tags have the same format as a <proto> 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
+