1261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick#!/bin/env python 2261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 3261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# (C) Copyright IBM Corporation 2005, 2006 4261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# All Rights Reserved. 5261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# 6261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# Permission is hereby granted, free of charge, to any person obtaining a 7261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# copy of this software and associated documentation files (the "Software"), 8261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# to deal in the Software without restriction, including without limitation 9261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# on the rights to use, copy, modify, merge, publish, distribute, sub 10261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# license, and/or sell copies of the Software, and to permit persons to whom 11261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# the Software is furnished to do so, subject to the following conditions: 12261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# 13261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# The above copyright notice and this permission notice (including the next 14261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# paragraph) shall be included in all copies or substantial portions of the 15261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# Software. 16261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# 17261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 20261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 23261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# IN THE SOFTWARE. 24261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# 25261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# Authors: 26261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick# Ian Romanick <idr@us.ibm.com> 27261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 284169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanickimport gl_XML, glX_XML, glX_proto_common, license 29261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanickimport sys, getopt 30261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 31261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 32261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanickdef log2(value): 33261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for i in range(0, 30): 34261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick p = 1 << i 35261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if p >= value: 36261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return i 37261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 38261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return -1 39261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 40261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 41261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanickdef round_down_to_power_of_two(n): 42261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick """Returns the nearest power-of-two less than or equal to n.""" 43261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 44261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for i in range(30, 0, -1): 45261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick p = 1 << i 46261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if p <= n: 47261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return p 48261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 49261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return -1 50261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 51261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 52261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanickclass function_table: 53261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def __init__(self, name, do_size_check): 54261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.name_base = name 55261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.do_size_check = do_size_check 56261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 57261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 58261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.max_bits = 1 59261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.next_opcode_threshold = (1 << self.max_bits) 60261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.max_opcode = 0 61261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 62261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.functions = {} 63261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.lookup_table = [] 64261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 65261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # Minimum number of opcodes in a leaf node. 66261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.min_op_bits = 3 67261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.min_op_count = (1 << self.min_op_bits) 68261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 69261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 70261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 71261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def append(self, opcode, func): 72261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.functions[opcode] = func 73261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 74261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if opcode > self.max_opcode: 75261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.max_opcode = opcode 76261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 77261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if opcode > self.next_opcode_threshold: 78261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick bits = log2(opcode) 79261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if (1 << bits) <= opcode: 80261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick bits += 1 81261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 82261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.max_bits = bits 83261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.next_opcode_threshold = 1 << bits 84261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 85261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 86261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 87261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def divide_group(self, min_opcode, total): 88261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick """Divide the group starting min_opcode into subgroups. 89261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick Returns a tuple containing the number of bits consumed by 90261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick the node, the list of the children's tuple, and the number 91261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick of entries in the final array used by this node and its 92261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick children, and the depth of the subtree rooted at the node.""" 93261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 94261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick remaining_bits = self.max_bits - total 95261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick next_opcode = min_opcode + (1 << remaining_bits) 96261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick empty_children = 0 97261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 98261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for M in range(0, remaining_bits): 99261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick op_count = 1 << (remaining_bits - M); 100261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_count = 1 << M; 101261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 102261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick empty_children = 0 103261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick full_children = 0 104261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for i in range(min_opcode, next_opcode, op_count): 105261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick used = 0 106261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick empty = 0 107261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 108261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for j in range(i, i + op_count): 109261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if self.functions.has_key(j): 110261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick used += 1; 111261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 112261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick empty += 1; 113261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 114261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 115261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if empty == op_count: 116261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick empty_children += 1 117261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 118261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if used == op_count: 119261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick full_children += 1 120261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 121261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if (empty_children > 0) or (full_children == child_count) or (op_count <= self.min_op_count): 122261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick break 123261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 124261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 125261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # If all the remaining bits are used by this node, as is the 126261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # case when M is 0 or remaining_bits, the node is a leaf. 127261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 128261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if (M == 0) or (M == remaining_bits): 129261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return [remaining_bits, [], 0, 0] 130261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 131261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick children = [] 132261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick count = 1 133261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick depth = 1 134261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick all_children_are_nonempty_leaf_nodes = 1 135261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for i in range(min_opcode, next_opcode, op_count): 136261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick n = self.divide_group(i, total + M) 137261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 138261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if not (n[1] == [] and not self.is_empty_leaf(i, n[0])): 139261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick all_children_are_nonempty_leaf_nodes = 0 140261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 141261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick children.append(n) 142261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick count += n[2] + 1 143261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 144261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if n[3] >= depth: 145261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick depth = n[3] + 1 146261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 147261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # If all of the child nodes are non-empty leaf nodes, pull 148261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # them up and make this node a leaf. 149261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 150261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if all_children_are_nonempty_leaf_nodes: 151261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return [remaining_bits, [], 0, 0] 152261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 153261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return [M, children, count, depth] 154261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 155261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 156261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def is_empty_leaf(self, base_opcode, M): 157261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for op in range(base_opcode, base_opcode + (1 << M)): 158261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if self.functions.has_key(op): 159261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 0 160261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick break 161261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 162261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 1 163261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 164261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 165261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def dump_tree(self, node, base_opcode, remaining_bits, base_entry, depth): 166261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick M = node[0] 167261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick children = node[1] 168261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_M = remaining_bits - M 169261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 170261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 171261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # This actually an error condition. 172261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if children == []: 173261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 174261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 175261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' /* [%u] -> opcode range [%u, %u], node depth %u */' % (base_entry, base_opcode, base_opcode + (1 << remaining_bits), depth) 176261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %u,' % (M) 177261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 178261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick base_entry += (1 << M) + 1 179261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 180261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_index = base_entry 181261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_base_opcode = base_opcode 182261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for child in children: 183261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if child[1] == []: 184261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if self.is_empty_leaf(child_base_opcode, child_M): 185261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' EMPTY_LEAF,' 186261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 187261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # Emit the index of the next dispatch 188261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # function. Then add all the 189261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # dispatch functions for this leaf 190261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # node to the dispatch function 191261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # lookup table. 192261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 193261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' LEAF(%u),' % (len(self.lookup_table)) 194261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 195261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for op in range(child_base_opcode, child_base_opcode + (1 << child_M)): 196261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if self.functions.has_key(op): 197261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick func = self.functions[op] 198261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick size = func.command_fixed_length() 1994169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick 2004169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick if func.glx_rop != 0: 2014169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick size += 4 2024169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick 2034169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick size = ((size + 3) & ~3) 2044169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick 205261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if func.has_variable_size_request(): 206261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick size_name = "__glX%sReqSize" % (func.name) 207261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 208261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick size_name = "" 209261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 210f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick if func.glx_vendorpriv == op: 211f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick func_name = func.glx_vendorpriv_names[0] 212f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick else: 213f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick func_name = func.name 214f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick 215f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick temp = [op, "__glXDisp_%s" % (func_name), "__glXDispSwap_%s" % (func_name), size, size_name] 216261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 217261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick temp = [op, "NULL", "NULL", 0, ""] 218261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 219261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.lookup_table.append(temp) 220261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 221261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %u,' % (child_index) 222261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_index += child[2] 223261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 224261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_base_opcode += 1 << child_M 225261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 226261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '' 227261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 228261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_index = base_entry 229261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for child in children: 230261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if child[1] != []: 231261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.dump_tree(child, base_opcode, remaining_bits - M, child_index, depth + 1) 232261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick child_index += child[2] 233261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 234261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick base_opcode += 1 << (remaining_bits - M) 235261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 236261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 237261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def Print(self): 238261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # Each dispatch table consists of two data structures. 239261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # 240261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # The first structure is an N-way tree where the opcode for 241261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # the function is the key. Each node switches on a range of 242261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # bits from the opcode. M bits are extracted from the opcde 243261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # and are used as an index to select one of the N, where 244261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # N = 2^M, children. 245261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # 246261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # The tree is stored as a flat array. The first value is the 247261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # number of bits, M, used by the node. For inner nodes, the 248261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # following 2^M values are indexes into the array for the 249261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # child nodes. For leaf nodes, the followign 2^M values are 250261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # indexes into the second data structure. 251261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # 252261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # If an inner node's child index is 0, the child is an empty 253261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # leaf node. That is, none of the opcodes selectable from 254261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # that child exist. Since most of the possible opcode space 255261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # is unused, this allows compact data storage. 256261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # 257261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # The second data structure is an array of pairs of function 258261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # pointers. Each function contains a pointer to a protocol 259261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # decode function and a pointer to a byte-swapped protocol 260261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # decode function. Elements in this array are selected by the 261261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # leaf nodes of the first data structure. 262261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # 263261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # As the tree is traversed, an accumulator is kept. This 264261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # accumulator counts the bits of the opcode consumed by the 265261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # traversal. When accumulator + M = B, where B is the 266261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # maximum number of bits in an opcode, the traversal has 267261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # reached a leaf node. The traversal starts with the most 268261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # significant bits and works down to the least significant 269261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # bits. 270261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # 271261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # Creation of the tree is the most complicated part. At 272261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # each node the elements are divided into groups of 2^M 273261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # elements. The value of M selected is the smallest possible 274261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # value where all of the groups are either empty or full, or 275261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # the groups are a preset minimum size. If all the children 276261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # of a node are non-empty leaf nodes, the children are merged 277261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # to create a single leaf node that replaces the parent. 278261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 279261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick tree = self.divide_group(0, 0) 280261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 281261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '/*****************************************************************/' 282261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '/* tree depth = %u */' % (tree[3]) 283261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print 'static const int_fast16_t %s_dispatch_tree[%u] = {' % (self.name_base, tree[2]) 284261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.dump_tree(tree, 0, self.max_bits, 0, 1) 285261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '};\n' 286261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 287261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick # After dumping the tree, dump the function lookup table. 288261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 2894169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick print 'static const void *%s_function_table[%u][2] = {' % (self.name_base, len(self.lookup_table)) 290261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick index = 0 291261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for func in self.lookup_table: 292261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick opcode = func[0] 293261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick name = func[1] 294261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick name_swap = func[2] 295261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 296261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' /* [% 3u] = %5u */ {%s, %s},' % (index, opcode, name, name_swap) 297261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 298261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick index += 1 299261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 300261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '};\n' 301261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 302261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if self.do_size_check: 303261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick var_table = [] 304261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 305261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print 'static const int_fast16_t %s_size_table[%u][2] = {' % (self.name_base, len(self.lookup_table)) 306261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick index = 0 307261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick var_table = [] 308261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for func in self.lookup_table: 309261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick opcode = func[0] 310261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick fixed = func[3] 311261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick var = func[4] 312261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 313261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if var != "": 3144169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick var_offset = "%2u" % (len(var_table)) 315261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick var_table.append(var) 316261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 317261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick var_offset = "~0" 318261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 3194169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick print ' /* [%3u] = %5u */ {%3u, %s},' % (index, opcode, fixed, var_offset) 320261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick index += 1 321261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 322261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 323261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '};\n' 324261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 325261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 3264169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick print 'static const gl_proto_size_func %s_size_func_table[%u] = {' % (self.name_base, len(var_table)) 327261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for func in var_table: 328261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %s,' % (func) 329261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 330261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '};\n' 331261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 332261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 333261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print 'const struct __glXDispatchInfo %s_dispatch_info = {' % (self.name_base) 334261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %u,' % (self.max_bits) 335261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %s_dispatch_tree,' % (self.name_base) 336261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %s_function_table,' % (self.name_base) 337261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if self.do_size_check: 338261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %s_size_table,' % (self.name_base) 339261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' %s_size_func_table' % (self.name_base) 340261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 341261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' NULL,' 342261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print ' NULL' 343261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '};\n' 344261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 345261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 346261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 3474169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanickclass PrintGlxDispatchTables(glX_proto_common.glx_print_proto): 348261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def __init__(self): 349261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick gl_XML.gl_print_base.__init__(self) 350261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.name = "glX_server_table.py (from Mesa)" 351261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005, 2006", "IBM") 352261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 353261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.rop_functions = function_table("Render", 1) 354261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.sop_functions = function_table("Single", 0) 355261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.vop_functions = function_table("VendorPriv", 0) 356261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 357261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 358261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 359261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def printRealHeader(self): 360261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '#include <inttypes.h>' 361261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '#include "glxserver.h"' 362261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '#include "glxext.h"' 363261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '#include "indirect_dispatch.h"' 364261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '#include "indirect_reqsize.h"' 365261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '#include "indirect_table.h"' 366261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick print '' 367261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 368261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 369261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 370261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick def printBody(self, api): 371261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for f in api.functionIterateAll(): 372261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if not f.ignore and f.vectorequiv == None: 373261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if f.glx_rop != 0: 374261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.rop_functions.append(f.glx_rop, f) 375f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick if f.glx_sop != 0: 376261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.sop_functions.append(f.glx_sop, f) 377f3f51bc844c8749250724d164722402cb9a07dc7Ian Romanick if f.glx_vendorpriv != 0: 378261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.vop_functions.append(f.glx_vendorpriv, f) 379261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 380261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.sop_functions.Print() 3814169c220bdd65bb5a35ab50ae467ab9076f8c4f9Ian Romanick self.rop_functions.Print() 382261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick self.vop_functions.Print() 383261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick return 384261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 385261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 386261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanickif __name__ == '__main__': 387261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick file_name = "gl_API.xml" 388261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 389261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick try: 390261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick (args, trail) = getopt.getopt(sys.argv[1:], "f:m") 391261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick except Exception,e: 392261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick show_usage() 393261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 394261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick mode = "table_c" 395261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick for (arg,val) in args: 396261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if arg == "-f": 397261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick file_name = val 398261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick elif arg == "-m": 399261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick mode = val 400261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 401261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick if mode == "table_c": 402261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick printer = PrintGlxDispatchTables() 403261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick else: 404261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick show_usage() 405261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 406261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 407261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() ) 408261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 409261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick 410261a806f9e26347d756bddeae81f4e98325b8e84Ian Romanick printer.Print( api ) 411