1#!/usr/bin/env python
2
3# (C) Copyright IBM Corporation 2004, 2005
4# All Rights Reserved.
5#
6# Permission is hereby granted, free of charge, to any person obtaining a
7# copy of this software and associated documentation files (the "Software"),
8# to deal in the Software without restriction, including without limitation
9# on the rights to use, copy, modify, merge, publish, distribute, sub
10# license, and/or sell copies of the Software, and to permit persons to whom
11# the Software is furnished to do so, subject to the following conditions:
12#
13# The above copyright notice and this permission notice (including the next
14# paragraph) shall be included in all copies or substantial portions of the
15# Software.
16#
17# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
20# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23# IN THE SOFTWARE.
24#
25# Authors:
26#    Ian Romanick <idr@us.ibm.com>
27
28import gl_XML, glX_XML, glX_proto_common, license
29import sys, getopt
30
31
32class glx_doc_item_factory(glX_proto_common.glx_proto_item_factory):
33	"""Factory to create GLX protocol documentation oriented objects derived from glItem."""
34
35	def create_item(self, name, element, context):
36		if name == "parameter":
37			return glx_doc_parameter(element, context)
38		else:
39			return glX_proto_common.glx_proto_item_factory.create_item(self, name, element, context)
40
41
42class glx_doc_parameter(gl_XML.gl_parameter):
43	def packet_type(self, type_dict):
44		"""Get the type string for the packet header
45
46		GLX protocol documentation uses type names like CARD32,
47		FLOAT64, LISTofCARD8, and ENUM.  This function converts the
48		type of the parameter to one of these names."""
49
50		list_of = ""
51		if self.is_array():
52			list_of = "LISTof"
53
54		t_name = self.get_base_type_string()
55		if not type_dict.has_key( t_name ):
56			type_name = "CARD8"
57		else:
58			type_name = type_dict[ t_name ]
59
60		return "%s%s" % (list_of, type_name)
61
62
63	def packet_size(self):
64		p = None
65		s = self.size()
66		if s == 0:
67			a_prod = "n"
68			b_prod = self.p_type.size
69
70			if not self.count_parameter_list and self.counter:
71				a_prod = self.counter
72			elif self.count_parameter_list and not self.counter or self.is_output:
73				pass
74			elif self.count_parameter_list and self.counter:
75				b_prod = self.counter
76			else:
77				raise RuntimeError("Parameter '%s' to function '%s' has size 0." % (self.name, self.context.name))
78
79			ss = "%s*%s" % (a_prod, b_prod)
80
81			return [ss, p]
82		else:
83			if s % 4 != 0:
84				p = "p"
85
86			return [str(s), p]
87
88class PrintGlxProtoText(gl_XML.gl_print_base):
89	def __init__(self):
90		gl_XML.gl_print_base.__init__(self)
91		self.license = ""
92
93
94	def printHeader(self):
95		return
96
97
98	def body_size(self, f):
99		# At some point, refactor this function and
100		# glXFunction::command_payload_length.
101
102		size = 0;
103		size_str = ""
104		pad_str = ""
105		plus = ""
106		for p in f.parameterIterateGlxSend():
107			[s, pad] = p.packet_size()
108			try:
109				size += int(s)
110			except Exception,e:
111				size_str += "%s%s" % (plus, s)
112				plus = "+"
113
114			if pad != None:
115				pad_str = pad
116
117		return [size, size_str, pad_str]
118
119
120	def print_render_header(self, f):
121		[size, size_str, pad_str] = self.body_size(f)
122		size += 4;
123
124		if size_str == "":
125			s = "%u" % ((size + 3) & ~3)
126		elif pad_str != "":
127			s = "%u+%s+%s" % (size, size_str, pad_str)
128		else:
129			s = "%u+%s" % (size, size_str)
130
131		print '            2        %-15s rendering command length' % (s)
132		print '            2        %-4u            rendering command opcode' % (f.glx_rop)
133		return
134
135
136	def print_single_header(self, f):
137		[size, size_str, pad_str] = self.body_size(f)
138		size = ((size + 3) / 4) + 2;
139
140		if f.glx_vendorpriv != 0:
141			size += 1
142
143		print '            1        CARD8           opcode (X assigned)'
144		print '            1        %-4u            GLX opcode (%s)' % (f.opcode_real_value(), f.opcode_real_name())
145
146		if size_str == "":
147			s = "%u" % (size)
148		elif pad_str != "":
149			s = "%u+((%s+%s)/4)" % (size, size_str, pad_str)
150		else:
151			s = "%u+((%s)/4)" % (size, size_str)
152
153		print '            2        %-15s request length' % (s)
154
155		if f.glx_vendorpriv != 0:
156			print '            4        %-4u            vendor specific opcode' % (f.opcode_value())
157
158		print '            4        GLX_CONTEXT_TAG context tag'
159
160		return
161
162
163	def print_reply(self, f):
164		print '          =>'
165		print '            1        1               reply'
166		print '            1                        unused'
167		print '            2        CARD16          sequence number'
168
169		if f.output == None:
170			print '            4        0               reply length'
171		elif f.reply_always_array:
172			print '            4        m               reply length'
173		else:
174			print '            4        m               reply length, m = (n == 1 ? 0 : n)'
175
176
177		output = None
178		for x in f.parameterIterateOutputs():
179			output = x
180			break
181
182
183		unused = 24
184		if f.return_type != 'void':
185			print '            4        %-15s return value' % (f.return_type)
186			unused -= 4
187		elif output != None:
188			print '            4                        unused'
189			unused -= 4
190
191		if output != None:
192			print '            4        CARD32          n'
193			unused -= 4
194
195		if output != None:
196			if not f.reply_always_array:
197				print ''
198				print '            if (n = 1) this follows:'
199				print ''
200				print '            4        CARD32          %s' % (output.name)
201				print '            %-2u                       unused' % (unused - 4)
202				print ''
203				print '            otherwise this follows:'
204				print ''
205
206			print '            %-2u                       unused' % (unused)
207
208			[s, pad] = output.packet_size()
209			print '            %-8s %-15s %s' % (s, output.packet_type( self.type_map ), output.name)
210			if pad != None:
211				try:
212					bytes = int(s)
213					bytes = 4 - (bytes & 3)
214					print '            %-8u %-15s unused' % (bytes, "")
215				except Exception,e:
216					print '            %-8s %-15s unused, %s=pad(%s)' % (pad, "", pad, s)
217		else:
218			print '            %-2u                       unused' % (unused)
219
220
221	def print_body(self, f):
222		for p in f.parameterIterateGlxSend():
223			[s, pad] = p.packet_size()
224			print '            %-8s %-15s %s' % (s, p.packet_type( self.type_map ), p.name)
225			if pad != None:
226				try:
227					bytes = int(s)
228					bytes = 4 - (bytes & 3)
229					print '            %-8u %-15s unused' % (bytes, "")
230				except Exception,e:
231					print '            %-8s %-15s unused, %s=pad(%s)' % (pad, "", pad, s)
232
233	def printBody(self, api):
234		self.type_map = {}
235		for t in api.typeIterate():
236			self.type_map[ "GL" + t.name ] = t.glx_name
237
238
239		# At some point this should be expanded to support pixel
240		# functions, but I'm not going to lose any sleep over it now.
241
242		for f in api.functionIterateByOffset():
243			if f.client_handcode or f.server_handcode or f.vectorequiv or len(f.get_images()):
244				continue
245
246
247			if f.glx_rop:
248				print '        %s' % (f.name)
249				self.print_render_header(f)
250			elif f.glx_sop or f.glx_vendorpriv:
251				print '        %s' % (f.name)
252				self.print_single_header(f)
253			else:
254				continue
255
256			self.print_body(f)
257
258			if f.needs_reply():
259				self.print_reply(f)
260
261			print ''
262		return
263
264
265if __name__ == '__main__':
266	file_name = "gl_API.xml"
267
268	try:
269		(args, trail) = getopt.getopt(sys.argv[1:], "f:")
270	except Exception,e:
271		show_usage()
272
273	for (arg,val) in args:
274		if arg == "-f":
275			file_name = val
276
277	api = gl_XML.parse_GL_API( file_name, glx_doc_item_factory() )
278
279	printer = PrintGlxProtoText()
280	printer.Print( api )
281