1bf215546Sopenharmony_ci
2bf215546Sopenharmony_ci# (C) Copyright IBM Corporation 2005, 2006
3bf215546Sopenharmony_ci# All Rights Reserved.
4bf215546Sopenharmony_ci#
5bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci# on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci# license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci# the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci#
12bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci# Software.
15bf215546Sopenharmony_ci#
16bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21bf215546Sopenharmony_ci# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22bf215546Sopenharmony_ci# IN THE SOFTWARE.
23bf215546Sopenharmony_ci#
24bf215546Sopenharmony_ci# Authors:
25bf215546Sopenharmony_ci#    Ian Romanick <idr@us.ibm.com>
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ciimport argparse
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ciimport gl_XML, glX_XML, glX_proto_common, license
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_cidef log2(value):
33bf215546Sopenharmony_ci    for i in range(0, 30):
34bf215546Sopenharmony_ci        p = 1 << i
35bf215546Sopenharmony_ci        if p >= value:
36bf215546Sopenharmony_ci            return i
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci    return -1
39bf215546Sopenharmony_ci
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_cidef round_down_to_power_of_two(n):
42bf215546Sopenharmony_ci    """Returns the nearest power-of-two less than or equal to n."""
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci    for i in range(30, 0, -1):
45bf215546Sopenharmony_ci        p = 1 << i
46bf215546Sopenharmony_ci        if p <= n:
47bf215546Sopenharmony_ci            return p
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci    return -1
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ciclass function_table:
53bf215546Sopenharmony_ci    def __init__(self, name, do_size_check):
54bf215546Sopenharmony_ci        self.name_base = name
55bf215546Sopenharmony_ci        self.do_size_check = do_size_check
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_ci        self.max_bits = 1
59bf215546Sopenharmony_ci        self.next_opcode_threshold = (1 << self.max_bits)
60bf215546Sopenharmony_ci        self.max_opcode = 0
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci        self.functions = {}
63bf215546Sopenharmony_ci        self.lookup_table = []
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci        # Minimum number of opcodes in a leaf node.
66bf215546Sopenharmony_ci        self.min_op_bits = 3
67bf215546Sopenharmony_ci        self.min_op_count = (1 << self.min_op_bits)
68bf215546Sopenharmony_ci        return
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci    def append(self, opcode, func):
72bf215546Sopenharmony_ci        self.functions[opcode] = func
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci        if opcode > self.max_opcode:
75bf215546Sopenharmony_ci            self.max_opcode = opcode
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci            if opcode > self.next_opcode_threshold:
78bf215546Sopenharmony_ci                bits = log2(opcode)
79bf215546Sopenharmony_ci                if (1 << bits) <= opcode:
80bf215546Sopenharmony_ci                    bits += 1
81bf215546Sopenharmony_ci
82bf215546Sopenharmony_ci                self.max_bits = bits
83bf215546Sopenharmony_ci                self.next_opcode_threshold = 1 << bits
84bf215546Sopenharmony_ci        return
85bf215546Sopenharmony_ci
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci    def divide_group(self, min_opcode, total):
88bf215546Sopenharmony_ci        """Divide the group starting min_opcode into subgroups.
89bf215546Sopenharmony_ci        Returns a tuple containing the number of bits consumed by
90bf215546Sopenharmony_ci        the node, the list of the children's tuple, and the number
91bf215546Sopenharmony_ci        of entries in the final array used by this node and its
92bf215546Sopenharmony_ci        children, and the depth of the subtree rooted at the node."""
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_ci        remaining_bits = self.max_bits - total
95bf215546Sopenharmony_ci        next_opcode = min_opcode + (1 << remaining_bits)
96bf215546Sopenharmony_ci        empty_children = 0
97bf215546Sopenharmony_ci
98bf215546Sopenharmony_ci        for M in range(0, remaining_bits):
99bf215546Sopenharmony_ci            op_count = 1 << (remaining_bits - M);
100bf215546Sopenharmony_ci            child_count = 1 << M;
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_ci            empty_children = 0
103bf215546Sopenharmony_ci            full_children = 0
104bf215546Sopenharmony_ci            for i in range(min_opcode, next_opcode, op_count):
105bf215546Sopenharmony_ci                used = 0
106bf215546Sopenharmony_ci                empty = 0
107bf215546Sopenharmony_ci
108bf215546Sopenharmony_ci                for j in range(i, i + op_count):
109bf215546Sopenharmony_ci                    if self.functions.has_key(j):
110bf215546Sopenharmony_ci                        used += 1;
111bf215546Sopenharmony_ci                    else:
112bf215546Sopenharmony_ci                        empty += 1;
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci                if empty == op_count:
116bf215546Sopenharmony_ci                    empty_children += 1
117bf215546Sopenharmony_ci
118bf215546Sopenharmony_ci                if used == op_count:
119bf215546Sopenharmony_ci                    full_children += 1
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci            if (empty_children > 0) or (full_children == child_count) or (op_count <= self.min_op_count):
122bf215546Sopenharmony_ci                break
123bf215546Sopenharmony_ci
124bf215546Sopenharmony_ci
125bf215546Sopenharmony_ci        # If all the remaining bits are used by this node, as is the
126bf215546Sopenharmony_ci        # case when M is 0 or remaining_bits, the node is a leaf.
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci        if (M == 0) or (M == remaining_bits):
129bf215546Sopenharmony_ci            return [remaining_bits, [], 0, 0]
130bf215546Sopenharmony_ci        else:
131bf215546Sopenharmony_ci            children = []
132bf215546Sopenharmony_ci            count = 1
133bf215546Sopenharmony_ci            depth = 1
134bf215546Sopenharmony_ci            all_children_are_nonempty_leaf_nodes = 1
135bf215546Sopenharmony_ci            for i in range(min_opcode, next_opcode, op_count):
136bf215546Sopenharmony_ci                n = self.divide_group(i, total + M)
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci                if not (n[1] == [] and not self.is_empty_leaf(i, n[0])):
139bf215546Sopenharmony_ci                    all_children_are_nonempty_leaf_nodes = 0
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci                children.append(n)
142bf215546Sopenharmony_ci                count += n[2] + 1
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci                if n[3] >= depth:
145bf215546Sopenharmony_ci                    depth = n[3] + 1
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci            # If all of the child nodes are non-empty leaf nodes, pull
148bf215546Sopenharmony_ci            # them up and make this node a leaf.
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci            if all_children_are_nonempty_leaf_nodes:
151bf215546Sopenharmony_ci                return [remaining_bits, [], 0, 0]
152bf215546Sopenharmony_ci            else:
153bf215546Sopenharmony_ci                return [M, children, count, depth]
154bf215546Sopenharmony_ci
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci    def is_empty_leaf(self, base_opcode, M):
157bf215546Sopenharmony_ci        for op in range(base_opcode, base_opcode + (1 << M)):
158bf215546Sopenharmony_ci            if self.functions.has_key(op):
159bf215546Sopenharmony_ci                return 0
160bf215546Sopenharmony_ci                break
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_ci        return 1
163bf215546Sopenharmony_ci
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci    def dump_tree(self, node, base_opcode, remaining_bits, base_entry, depth):
166bf215546Sopenharmony_ci        M = node[0]
167bf215546Sopenharmony_ci        children = node[1]
168bf215546Sopenharmony_ci        child_M = remaining_bits - M
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci        # This actually an error condition.
172bf215546Sopenharmony_ci        if children == []:
173bf215546Sopenharmony_ci            return
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_ci        print '    /* [%u] -> opcode range [%u, %u], node depth %u */' % (base_entry, base_opcode, base_opcode + (1 << remaining_bits), depth)
176bf215546Sopenharmony_ci        print '    %u,' % (M)
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci        base_entry += (1 << M) + 1
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci        child_index = base_entry
181bf215546Sopenharmony_ci        child_base_opcode = base_opcode
182bf215546Sopenharmony_ci        for child in children:
183bf215546Sopenharmony_ci            if child[1] == []:
184bf215546Sopenharmony_ci                if self.is_empty_leaf(child_base_opcode, child_M):
185bf215546Sopenharmony_ci                    print '    EMPTY_LEAF,'
186bf215546Sopenharmony_ci                else:
187bf215546Sopenharmony_ci                    # Emit the index of the next dispatch
188bf215546Sopenharmony_ci                    # function.  Then add all the
189bf215546Sopenharmony_ci                    # dispatch functions for this leaf
190bf215546Sopenharmony_ci                    # node to the dispatch function
191bf215546Sopenharmony_ci                    # lookup table.
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci                    print '    LEAF(%u),' % (len(self.lookup_table))
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci                    for op in range(child_base_opcode, child_base_opcode + (1 << child_M)):
196bf215546Sopenharmony_ci                        if self.functions.has_key(op):
197bf215546Sopenharmony_ci                            func = self.functions[op]
198bf215546Sopenharmony_ci                            size = func.command_fixed_length()
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci                            if func.glx_rop != 0:
201bf215546Sopenharmony_ci                                size += 4
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci                            size = ((size + 3) & ~3)
204bf215546Sopenharmony_ci
205bf215546Sopenharmony_ci                            if func.has_variable_size_request():
206bf215546Sopenharmony_ci                                size_name = "__glX%sReqSize" % (func.name)
207bf215546Sopenharmony_ci                            else:
208bf215546Sopenharmony_ci                                size_name = ""
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci                            if func.glx_vendorpriv == op:
211bf215546Sopenharmony_ci                                func_name = func.glx_vendorpriv_names[0]
212bf215546Sopenharmony_ci                            else:
213bf215546Sopenharmony_ci                                func_name = func.name
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci                            temp = [op, "__glXDisp_%s" % (func_name), "__glXDispSwap_%s" % (func_name), size, size_name]
216bf215546Sopenharmony_ci                        else:
217bf215546Sopenharmony_ci                            temp = [op, "NULL", "NULL", 0, ""]
218bf215546Sopenharmony_ci
219bf215546Sopenharmony_ci                        self.lookup_table.append(temp)
220bf215546Sopenharmony_ci            else:
221bf215546Sopenharmony_ci                print '    %u,' % (child_index)
222bf215546Sopenharmony_ci                child_index += child[2]
223bf215546Sopenharmony_ci
224bf215546Sopenharmony_ci            child_base_opcode += 1 << child_M
225bf215546Sopenharmony_ci
226bf215546Sopenharmony_ci        print ''
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_ci        child_index = base_entry
229bf215546Sopenharmony_ci        for child in children:
230bf215546Sopenharmony_ci            if child[1] != []:
231bf215546Sopenharmony_ci                self.dump_tree(child, base_opcode, remaining_bits - M, child_index, depth + 1)
232bf215546Sopenharmony_ci                child_index += child[2]
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci            base_opcode += 1 << (remaining_bits - M)
235bf215546Sopenharmony_ci
236bf215546Sopenharmony_ci
237bf215546Sopenharmony_ci    def Print(self):
238bf215546Sopenharmony_ci        # Each dispatch table consists of two data structures.
239bf215546Sopenharmony_ci        #
240bf215546Sopenharmony_ci        # The first structure is an N-way tree where the opcode for
241bf215546Sopenharmony_ci        # the function is the key.  Each node switches on a range of
242bf215546Sopenharmony_ci        # bits from the opcode.  M bits are extracted from the opcde
243bf215546Sopenharmony_ci        # and are used as an index to select one of the N, where
244bf215546Sopenharmony_ci        # N = 2^M, children.
245bf215546Sopenharmony_ci        #
246bf215546Sopenharmony_ci        # The tree is stored as a flat array.  The first value is the
247bf215546Sopenharmony_ci        # number of bits, M, used by the node.  For inner nodes, the
248bf215546Sopenharmony_ci        # following 2^M values are indexes into the array for the
249bf215546Sopenharmony_ci        # child nodes.  For leaf nodes, the followign 2^M values are
250bf215546Sopenharmony_ci        # indexes into the second data structure.
251bf215546Sopenharmony_ci        #
252bf215546Sopenharmony_ci        # If an inner node's child index is 0, the child is an empty
253bf215546Sopenharmony_ci        # leaf node.  That is, none of the opcodes selectable from
254bf215546Sopenharmony_ci        # that child exist.  Since most of the possible opcode space
255bf215546Sopenharmony_ci        # is unused, this allows compact data storage.
256bf215546Sopenharmony_ci        #
257bf215546Sopenharmony_ci        # The second data structure is an array of pairs of function
258bf215546Sopenharmony_ci        # pointers.  Each function contains a pointer to a protocol
259bf215546Sopenharmony_ci        # decode function and a pointer to a byte-swapped protocol
260bf215546Sopenharmony_ci        # decode function.  Elements in this array are selected by the
261bf215546Sopenharmony_ci        # leaf nodes of the first data structure.
262bf215546Sopenharmony_ci        #
263bf215546Sopenharmony_ci        # As the tree is traversed, an accumulator is kept.  This
264bf215546Sopenharmony_ci        # accumulator counts the bits of the opcode consumed by the
265bf215546Sopenharmony_ci        # traversal.  When accumulator + M = B, where B is the
266bf215546Sopenharmony_ci        # maximum number of bits in an opcode, the traversal has
267bf215546Sopenharmony_ci        # reached a leaf node.  The traversal starts with the most
268bf215546Sopenharmony_ci        # significant bits and works down to the least significant
269bf215546Sopenharmony_ci        # bits.
270bf215546Sopenharmony_ci        #
271bf215546Sopenharmony_ci        # Creation of the tree is the most complicated part.  At
272bf215546Sopenharmony_ci        # each node the elements are divided into groups of 2^M
273bf215546Sopenharmony_ci        # elements.  The value of M selected is the smallest possible
274bf215546Sopenharmony_ci        # value where all of the groups are either empty or full, or
275bf215546Sopenharmony_ci        # the groups are a preset minimum size.  If all the children
276bf215546Sopenharmony_ci        # of a node are non-empty leaf nodes, the children are merged
277bf215546Sopenharmony_ci        # to create a single leaf node that replaces the parent.
278bf215546Sopenharmony_ci
279bf215546Sopenharmony_ci        tree = self.divide_group(0, 0)
280bf215546Sopenharmony_ci
281bf215546Sopenharmony_ci        print '/*****************************************************************/'
282bf215546Sopenharmony_ci        print '/* tree depth = %u */' % (tree[3])
283bf215546Sopenharmony_ci        print 'static const int_fast16_t %s_dispatch_tree[%u] = {' % (self.name_base, tree[2])
284bf215546Sopenharmony_ci        self.dump_tree(tree, 0, self.max_bits, 0, 1)
285bf215546Sopenharmony_ci        print '};\n'
286bf215546Sopenharmony_ci
287bf215546Sopenharmony_ci        # After dumping the tree, dump the function lookup table.
288bf215546Sopenharmony_ci
289bf215546Sopenharmony_ci        print 'static const void *%s_function_table[%u][2] = {' % (self.name_base, len(self.lookup_table))
290bf215546Sopenharmony_ci        index = 0
291bf215546Sopenharmony_ci        for func in self.lookup_table:
292bf215546Sopenharmony_ci            opcode = func[0]
293bf215546Sopenharmony_ci            name = func[1]
294bf215546Sopenharmony_ci            name_swap = func[2]
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci            print '    /* [% 3u] = %5u */ {%s, %s},' % (index, opcode, name, name_swap)
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci            index += 1
299bf215546Sopenharmony_ci
300bf215546Sopenharmony_ci        print '};\n'
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci        if self.do_size_check:
303bf215546Sopenharmony_ci            var_table = []
304bf215546Sopenharmony_ci
305bf215546Sopenharmony_ci            print 'static const int_fast16_t %s_size_table[%u][2] = {' % (self.name_base, len(self.lookup_table))
306bf215546Sopenharmony_ci            index = 0
307bf215546Sopenharmony_ci            var_table = []
308bf215546Sopenharmony_ci            for func in self.lookup_table:
309bf215546Sopenharmony_ci                opcode = func[0]
310bf215546Sopenharmony_ci                fixed = func[3]
311bf215546Sopenharmony_ci                var = func[4]
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci                if var != "":
314bf215546Sopenharmony_ci                    var_offset = "%2u" % (len(var_table))
315bf215546Sopenharmony_ci                    var_table.append(var)
316bf215546Sopenharmony_ci                else:
317bf215546Sopenharmony_ci                    var_offset = "~0"
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci                print '    /* [%3u] = %5u */ {%3u, %s},' % (index, opcode, fixed, var_offset)
320bf215546Sopenharmony_ci                index += 1
321bf215546Sopenharmony_ci
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci            print '};\n'
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci            print 'static const gl_proto_size_func %s_size_func_table[%u] = {' % (self.name_base, len(var_table))
327bf215546Sopenharmony_ci            for func in var_table:
328bf215546Sopenharmony_ci                print '   %s,' % (func)
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_ci            print '};\n'
331bf215546Sopenharmony_ci
332bf215546Sopenharmony_ci
333bf215546Sopenharmony_ci        print 'const struct __glXDispatchInfo %s_dispatch_info = {' % (self.name_base)
334bf215546Sopenharmony_ci        print '    %u,' % (self.max_bits)
335bf215546Sopenharmony_ci        print '    %s_dispatch_tree,' % (self.name_base)
336bf215546Sopenharmony_ci        print '    %s_function_table,' % (self.name_base)
337bf215546Sopenharmony_ci        if self.do_size_check:
338bf215546Sopenharmony_ci            print '    %s_size_table,' % (self.name_base)
339bf215546Sopenharmony_ci            print '    %s_size_func_table' % (self.name_base)
340bf215546Sopenharmony_ci        else:
341bf215546Sopenharmony_ci            print '    NULL,'
342bf215546Sopenharmony_ci            print '    NULL'
343bf215546Sopenharmony_ci        print '};\n'
344bf215546Sopenharmony_ci        return
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci
347bf215546Sopenharmony_ciclass PrintGlxDispatchTables(glX_proto_common.glx_print_proto):
348bf215546Sopenharmony_ci    def __init__(self):
349bf215546Sopenharmony_ci        gl_XML.gl_print_base.__init__(self)
350bf215546Sopenharmony_ci        self.name = "glX_server_table.py (from Mesa)"
351bf215546Sopenharmony_ci        self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005, 2006", "IBM")
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci        self.rop_functions = function_table("Render", 1)
354bf215546Sopenharmony_ci        self.sop_functions = function_table("Single", 0)
355bf215546Sopenharmony_ci        self.vop_functions = function_table("VendorPriv", 0)
356bf215546Sopenharmony_ci        return
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci    def printRealHeader(self):
360bf215546Sopenharmony_ci        print '#include <inttypes.h>'
361bf215546Sopenharmony_ci        print '#include "glxserver.h"'
362bf215546Sopenharmony_ci        print '#include "glxext.h"'
363bf215546Sopenharmony_ci        print '#include "indirect_dispatch.h"'
364bf215546Sopenharmony_ci        print '#include "indirect_reqsize.h"'
365bf215546Sopenharmony_ci        print '#include "indirect_table.h"'
366bf215546Sopenharmony_ci        print ''
367bf215546Sopenharmony_ci        return
368bf215546Sopenharmony_ci
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci    def printBody(self, api):
371bf215546Sopenharmony_ci        for f in api.functionIterateAll():
372bf215546Sopenharmony_ci            if not f.ignore and f.vectorequiv == None:
373bf215546Sopenharmony_ci                if f.glx_rop != 0:
374bf215546Sopenharmony_ci                    self.rop_functions.append(f.glx_rop, f)
375bf215546Sopenharmony_ci                if f.glx_sop != 0:
376bf215546Sopenharmony_ci                    self.sop_functions.append(f.glx_sop, f)
377bf215546Sopenharmony_ci                if f.glx_vendorpriv != 0:
378bf215546Sopenharmony_ci                    self.vop_functions.append(f.glx_vendorpriv, f)
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci        self.sop_functions.Print()
381bf215546Sopenharmony_ci        self.rop_functions.Print()
382bf215546Sopenharmony_ci        self.vop_functions.Print()
383bf215546Sopenharmony_ci        return
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_cidef _parser():
387bf215546Sopenharmony_ci    """Parse arguments and return namespace."""
388bf215546Sopenharmony_ci    parser = argparse.ArgumentParser()
389bf215546Sopenharmony_ci    parser.add_argument('-f',
390bf215546Sopenharmony_ci                        dest='filename',
391bf215546Sopenharmony_ci                        default='gl_API.xml',
392bf215546Sopenharmony_ci                        help='An XML file describing an API.')
393bf215546Sopenharmony_ci    return parser.parse_args()
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ciif __name__ == '__main__':
397bf215546Sopenharmony_ci    args = _parser()
398bf215546Sopenharmony_ci    printer = PrintGlxDispatchTables()
399bf215546Sopenharmony_ci    api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci    printer.Print(api)
402