On 21 May 2012 11:08, Pauli Nieminen <span dir="ltr">&lt;<a href="mailto:pauli.nieminen@linux.intel.com" target="_blank">pauli.nieminen@linux.intel.com</a>&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
To generate dispatch functions for GLES and EGL we need information<br>
about functions and defines required for those APIs. Too bad there<br>
appears not to be GL like API specification fails. But luckily parsing<br>
headers is simple.<br>
<br>
The parser has support for gl.h, glext.h, gl2.h, gl2ext.h, egl.h and<br>
eglext.h. I didn&#39;t do any automated verification that parsign managed to<br>
capture all enums and functions but all currently used in piglit were<br>
captured.<br></blockquote><div><br>I&#39;m really not comfortable with this approach.  When I first tried writing piglit-dispatch I tried parsing header files, and there were enough inconsistencies in the way the headers were laid out that things felt very fragile.  I think we would be a lot better off adding a little bit of information to the gl.spec and enumext.spec files to cover what piglit-dispatch needs to know about GLES, rather than make parse_glspec.py able to parse an entirely new kind of file.  I believe the only things we would need to add to the .spec files would be (a) for each core GLES function, an annotation of the version of GLES in which the function was added, and (b) for each GLES extension, a description of the functions and enums that extension adds, in the format already used by gl.spec and enumext.spec.<br>
<br>The downside would of course be that piglit&#39;s copies of gl.spec and enumext.spec woud diverge from the files published by <a href="http://www.opengl.org">www.opengl.org</a>.  But that is already happening anyhow, because we&#39;ve found errors and omissions in gl.spec and enumext.spec that we&#39;ve had to correct.  I think the burden of maintaining these .spec files is going to be less than the burden of maintaining code that parses the gles headers.<br>
<br>I&#39;ll try to flesh out my suggestion into an alternative patch series in the next few days.<br> </div><blockquote class="gmail_quote" style="margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<br>
Signed-off-by: Pauli Nieminen &lt;<a href="mailto:pauli.nieminen@linux.intel.com">pauli.nieminen@linux.intel.com</a>&gt;<br>
---<br>
 glapi/parse_glspec.py                |  190 +++++++++++++++++++++++++++++++++-<br>
 tests/texturing/1-1-linear-texture.c |   11 ++-<br>
 2 files changed, 196 insertions(+), 5 deletions(-)<br>
