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