glX_proto_send.py revision 47719fda0c2fba13c81e84e33523d5489263182e
1#!/usr/bin/python2
2
3# (C) Copyright IBM Corporation 2004
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
28from xml.sax import saxutils
29from xml.sax import make_parser
30from xml.sax.handler import feature_namespaces
31
32import gl_XML
33import license
34import sys, getopt
35
36
37def printPure():
38	print """#  if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
39#    define PURE __attribute__((pure))
40#  else
41#    define PURE
42#  endif"""
43
44def printFastcall():
45	print """#  if defined(__i386__) && defined(__GNUC__)
46#    define FASTCALL __attribute__((fastcall))
47#  else
48#    define FASTCALL
49#  endif"""
50
51def printVisibility(S, s):
52	print """#  if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
53#    define %s  __attribute__((visibility("%s")))
54#  else
55#    define %s
56#  endif""" % (S, s, S)
57
58def printNoinline():
59	print """#  if defined(__GNUC__)
60#    define NOINLINE __attribute__((noinline))
61#  else
62#    define NOINLINE
63#  endif"""
64
65
66class glXItemFactory(gl_XML.glItemFactory):
67	"""Factory to create GLX protocol oriented objects derived from glItem."""
68
69	def create(self, context, name, attrs):
70		if name == "function":
71			return glXFunction(context, name, attrs)
72		elif name == "enum":
73			return glXEnum(context, name, attrs)
74		elif name == "param":
75			return glXParameter(context, name, attrs)
76		else:
77			return gl_XML.glItemFactory.create(self, context, name, attrs)
78
79class glXEnumFunction:
80	def __init__(self, name):
81		self.name = name
82
83		# "enums" is a set of lists.  The element in the set is the
84		# value of the enum.  The list is the list of names for that
85		# value.  For example, [0x8126] = {"POINT_SIZE_MIN",
86		# "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT",
87		# "POINT_SIZE_MIN_SGIS"}.
88
89		self.enums = {}
90
91		# "count" is indexed by count values.  Each element of count
92		# is a list of index to "enums" that have that number of
93		# associated data elements.  For example, [4] =
94		# {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
95		# GL_AMBIENT_AND_DIFFUSE} (the enum names are used here,
96		# but the actual hexadecimal values would be in the array).
97
98		self.count = {}
99
100
101	def append(self, count, value, name):
102		if self.enums.has_key( value ):
103			self.enums[value].append(name)
104		else:
105			if not self.count.has_key(count):
106				self.count[count] = []
107
108			self.enums[value] = []
109			self.enums[value].append(name)
110			self.count[count].append(value)
111
112
113	def signature( self ):
114		sig = ""
115		for i in self.count:
116			for e in self.count[i]:
117				sig += "%04x,%u," % (e, i)
118
119		return sig;
120
121
122	def PrintUsingTable(self):
123		"""Emit the body of the __gl*_size function using a pair
124		of look-up tables and a mask.  The mask is calculated such
125		that (e & mask) is unique for all the valid values of e for
126		this function.  The result of (e & mask) is used as an index
127		into the first look-up table.  If it matches e, then the
128		same entry of the second table is returned.  Otherwise zero
129		is returned.
130
131		It seems like this should cause better code to be generated.
132		However, on x86 at least, the resulting .o file is about 20%
133		larger then the switch-statment version.  I am leaving this
134		code in because the results may be different on other
135		platforms (e.g., PowerPC or x86-64)."""
136
137		return 0
138		count = 0
139		for a in self.enums:
140			count += 1
141
142		# Determine if there is some mask M, such that M = (2^N) - 1,
143		# that will generate unique values for all of the enums.
144
145		mask = 0
146		for i in [1, 2, 3, 4, 5, 6, 7, 8]:
147			mask = (1 << i) - 1
148
149			fail = 0;
150			for a in self.enums:
151				for b in self.enums:
152					if a != b:
153						if (a & mask) == (b & mask):
154							fail = 1;
155
156			if not fail:
157				break;
158			else:
159				mask = 0
160
161		if (mask != 0) and (mask < (2 * count)):
162			masked_enums = {}
163			masked_count = {}
164
165			for i in range(0, mask + 1):
166				masked_enums[i] = "0";
167				masked_count[i] = 0;
168
169			for c in self.count:
170				for e in self.count[c]:
171					i = e & mask
172					masked_enums[i] = '0x%04x /* %s */' % (e, self.enums[e][0])
173					masked_count[i] = c
174
175
176			print '    static const GLushort a[%u] = {' % (mask + 1)
177			for e in masked_enums:
178				print '        %s, ' % (masked_enums[e])
179			print '    };'
180
181			print '    static const GLubyte b[%u] = {' % (mask + 1)
182			for c in masked_count:
183				print '        %u, ' % (masked_count[c])
184			print '    };'
185
186			print '    const unsigned idx = (e & 0x%02xU);' % (mask)
187			print ''
188			print '    return (e == a[idx]) ? (GLint) b[idx] : 0;'
189			return 1;
190		else:
191			return 0;
192
193	def PrintUsingSwitch(self):
194		"""Emit the body of the __gl*_size function using a
195		switch-statement."""
196
197		print '    switch( e ) {'
198
199		for c in self.count:
200			for e in self.count[c]:
201				first = 1
202
203				# There may be multiple enums with the same
204				# value.  This happens has extensions are
205				# promoted from vendor-specific or EXT to
206				# ARB and to the core.  Emit the first one as
207				# a case label, and emit the others as
208				# commented-out case labels.
209
210				for j in self.enums[e]:
211					if first:
212						print '        case %s:' % (j)
213						first = 0
214					else:
215						print '/*      case %s:*/' % (j)
216
217			print '            return %u;' % (c)
218
219		print '        default: return 0;'
220		print '    }'
221
222
223	def Print(self, name):
224		print 'INTERNAL PURE FASTCALL GLint'
225		print '__gl%s_size( GLenum e )' % (name)
226		print '{'
227
228		if not self.PrintUsingTable():
229			self.PrintUsingSwitch()
230
231		print '}'
232		print ''
233
234
235
236class glXEnum(gl_XML.glEnum):
237	def __init__(self, context, name, attrs):
238		gl_XML.glEnum.__init__(self, context, name, attrs)
239		self.glx_functions = []
240
241	def startElement(self, name, attrs):
242		if name == "size":
243			n = attrs.get('name', None)
244			if not self.context.glx_enum_functions.has_key( n ):
245				f = glXEnumFunction( n )
246				self.context.glx_enum_functions[ f.name ] = f
247
248			temp = attrs.get('count', None)
249			try:
250				c = int(temp)
251			except Exception,e:
252				raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
253
254			self.context.glx_enum_functions[ n ].append( c, self.value, self.name )
255		else:
256			gl_XML.glEnum.startElement(self, context, name, attrs)
257		return
258
259
260class glXParameter(gl_XML.glParameter):
261	def __init__(self, context, name, attrs):
262		self.order = 1;
263		gl_XML.glParameter.__init__(self, context, name, attrs);
264
265
266class glXFunction(gl_XML.glFunction):
267	glx_rop = 0
268	glx_sop = 0
269	glx_vendorpriv = 0
270
271	# If this is set to true, it means that GLdouble parameters should be
272	# written to the GLX protocol packet in the order they appear in the
273	# prototype.  This is different from the "classic" ordering.  In the
274	# classic ordering GLdoubles are written to the protocol packet first,
275	# followed by non-doubles.  NV_vertex_program was the first extension
276	# to break with this tradition.
277
278	glx_doubles_in_order = 0
279
280	vectorequiv = None
281	handcode = 0
282	ignore = 0
283	can_be_large = 0
284
285	def __init__(self, context, name, attrs):
286		self.vectorequiv = attrs.get('vectorequiv', None)
287		self.count_parameters = None
288		self.counter = None
289		self.output = None
290		self.can_be_large = 0
291		self.reply_always_array = 0
292
293		gl_XML.glFunction.__init__(self, context, name, attrs)
294		return
295
296	def startElement(self, name, attrs):
297		"""Process elements within a function that are specific to GLX."""
298
299		if name == "glx":
300			self.glx_rop = int(attrs.get('rop', "0"))
301			self.glx_sop = int(attrs.get('sop', "0"))
302			self.glx_vendorpriv = int(attrs.get('vendorpriv', "0"))
303
304			if attrs.get('handcode', "false") == "true":
305				self.handcode = 1
306			else:
307				self.handcode = 0
308
309			if attrs.get('ignore', "false") == "true":
310				self.ignore = 1
311			else:
312				self.ignore = 0
313
314			if attrs.get('large', "false") == "true":
315				self.can_be_large = 1
316			else:
317				self.can_be_large = 0
318
319			if attrs.get('doubles_in_order', "false") == "true":
320				self.glx_doubles_in_order = 1
321			else:
322				self.glx_doubles_in_order = 0
323
324			if attrs.get('always_array', "false") == "true":
325				self.reply_always_array = 1
326			else:
327				self.reply_always_array = 0
328
329		else:
330			gl_XML.glFunction.startElement(self, name, attrs)
331
332
333	def append(self, tag_name, p):
334		gl_XML.glFunction.append(self, tag_name, p)
335
336		if p.is_variable_length_array():
337			p.order = 2;
338		elif not self.glx_doubles_in_order and p.p_type.size == 8:
339			p.order = 0;
340
341		if p.p_count_parameters != None:
342			self.count_parameters = p.p_count_parameters
343
344		if p.is_counter:
345			self.counter = p.name
346
347		if p.is_output:
348			self.output = p
349
350		return
351
352	def variable_length_parameter(self):
353		for param in self.fn_parameters:
354			if param.is_variable_length_array():
355				return param
356
357		return None
358
359
360	def command_payload_length(self):
361		size = 0
362		size_string = ""
363		for p in self:
364			if p.is_output: continue
365			temp = p.size_string()
366			try:
367				s = int(temp)
368				size += s
369			except Exception,e:
370				size_string = size_string + " + __GLX_PAD(%s)" % (temp)
371
372		return [size, size_string]
373
374	def command_length(self):
375		[size, size_string] = self.command_payload_length()
376
377		if self.glx_rop != 0:
378			size += 4
379
380		size = ((size + 3) & ~3)
381		return "%u%s" % (size, size_string)
382
383
384	def opcode_real_value(self):
385		if self.glx_vendorpriv != 0:
386			if self.needs_reply():
387				return 17
388			else:
389				return 16
390		else:
391			return self.opcode_value()
392
393	def opcode_value(self):
394		if self.glx_rop != 0:
395			return self.glx_rop
396		elif self.glx_sop != 0:
397			return self.glx_sop
398		elif self.glx_vendorpriv != 0:
399			return self.glx_vendorpriv
400		else:
401			return -1
402
403	def opcode_rop_basename(self):
404		if self.vectorequiv == None:
405			return self.name
406		else:
407			return self.vectorequiv
408
409	def opcode_name(self):
410		if self.glx_rop != 0:
411			return "X_GLrop_%s" % (self.opcode_rop_basename())
412		elif self.glx_sop != 0:
413			return "X_GLsop_%s" % (self.name)
414		elif self.glx_vendorpriv != 0:
415			return "X_GLvop_%s" % (self.name)
416		else:
417			return "ERROR"
418
419	def opcode_real_name(self):
420		if self.glx_vendorpriv != 0:
421			if self.needs_reply():
422				return "X_GLXVendorPrivateWithReply"
423			else:
424				return "X_GLXVendorPrivate"
425		else:
426			return self.opcode_name()
427
428
429	def return_string(self):
430		if self.fn_return_type != 'void':
431			return "return retval;"
432		else:
433			return "return;"
434
435
436	def needs_reply(self):
437		return self.fn_return_type != 'void' or self.output != None
438
439
440class GlxProto(gl_XML.FilterGLAPISpecBase):
441	name = "glX_proto_send.py (from Mesa)"
442
443	def __init__(self):
444		gl_XML.FilterGLAPISpecBase.__init__(self)
445		self.factory = glXItemFactory()
446		self.glx_enum_functions = {}
447
448
449	def endElement(self, name):
450		if name == 'OpenGLAPI':
451			# Once all the parsing is done, we have to go back and
452			# fix-up some cross references between different
453			# functions.
454
455			for k in self.functions:
456				f = self.functions[k]
457				if f.vectorequiv != None:
458					equiv = self.find_function(f.vectorequiv)
459					if equiv != None:
460						f.glx_doubles_in_order = equiv.glx_doubles_in_order
461						f.glx_rop = equiv.glx_rop
462					else:
463						raise RuntimeError("Could not find the vector equiv. function %s for %s!" % (f.name, f.vectorequiv))
464		else:
465			gl_XML.FilterGLAPISpecBase.endElement(self, name)
466		return
467
468
469class PrintGlxProtoStubs(GlxProto):
470	def __init__(self):
471		GlxProto.__init__(self)
472		self.last_category = ""
473		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
474		self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
475		return
476
477	def printRealHeader(self):
478		print ''
479		print '#include <GL/gl.h>'
480		print '#include "indirect.h"'
481		print '#include "glxclient.h"'
482		print '#include "size.h"'
483		print '#include <GL/glxproto.h>'
484		print ''
485		print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
486		print ''
487		printFastcall()
488		printNoinline()
489		print ''
490		print '/* If the size and opcode values are known at compile-time, this will, on'
491		print ' * x86 at least, emit them with a single instruction.'
492		print ' */'
493		print '#define emit_header(dest, op, size)            \\'
494		print '    do { union { short s[2]; int i; } temp;    \\'
495		print '         temp.s[0] = (size); temp.s[1] = (op); \\'
496		print '         *((int *)(dest)) = temp.i; } while(0)'
497		print ''
498		print """static NOINLINE CARD32
499read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
500{
501    xGLXSingleReply reply;
502
503    (void) _XReply(dpy, (xReply *) & reply, 0, False);
504    if (size != 0) {
505	if ((reply.size >= 1) || reply_is_always_array) {
506	    const GLint bytes = (reply_is_always_array)
507	      ? (4 * reply.length) : (reply.size * size);
508	    const GLint extra = 4 - (bytes & 3);
509
510	    _XRead(dpy, dest, bytes);
511	    if ( extra != 0 ) {
512		_XEatData(dpy, extra);
513	    }
514	}
515	else {
516	    (void) memcpy( dest, &(reply.pad3), size);
517	}
518    }
519
520    return reply.retval;
521}
522
523#define X_GLXSingle 0
524
525static NOINLINE GLubyte *
526setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen )
527{
528    xGLXSingleReq * req;
529    Display * const dpy = gc->currentDpy;
530
531    (void) __glXFlushRenderBuffer(gc, gc->pc);
532    LockDisplay(dpy);
533    GetReqExtra(GLXSingle, cmdlen, req);
534    req->reqType = gc->majorOpcode;
535    req->contextTag = gc->currentContextTag;
536    req->glxCode = sop;
537    return (GLubyte *)(req) + sz_xGLXSingleReq;
538}
539
540static NOINLINE GLubyte *
541setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
542{
543    xGLXVendorPrivateReq * req;
544    Display * const dpy = gc->currentDpy;
545
546    (void) __glXFlushRenderBuffer(gc, gc->pc);
547    LockDisplay(dpy);
548    GetReqExtra(GLXVendorPrivate, cmdlen, req);
549    req->reqType = gc->majorOpcode;
550    req->glxCode = code;
551    req->vendorCode = vop;
552    req->contextTag = gc->currentContextTag;
553    return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
554}
555"""
556
557		for size in self.generic_sizes:
558			self.print_generic_function(size)
559		return
560
561	def printFunction(self, f):
562		if f.fn_offset < 0 or f.handcode or f.ignore: return
563
564		if f.glx_rop != 0 or f.vectorequiv != None:
565			self.printRenderFunction(f)
566		elif f.glx_sop != 0 or f.glx_vendorpriv != 0:
567			self.printSingleFunction(f)
568		else:
569			print "/* Missing GLX protocol for %s. */" % (f.name)
570
571	def print_generic_function(self, n):
572		print """static FASTCALL NOINLINE void
573generic_%u_byte( GLint rop, const void * ptr )
574{
575    __GLXcontext * const gc = __glXGetCurrentContext();
576    const GLuint cmdlen = %u;
577
578    emit_header(gc->pc, rop, cmdlen);
579    (void) memcpy((void *)(gc->pc + 4), ptr, %u);
580    gc->pc += cmdlen;
581    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
582}
583""" % (n, n + 4, n)
584
585
586	def common_emit_one_arg(self, p, offset, pc, indent, adjust):
587		if p.is_output: return
588
589		t = p.p_type
590		if p.is_array():
591			src_ptr = p.name
592		else:
593			src_ptr = "&" + p.name
594
595		print '%s    (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
596			% (indent, pc, offset + adjust, src_ptr, p.size_string() )
597
598	def common_emit_args(self, f, pc, indent, adjust, skip_vla):
599		# First emit all of the fixed-length 8-byte (i.e., GLdouble)
600		# parameters.
601
602		offset = 0
603
604		if skip_vla:
605			r = [0, 1]
606		else:
607			r = [0, 1, 2]
608
609		for order in r:
610			for p in f:
611				if p.is_output or p.order != order: continue
612
613				self.common_emit_one_arg(p, offset, pc, indent, adjust)
614				offset += p.size()
615
616
617		return offset
618
619
620	def common_func_print_just_header(self, f):
621		print '#define %s %d' % (f.opcode_name(), f.opcode_value())
622
623		print '%s' % (f.fn_return_type)
624		print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string())
625		print '{'
626
627
628	def common_func_print_header(self, f):
629		self.common_func_print_just_header(f)
630
631		print '    __GLXcontext * const gc = __glXGetCurrentContext();'
632		print '    Display * const dpy = gc->currentDpy;'
633
634		if f.fn_return_type != 'void':
635			print '    %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type)
636
637		if f.count_parameters != None:
638			print '    const GLuint compsize = __gl%s_size(%s);' % (f.name, f.count_parameters)
639
640		print '    const GLuint cmdlen = %s;' % (f.command_length())
641
642		if f.counter != None:
643			print '    if (%s < 0) %s' % (f.counter, f.return_string())
644
645		if f.can_be_large:
646			print '    if (dpy == NULL) return;'
647			print '    if ( ((gc->pc + cmdlen) > gc->bufEnd)'
648			print '         || (cmdlen > gc->maxSmallRenderCommandSize)) {'
649			print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
650			print '    }'
651		else:
652			print '    (void) dpy;'
653
654		return
655
656
657	def printSingleFunction(self, f):
658		self.common_func_print_header(f)
659
660		print '    if (dpy != NULL) {'
661
662		if f.fn_parameters != []:
663			pc_decl = "GLubyte const * pc ="
664		else:
665			pc_decl = "(void)"
666
667		if f.glx_vendorpriv != 0:
668			print '        %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
669		else:
670			print '        %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
671
672		self.common_emit_args(f, "pc", "    ", 0, 0)
673
674		if f.needs_reply():
675			if f.output != None:
676				output_size = f.output.p_type.size
677				output_str = f.output.name
678			else:
679				output_size = 0
680				output_str = "NULL"
681
682			if f.fn_return_type != 'void':
683				return_str = " retval = (%s)" % (f.fn_return_type)
684			else:
685				return_str = " (void)"
686
687			if f.reply_always_array:
688				aa = "GL_TRUE"
689			else:
690				aa = "GL_FALSE"
691
692			print "       %s read_reply(gc->currentDpy, %s, %s, %s);" % (return_str, output_size, output_str, aa)
693
694		print '        UnlockDisplay(gc->currentDpy); SyncHandle();'
695		print '    }'
696		print '    %s' % f.return_string()
697		print '}'
698		print ''
699		return
700
701
702	def printRenderFunction(self, f):
703		# There is a class of GL functions that take a single pointer
704		# as a parameter.  This pointer points to a fixed-size chunk
705		# of data, and the protocol for this functions is very
706		# regular.  Since they are so regular and there are so many
707		# of them, special case them with generic functions.  On
708		# x86, this save about 26KB in the libGL.so binary.
709
710		if f.variable_length_parameter() == None and len(f.fn_parameters) == 1:
711			p = f.fn_parameters[0]
712			if p.is_pointer:
713				[cmdlen, size_string] = f.command_payload_length()
714				if cmdlen in self.generic_sizes:
715					self.common_func_print_just_header(f)
716					print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
717					print '}'
718					print ''
719					return
720
721		self.common_func_print_header(f)
722
723		if f.can_be_large:
724			print '    if (cmdlen <= gc->maxSmallRenderCommandSize) {'
725			indent = "    "
726		else:
727			indent = ""
728
729		print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
730
731		self.common_emit_args(f, "gc->pc", indent, 4, 0)
732		print '%s    gc->pc += cmdlen;' % (indent)
733		print '%s    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
734
735		if f.can_be_large:
736			print '    }'
737			print '    else {'
738			print '        const GLint op = %s;' % (f.opcode_real_name())
739			print '        const GLuint cmdlenLarge = cmdlen + 4;'
740			print '        (void) memcpy((void *)(gc->pc + 0), (void *)(&op), 4);'
741			print '        (void) memcpy((void *)(gc->pc + 4), (void *)(&cmdlenLarge), 4);'
742			offset = self.common_emit_args(f, "gc->pc", indent, 8, 1)
743
744			p = f.variable_length_parameter()
745			print '        __glXSendLargeCommand(gc, gc->pc, %u, %s, %s);' % (offset + 8, p.name, p.size_string())
746			print '    }'
747
748		print '}'
749		print ''
750		return
751
752
753class PrintGlxProtoInit_c(GlxProto):
754	def __init__(self):
755		GlxProto.__init__(self)
756		self.last_category = ""
757		self.license = license.bsd_license_template % ( \
758"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
759(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
760
761
762	def printRealHeader(self):
763		print """/**
764 * \\file indirect_init.c
765 * Initialize indirect rendering dispatch table.
766 *
767 * \\author Kevin E. Martin <kevin@precisioninsight.com>
768 * \\author Brian Paul <brian@precisioninsight.com>
769 * \\author Ian Romanick <idr@us.ibm.com>
770 */
771
772#include "indirect_init.h"
773#include "indirect.h"
774#include "glapi.h"
775
776
777/**
778 * No-op function used to initialize functions that have no GLX protocol
779 * support.
780 */
781static int NoOp(void)
782{
783    return 0;
784}
785
786/**
787 * Create and initialize a new GL dispatch table.  The table is initialized
788 * with GLX indirect rendering protocol functions.
789 */
790__GLapi * __glXNewIndirectAPI( void )
791{
792    __GLapi *glAPI;
793    GLuint entries;
794
795    entries = _glapi_get_dispatch_table_size();
796    glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
797
798    /* first, set all entries to point to no-op functions */
799    {
800       int i;
801       void **dispatch = (void **) glAPI;
802       for (i = 0; i < entries; i++) {
803          dispatch[i] = (void *) NoOp;
804       }
805    }
806
807    /* now, initialize the entries we understand */"""
808
809	def printRealFooter(self):
810		print """
811    return glAPI;
812}
813"""
814
815	def printFunction(self, f):
816		if f.fn_offset < 0 or f.ignore: return
817
818		if f.category != self.last_category:
819			self.last_category = f.category
820			print ''
821			print '    /* %s */' % (self.last_category)
822			print ''
823
824		print '    glAPI->%s = __indirect_gl%s;' % (f.name, f.name)
825
826
827class PrintGlxProtoInit_h(GlxProto):
828	def __init__(self):
829		GlxProto.__init__(self)
830		self.last_category = ""
831		self.license = license.bsd_license_template % ( \
832"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
833(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
834
835
836	def printRealHeader(self):
837		print """
838/**
839 * \\file
840 * Prototypes for indirect rendering functions.
841 *
842 * \\author Kevin E. Martin <kevin@precisioninsight.com>
843 * \\author Ian Romanick <idr@us.ibm.com>
844 */
845
846#if !defined( _INDIRECT_H_ )
847#  define _INDIRECT_H_
848
849"""
850		printVisibility( "HIDDEN", "hidden" )
851
852
853	def printRealFooter(self):
854		print "#  undef HIDDEN"
855		print "#endif /* !defined( _INDIRECT_H_ ) */"
856
857	def printFunction(self, f):
858		if f.fn_offset < 0 or f.ignore: return
859		print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string())
860
861
862class PrintGlxSizeStubs(GlxProto):
863	def __init__(self):
864		GlxProto.__init__(self)
865		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
866		self.aliases = []
867		self.glx_enum_sigs = {}
868
869	def printRealHeader(self):
870		print ''
871		print '#include <GL/gl.h>'
872		print '#include "indirect_size.h"'
873
874		print ''
875		printPure()
876		print ''
877		printFastcall()
878		print ''
879		printVisibility( "INTERNAL", "internal" )
880		print ''
881		print ''
882		print '#ifdef HAVE_ALIAS'
883		print '#  define ALIAS2(from,to) \\'
884		print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
885		print '        __attribute__ ((alias( # to )));'
886		print '#  define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
887		print '#else'
888		print '#  define ALIAS(from,to) \\'
889		print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
890		print '    { return __gl ## to ## _size( e ); }'
891		print '#endif'
892		print ''
893		print ''
894
895	def printRealFooter(self):
896		for a in self.aliases:
897			print a
898
899	def printFunction(self, f):
900		if self.glx_enum_functions.has_key(f.name):
901			ef = self.glx_enum_functions[f.name]
902
903			sig = ef.signature();
904			if self.glx_enum_sigs.has_key(sig):
905				n = self.glx_enum_sigs[sig];
906				a = 'ALIAS( %s, %s )' % (f.name, n)
907				self.aliases.append(a)
908			else:
909				ef.Print( f.name )
910				self.glx_enum_sigs[sig] = f.name;
911
912
913
914class PrintGlxSizeStubs_h(GlxProto):
915	def __init__(self):
916		GlxProto.__init__(self)
917		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
918		self.aliases = []
919		self.glx_enum_sigs = {}
920
921	def printRealHeader(self):
922		print """
923/**
924 * \\file
925 * Prototypes for functions used to determine the number of data elements in
926 * various GLX protocol messages.
927 *
928 * \\author Ian Romanick <idr@us.ibm.com>
929 */
930
931#if !defined( _GLXSIZE_H_ )
932#  define _GLXSIZE_H_
933
934"""
935		printPure();
936		print ''
937		printFastcall();
938		print ''
939		printVisibility( "INTERNAL", "internal" );
940		print ''
941
942	def printRealFooter(self):
943		print ''
944		print "#  undef INTERNAL"
945		print "#  undef PURE"
946		print "#  undef FASTCALL"
947		print "#endif /* !defined( _GLXSIZE_H_ ) */"
948
949
950	def printFunction(self, f):
951		if self.glx_enum_functions.has_key(f.name):
952			ef = self.glx_enum_functions[f.name]
953			print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name)
954
955
956def show_usage():
957	print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0]
958	sys.exit(1)
959
960
961if __name__ == '__main__':
962	file_name = "gl_API.xml"
963
964	try:
965		(args, trail) = getopt.getopt(sys.argv[1:], "f:m:")
966	except Exception,e:
967		show_usage()
968
969	mode = "proto"
970	for (arg,val) in args:
971		if arg == "-f":
972			file_name = val
973		elif arg == "-m":
974			mode = val
975
976	if mode == "proto":
977		dh = PrintGlxProtoStubs()
978	elif mode == "init_c":
979		dh = PrintGlxProtoInit_c()
980	elif mode == "init_h":
981		dh = PrintGlxProtoInit_h()
982	elif mode == "size_c":
983		dh = PrintGlxSizeStubs()
984	elif mode == "size_h":
985		dh = PrintGlxSizeStubs_h()
986	else:
987		show_usage()
988
989	parser = make_parser()
990	parser.setFeature(feature_namespaces, 0)
991	parser.setContentHandler(dh)
992
993	f = open(file_name)
994
995	dh.printHeader()
996	parser.parse(f)
997	dh.printFooter()
998