<br>
diff --git a/glapi/parse_glspec.py b/glapi/parse_glspec.py<br>
index d2be059..68c72fe 100644<br>
--- a/glapi/parse_glspec.py<br>
+++ b/glapi/parse_glspec.py<br>
@@ -130,6 +130,15 @@ GLSPEC_EXT_VERSION_REGEXP = re.compile(r&#39;^passthru:\s+/\*\sOpenGL\s+([0-9.]+)\s+<br>
 GLSPEC_EXT_REGEXP = re.compile(r&#39;^passthru:\s+/\*\s+(\w+)&#39;)<br>
 GL_VERSION_REGEXP = re.compile(&#39;^VERSION_([0-9])_([0-9])(_DEPRECATED)?$&#39;)<br>
 ENUM_REGEXP = re.compile(r&#39;^\s+(\w+)\s+=\s+(\w+)$&#39;)<br>
+H_VERSION_REGEXP = re.compile(r&#39;^#define\s+(EGL|GL_ES|GL)_VERSION_E?S?_?C?[ML]?_?(\d+)_(\d)&#39;)<br>
+H_ENUM_REGEXP = re.compile(r&#39;^#define\s+(\w+)\s+([^\s]+)$&#39;)<br>
+H_EXT_START_REGEXP = re.compile(r&#39;^#ifndef\s+(E?GL_\w+)$&#39;)<br>
+H_EXT_END_REGEXP = re.compile(r&#39;^#endif$&#39;)<br>
+H_DETECT_EGL_REGEXP = re.compile(r&#39;^#ifndef\s+__egl\w*_h_$&#39;)<br>
+H_FUNC_REGEXP = re.compile(r&#39;^E?GL_?APIC?A?L?L?\s+(.+[\w*])\s+E?GL_?APIENTRY\s+(e?gl\w+)\s*\(([^)]*)(\)?;?)$&#39;)<br>
+H_FUNC_PARAM_REGEXP = re.compile(r&#39;^\s+([^)]*)(\)?;?)$&#39;)<br>
+H_GET_PROC_ADDRESS_START_REGEXP = re.compile(r&#39;^EGLAPI\s+(\w+)\s+\w+$&#39;)<br>
+H_GET_PROC_ADDRESS_END_REGEXP = re.compile(r&#39;^\s*(\w+)\((.+)\);$&#39;)<br>
<br>
<br>
 # Convert a type into a canonical form that is consistent about its<br>
@@ -179,6 +188,28 @@ def filter_comments(f):<br>
         if line != &#39;&#39;:<br>
             yield line.rstrip()<br>
<br>
+# Iterate through a file discarding all C comments and empty lines<br>
+# XXX: Support for C99 comments<br>
+# XXX: A new comment after multi-line comment isn&#39;t parsed correctly<br>
+def filter_comments_c(f):<br>
+    incomment = False<br>
+    for line in f:<br>
+       while not incomment and &#39;/*&#39; in line:<br>
+           end = &#39;&#39;<br>
+           if &#39;*/&#39; in line:<br>
+               end = line[line.find(&#39;*/&#39;)+2:]<br>
+           else:<br>
+               incomment = True<br>
+           line = line[:line.find(&#39;/*&#39;)]<br>
+       if incomment:<br>
+           if &#39;*/&#39; in line:<br>
+               line = line[line.find(&#39;*/&#39;)+2:]<br>
+               incomment = False<br>
+           else:<br>
+               line = &#39;&#39;<br>
+       line = line.rstrip()<br>
+       if line != &#39;&#39;:<br>
+           yield line<br>
<br>
 # Convert a category name from the form used in the gl.spec file to<br>
 # the form we want to output in JSON.  E.g.:<br>
@@ -464,9 +495,9 @@ class Api(object):<br>
     #                             &#39;value_str&#39;: &quot;0xFFFFFFFF&quot; }<br>
     def parse_enum(self, m):<br>
        name, value = m.groups()<br>
-       if not name.startswith(&#39;GL_&#39;):<br>
+       if not name.startswith(&#39;GL_&#39;) and not name.startswith(&#39;EGL_&#39;):<br>
            name = &#39;GL_&#39; + name<br>
-       if value.startswith(&#39;GL_&#39;):<br>
+       if value.startswith(&#39;GL_&#39;) or value.startswith(&#39;EGL_&#39;):<br>
            value_rhs = value<br>
            value_int = self.enums[value_rhs][&#39;value_int&#39;]<br>
        else:<br>
@@ -482,6 +513,158 @@ class Api(object):<br>
            if m:<br>
                self.parse_enum(m)<br>
<br>
+    # Parse parameter string to type and name lists<br>
+    def parse_params(self, params):<br>
+        params = params.strip()<br>
+        if params == &#39;void&#39;:<br>
+            return [], []<br>
+        split = normalize_type(params).split(&#39;, &#39;)<br>
+        i = 0<br>
+        types = []<br>
+        names = []<br>
+        for p in split:<br>
+            t = &#39;&#39;<br>
+            # Default name if not in header<br>
+            n = &#39;param&#39; + str(i)<br>
+            i = i + 1<br>
+            # figure out if we have variable name<br>
+            words = p.split()<br>
+            last = words.pop()<br>
+            index = last.rfind(&#39;*&#39;)<br>
+            if index != -1:<br>
+                words.append(last[:index + 1])<br>
+                last = last[index + 1:]<br>
+            if last != &#39;&#39; and last not in self.type_translation.values():<br>
+                n = last<br>
+            elif last != &#39;&#39;:<br>
+                words.append(last)<br>
+            t = &#39; &#39;.join(words)<br>
+<br>
+            types.append(t)<br>
+            names.append(n)<br>
+<br>
+        return types, names<br>
+<br>
+    # Insert es and egl function to functions and alias dictionaries<br>
+    def insert_es_function(self, ret, name, params, category):<br>
+        if name.startswith(&#39;gl&#39;):<br>
+            name = name[2:]<br>
+        param_types, param_names = self.parse_params(params)<br>
+       ret = normalize_type(ret)<br>
+        if name not in self.functions:<br>
+            self.functions[name] = {<br>
+                    &#39;return_type&#39;: ret,<br>
+                    &#39;param_types&#39;: param_types,<br>
+                    &#39;param_names&#39;: param_names,<br>
+                    &#39;category&#39;: [category],<br>
+                    }<br>
+            core_name = re.sub(r&#39;[A-Z]*$&#39;,&#39;&#39;, name)<br>
+            # XXX: Do we need manual list of aliases? */<br>
+            if core_name != name and core_name in self.functions and \<br>
+                    cmp(param_types, self.functions[core_name][&#39;param_types&#39;]) == 0 and \<br>
+                    ret == self.functions[core_name][&#39;return_type&#39;]:<br>
+                self.synonyms.add_alias(core_name, name)<br>
+            else:<br>
+                self.synonyms.add_singleton(name)<br>
+        else:<br>
+            if self.functions[name][&#39;return_type&#39;] != ret or \<br>
+                    cmp(self.functions[name][&#39;param_types&#39;], param_types) != 0:<br>
+                print &quot;Function &quot;+ name +&quot; type doesn&#39;t match&quot;<br>
+                print &quot;ES: &quot; + str(ret) + &quot; &quot; + str(param_types)<br>
+                print &quot;GL: &quot; + str(self.functions[name][&#39;return_type&#39;]) + \<br>
+                        &quot; &quot; + str(self.functions[name][&#39;param_types&#39;])<br>
+            self.functions[name][&#39;category&#39;].append(category)<br>
+<br>
+    def read_header(self, f):<br>
+        major = 0<br>
+        minor = 0<br>
+        category = None<br>
+        # GLES1 defines required extensions in core header<br>
+        es_version = None<br>
+        kind_suffix = &#39;ES&#39;<br>
+        func_name = None<br>
+        func_return = None<br>
+        func_params = None<br>
+        for line in filter_comments_c(f):<br>
+            m = H_DETECT_EGL_REGEXP.match(line)<br>
+            if m:<br>
+                kind_suffix = &#39;EGL&#39;<br>
+                continue<br>
+            m = H_VERSION_REGEXP.match(line)<br>
+            if m:<br>
+                kind, major_new, minor_new = m.groups()<br>
+                if kind in [&#39;GL&#39;, &#39;GL_ES&#39;]:<br>
+                    kind = &#39;ES&#39;<br>
+                category_new = kind + major_new + &#39;.&#39; + minor_new<br>
+                self.categories[category_new] = {<br>
+                        &#39;kind&#39;: kind,<br>
+                        &#39;gl_10x_version&#39;: int(major_new+minor_new)<br>
+                        }<br>
+                if major &gt; major_new and minor &gt; minor_new:<br>
+                    continue<br>
+                major = major_new<br>
+                minor = minor_new<br>
+                category = category_new<br>
+                es_version = category_new<br>
+                continue<br>
+            m = H_EXT_START_REGEXP.match(line)<br>
+            if m:<br>
+                category = m.group(1)<br>
+                if category in self.categories:<br>
+                    continue<br>
+                self.categories[category] = {<br>
+                        &#39;kind&#39;: &#39;extension_&#39; + kind_suffix,<br>
+                        &#39;extension_name&#39;: category<br>
+                        }<br>
+                continue<br>
+            m = H_EXT_END_REGEXP.match(line)<br>
+            if m:<br>
+                category = es_version<br>
+                continue<br>
+            m = H_ENUM_REGEXP.match(line)<br>
+            if m and m.group(1) not in self.categories:<br>
+                self.parse_enum(m)<br>
+                continue<br>
+            if func_name != None:<br>
+                m = H_FUNC_PARAM_REGEXP.match(line)<br>
+                if m:<br>
+                    func_params = func_params + m.group(1)<br>
+                    if m.group(2) != &#39;);&#39;:<br>
+                        func_params = func_params + &#39; &#39;<br>
+                        continue<br>
+                    self.insert_es_function(func_return, func_name, func_params, category)<br>
+                    func_return = None<br>
+                    func_name = None<br>
+                    func_params = None<br>
+                    continue<br>
+<br>
+            m = H_FUNC_REGEXP.match(line)<br>
+            if m:<br>
+                func_return, func_name, func_params, end = m.groups()<br>
+                if end != &#39;);&#39;:<br>
+                    func_params = func_params + &#39; &#39;<br>
+                    continue<br>
+                self.insert_es_function(func_return, func_name, func_params, category)<br>
+                func_return = None<br>
+                func_name = None<br>
+                func_params = None<br>
+                continue<br>
+<br>
+            if func_return != None:<br>
+                m = H_GET_PROC_ADDRESS_END_REGEXP.match(line)<br>
+                if m:<br>
+                    func_name, func_params = m.groups()<br>
+                    self.insert_es_function(func_return, func_name, func_params, category)<br>
+                    func_return = None<br>
+                    func_name = None<br>
+                    func_params = None<br>
+                    continue<br>
+<br>
+            m = H_GET_PROC_ADDRESS_START_REGEXP.match(line)<br>
+            if m:<br>
+                func_return = m.group(1)<br>
+                continue<br>
+<br>
     # Convert the stored API into JSON.  To make diffing easier, all<br>
     # dictionaries are sorted by key, and all sets are sorted by set<br>
     # element.<br>
@@ -509,6 +692,9 @@ if __name__ == &#39;__main__&#39;:<br>
        elif name.endswith(&#39;enumext.spec&#39;):<br>
            with open(name) as f:<br>
                api.read_enumext_spec(f)<br>
+       elif name.endswith(&#39;.h&#39;):<br>
+           with open(name) as f:<br>
+               api.read_header(f)<br>
        elif name.endswith(&#39;.json&#39;):<br>
            with open(name, &#39;w&#39;) as f:<br>
                f.write(api.to_json())<br>
diff --git a/tests/texturing/1-1-linear-texture.c b/tests/texturing/1-1-linear-texture.c<br>
index 2be7cd3..9e62cb9 100644<br>
--- a/tests/texturing/1-1-linear-texture.c<br>
+++ b/tests/texturing/1-1-linear-texture.c<br>
@@ -31,8 +31,8 @@<br>
<br>
 #include &quot;piglit-util.h&quot;<br>
<br>
-int piglit_width = 100;<br>
-int piglit_height = 100;<br>
+int piglit_width = 128;<br>
+int piglit_height = 128;<br>
 int piglit_window_mode = GLUT_RGB | GLUT_DOUBLE;<br>
<br>
 #define DATA_SIZE      (piglit_width * piglit_height * 4)<br>
@@ -135,5 +135,10 @@ piglit_display(void)<br>
 void<br>
 piglit_init(int argc, char **argv)<br>
 {<br>
-       piglit_require_extension(&quot;GL_ARB_texture_rectangle&quot;);<br>
+       if (!piglit_is_gles())<br>
+               piglit_require_extension(&quot;GL_ARB_texture_rectangle&quot;);<br>
+       else if (piglit_get_gl_version() &gt;= 20) {<br>
+               fprintf(stderr, &quot;This test requires GLES version 1.1\n&quot;);<br>
+               piglit_report_result(PIGLIT_SKIP);<br>
+       }<br>
 }<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.5.4<br>
<br>
_______________________________________________<br>
Piglit mailing list<br>
<a href="mailto:Piglit@lists.freedesktop.org">Piglit@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/piglit" target="_blank">http://lists.freedesktop.org/mailman/listinfo/piglit</a><br>
</font></span></blockquote></div><br>