glX_proto_send.py revision 5f1f229f8da255ca9b390da1757ad781978cf619
1#!/usr/bin/python2
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
28from xml.sax import saxutils
29from xml.sax import make_parser
30from xml.sax.handler import feature_namespaces
31
32import gl_XML
33import glX_XML
34import license
35import sys, getopt, copy
36
37def hash_pixel_function(func):
38	"""Generate a 'unique' key for a pixel function.  The key is based on
39	the parameters written in the command packet.  This includes any
40	padding that might be added for the original function and the 'NULL
41	image' flag."""
42
43	[dim, junk, junk, junk, junk] = func.dimensions()
44
45	d = (dim + 1) & ~1
46	h = "%uD%uD_" % (d - 1, d)
47
48	for p in func.parameterIterator(1, 1):
49		h = "%s%u" % (h, p.size())
50
51		if func.pad_after(p):
52			h += "4"
53
54	if func.image.img_null_flag:
55		h += "_NF"
56
57	n = func.name.replace("%uD" % (dim), "")
58	n = "__glx_%s_%uD%uD" % (n, d - 1, d)
59	return [h, n]
60
61
62class glXPixelFunctionUtility(glX_XML.glXFunction):
63	"""Dummy class used to generate pixel "utility" functions that are
64	shared by multiple dimension image functions.  For example, these
65	objects are used to generate shared functions used to send GLX
66	protocol for TexImage1D and TexImage2D, TexSubImage1D and
67	TexSubImage2D, etc."""
68
69	def __init__(self, func, name):
70		# The parameters to the utility function are the same as the
71		# parameters to the real function except for the added "pad"
72		# parameters.
73
74		self.name = name
75		self.image = copy.copy(func.image)
76		self.fn_parameters = []
77		for p in gl_XML.glFunction.parameterIterator(func):
78			self.fn_parameters.append(p)
79
80			pad_name = func.pad_after(p)
81			if pad_name:
82				pad = copy.copy(p)
83				pad.name = pad_name
84				self.fn_parameters.append(pad)
85
86
87		if self.image.height == None:
88			self.image.height = "height"
89
90		if self.image.img_yoff == None:
91			self.image.img_yoff = "yoffset"
92
93		if func.image.depth:
94			if self.image.extent == None:
95				self.image.extent = "extent"
96
97			if self.image.img_woff == None:
98				self.image.img_woff = "woffset"
99
100
101		self.set_return_type( func.fn_return_type )
102		self.glx_rop = ~0
103		self.can_be_large = func.can_be_large
104		self.count_parameters = func.count_parameters
105		self.counter = func.counter
106		return
107
108
109class PrintGlxProtoStubs(glX_XML.GlxProto):
110	def __init__(self):
111		glX_XML.GlxProto.__init__(self)
112		self.last_category = ""
113		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
114		self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
115		self.pixel_stubs = {}
116		return
117
118	def printRealHeader(self):
119		print ''
120		print '#include <GL/gl.h>'
121		print '#include "indirect.h"'
122		print '#include "glxclient.h"'
123		print '#include "indirect_size.h"'
124		print '#include <GL/glxproto.h>'
125		print ''
126		print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
127		print ''
128		glX_XML.printFastcall()
129		glX_XML.printNoinline()
130		print ''
131		print '#if !defined __GNUC__ || __GNUC__ < 3'
132		print '#  define __builtin_expect(x, y) x'
133		print '#endif'
134		print ''
135		print '/* If the size and opcode values are known at compile-time, this will, on'
136		print ' * x86 at least, emit them with a single instruction.'
137		print ' */'
138		print '#define emit_header(dest, op, size)            \\'
139		print '    do { union { short s[2]; int i; } temp;    \\'
140		print '         temp.s[0] = (size); temp.s[1] = (op); \\'
141		print '         *((int *)(dest)) = temp.i; } while(0)'
142		print ''
143		print """static NOINLINE CARD32
144read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
145{
146    xGLXSingleReply reply;
147
148    (void) _XReply(dpy, (xReply *) & reply, 0, False);
149    if (size != 0) {
150	if ((reply.length > 0) || reply_is_always_array) {
151	    const GLint bytes = (reply_is_always_array)
152	      ? (4 * reply.length) : (reply.size * size);
153	    const GLint extra = 4 - (bytes & 3);
154
155	    _XRead(dpy, dest, bytes);
156	    if ( extra < 4 ) {
157		_XEatData(dpy, extra);
158	    }
159	}
160	else {
161	    (void) memcpy( dest, &(reply.pad3), size);
162	}
163    }
164
165    return reply.retval;
166}
167
168#define X_GLXSingle 0
169
170static NOINLINE FASTCALL GLubyte *
171setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen )
172{
173    xGLXSingleReq * req;
174    Display * const dpy = gc->currentDpy;
175
176    (void) __glXFlushRenderBuffer(gc, gc->pc);
177    LockDisplay(dpy);
178    GetReqExtra(GLXSingle, cmdlen, req);
179    req->reqType = gc->majorOpcode;
180    req->contextTag = gc->currentContextTag;
181    req->glxCode = sop;
182    return (GLubyte *)(req) + sz_xGLXSingleReq;
183}
184
185static NOINLINE FASTCALL GLubyte *
186setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
187{
188    xGLXVendorPrivateReq * req;
189    Display * const dpy = gc->currentDpy;
190
191    (void) __glXFlushRenderBuffer(gc, gc->pc);
192    LockDisplay(dpy);
193    GetReqExtra(GLXVendorPrivate, cmdlen, req);
194    req->reqType = gc->majorOpcode;
195    req->glxCode = code;
196    req->vendorCode = vop;
197    req->contextTag = gc->currentContextTag;
198    return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
199}
200
201const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
202
203#define zero                        (__glXDefaultPixelStore+0)
204#define one                         (__glXDefaultPixelStore+8)
205#define default_pixel_store_1D      (__glXDefaultPixelStore+4)
206#define default_pixel_store_1D_size 20
207#define default_pixel_store_2D      (__glXDefaultPixelStore+4)
208#define default_pixel_store_2D_size 20
209#define default_pixel_store_3D      (__glXDefaultPixelStore+0)
210#define default_pixel_store_3D_size 36
211#define default_pixel_store_4D      (__glXDefaultPixelStore+0)
212#define default_pixel_store_4D_size 36
213"""
214
215		for size in self.generic_sizes:
216			self.print_generic_function(size)
217		return
218
219	def printFunction(self, f):
220		if f.fn_offset < 0 or f.handcode or f.ignore: return
221
222		if f.glx_rop != 0 or f.vectorequiv != None:
223			if f.image:
224				self.printPixelFunction(f)
225			else:
226				self.printRenderFunction(f)
227		elif f.glx_sop != 0 or f.glx_vendorpriv != 0:
228			self.printSingleFunction(f)
229		else:
230			print "/* Missing GLX protocol for %s. */" % (f.name)
231
232	def print_generic_function(self, n):
233		size = (n + 3) & ~3
234		print """static FASTCALL NOINLINE void
235generic_%u_byte( GLint rop, const void * ptr )
236{
237    __GLXcontext * const gc = __glXGetCurrentContext();
238    const GLuint cmdlen = %u;
239
240    emit_header(gc->pc, rop, cmdlen);
241    (void) memcpy((void *)(gc->pc + 4), ptr, %u);
242    gc->pc += cmdlen;
243    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
244}
245""" % (n, size + 4, size)
246
247
248	def common_emit_one_arg(self, p, offset, pc, indent, adjust):
249		t = p.p_type
250		if p.is_array():
251			src_ptr = p.name
252		else:
253			src_ptr = "&" + p.name
254
255		print '%s    (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
256			% (indent, pc, offset + adjust, src_ptr, p.size_string() )
257
258	def common_emit_args(self, f, pc, indent, adjust, skip_vla):
259		offset = 0
260
261		if skip_vla:
262			r = 1
263		else:
264			r = 2
265
266		for p in f.parameterIterator(1, r):
267			self.common_emit_one_arg(p, offset, pc, indent, adjust)
268			offset += p.size()
269
270		return offset
271
272
273	def pixel_emit_args(self, f, pc, indent, adjust, dim, large):
274		"""Emit the arguments for a pixel function.  This differs from
275		common_emit_args in that pixel functions may require padding
276		be inserted (i.e., for the missing width field for
277		TexImage1D), and they may also require a 'NULL image' flag
278		be inserted before the image data."""
279
280		offset = 0
281		for p in f.parameterIterator(1, 1):
282			self.common_emit_one_arg(p, offset, pc, indent, adjust)
283			offset += p.size()
284
285			if f.pad_after(p):
286				print '%s    (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust)
287				offset += 4
288
289		if f.image.img_null_flag:
290			if large:
291				print '%s    (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust)
292			else:
293				print '%s    (void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (indent, pc, offset + adjust, f.image.name)
294
295			offset += 4
296
297		return offset
298
299
300	def large_emit_begin(self, indent, f, op_name = None):
301		if not op_name:
302			op_name = f.opcode_real_name()
303
304		print '%s    const GLint op = %s;' % (indent, op_name)
305		print '%s    const GLuint cmdlenLarge = cmdlen + 4;' % (indent)
306		print '%s    GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
307		print '%s    (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent)
308		print '%s    (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent)
309		return
310
311
312	def common_func_print_just_header(self, f):
313		print '#define %s %d' % (f.opcode_name(), f.opcode_value())
314
315		print '%s' % (f.fn_return_type)
316		print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string())
317		print '{'
318
319
320	def common_func_print_just_start(self, f):
321		print '    __GLXcontext * const gc = __glXGetCurrentContext();'
322
323		# The only reason that single and vendor private commands need
324		# a variable called 'dpy' is becuase they use the SyncHandle
325		# macro.  For whatever brain-dead reason, that macro is hard-
326		# coded to use a variable called 'dpy' instead of taking a
327		# parameter.
328
329		if not f.glx_rop:
330			print '    Display * const dpy = gc->currentDpy;'
331			skip_condition = "dpy != NULL"
332		elif f.can_be_large:
333			skip_condition = "gc->currentDpy != NULL"
334		else:
335			skip_condition = None
336
337
338		if f.fn_return_type != 'void':
339			print '    %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type)
340
341		if f.count_parameters != None:
342			print '    const GLuint compsize = __gl%s_size(%s);' % (f.name, f.count_parameters)
343		elif f.image:
344			[dim, w, h, d, junk] = f.dimensions()
345
346			compsize = '__glImageSize(%s, %s, %s, %s, %s, %s)' % (w, h, d, f.image.img_format, f.image.img_type, f.image.img_target)
347			if not f.image.img_send_null:
348				compsize = '(%s != NULL) ? %s : 0' % (f.image.name, compsize)
349
350			print '    const GLuint compsize = %s;' % (compsize)
351
352
353		print '    const GLuint cmdlen = %s;' % (f.command_length())
354
355		if f.counter:
356			if skip_condition:
357				skip_condition = "(%s >= 0) && (%s)" % (f.counter, skip_condition)
358			else:
359				skip_condition = "%s >= 0" % (f.counter)
360
361
362		if skip_condition:
363			print '    if (__builtin_expect(%s, 1)) {' % (skip_condition)
364			return 1
365		else:
366			return 0
367
368
369	def common_func_print_header(self, f):
370		self.common_func_print_just_header(f)
371		return self.common_func_print_just_start(f)
372
373
374
375	def printSingleFunction(self, f):
376		self.common_func_print_header(f)
377
378		if f.fn_parameters != []:
379			pc_decl = "GLubyte const * pc ="
380		else:
381			pc_decl = "(void)"
382
383		if f.glx_vendorpriv != 0:
384			print '        %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
385		else:
386			print '        %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
387
388		self.common_emit_args(f, "pc", "    ", 0, 0)
389
390		if f.needs_reply():
391			if f.output != None:
392				output_size = f.output.p_type.size
393				output_str = f.output.name
394			else:
395				output_size = 0
396				output_str = "NULL"
397
398			if f.fn_return_type != 'void':
399				return_str = " retval = (%s)" % (f.fn_return_type)
400			else:
401				return_str = " (void)"
402
403			if f.reply_always_array:
404				aa = "GL_TRUE"
405			else:
406				aa = "GL_FALSE"
407
408			print "       %s read_reply(dpy, %s, %s, %s);" % (return_str, output_size, output_str, aa)
409
410		print '        UnlockDisplay(dpy); SyncHandle();'
411		print '    }'
412		print '    %s' % f.return_string()
413		print '}'
414		print ''
415		return
416
417
418	def printPixelFunction(self, f):
419		"""This function could use some major refactoring. :("""
420
421		# There is a code-space optimization that we can do here.
422		# Functions that are marked img_pad_dimensions have a version
423		# with an odd number of dimensions and an even number of
424		# dimensions.  TexSubImage1D and TexSubImage2D are examples.
425		# We can emit a single function that does both, and have the
426		# real functions call the utility function with the correct
427		# parameters.
428		#
429		# The only quirk to this is that utility funcitons will be
430		# generated for 3D and 4D functions, but 4D (e.g.,
431		# GL_SGIS_texture4D) isn't typically supported.  This is
432		# probably not an issue.  However, it would be possible to
433		# look at the total set of functions and determine if there
434		# is another function that would actually use the utility
435		# function.  If not, then fallback to the normal way of
436		# generating code.
437
438		if f.image.img_pad_dimensions:
439			# Determine the hash key and the name for the utility
440			# function that is used to implement the real
441			# function.
442
443			[h, n] = hash_pixel_function(f)
444
445
446			# If the utility function is not yet known, generate
447			# it.
448
449			if not self.pixel_stubs.has_key(h):
450				self.pixel_stubs[h] = n
451				pixel_func = glXPixelFunctionUtility(f, n)
452
453				print 'static void'
454				print '%s( unsigned opcode, unsigned dim, %s )' % (n, pixel_func.get_parameter_string())
455				print '{'
456
457				if self.common_func_print_just_start(pixel_func):
458					indent = "    "
459					trailer = "    }"
460				else:
461					indent = ""
462					trailer = None
463
464
465				if pixel_func.can_be_large:
466					print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
467					print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
468					print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
469					print '%s        }' % (indent)
470					indent += "    "
471
472				[dim, width, height, depth, extent] = pixel_func.dimensions()
473
474				if dim < 3:
475					adjust = 20 + 4
476				else:
477					adjust = 36 + 4
478
479
480				print '%s    emit_header(gc->pc, opcode, cmdlen);' % (indent)
481
482				offset = self.pixel_emit_args(pixel_func, "gc->pc", indent, adjust, dim, 0)
483
484				[s, junk] = pixel_func.command_payload_length()
485
486				pixHeaderPtr = "gc->pc + 4"
487				pcPtr = "gc->pc + %u" % (s + 4)
488
489				if pixel_func.image.img_send_null:
490					condition = '(compsize > 0) && (%s != NULL)' % (pixel_func.image.name)
491				else:
492					condition = 'compsize > 0'
493
494				print '%s    if (%s) {' % (indent, condition)
495				print '%s        (*gc->fillImage)(gc, dim, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, width, height, depth, pixel_func.image.img_format, pixel_func.image.img_type, pixel_func.image.name, pcPtr, pixHeaderPtr)
496				print '%s    }' % (indent)
497				print '%s    else {' % (indent)
498				print '%s        (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
499				print '%s    }' % (indent)
500
501				print '%s    gc->pc += cmdlen;' % (indent)
502				print '%s    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
503
504				if f.can_be_large:
505					adjust += 4
506
507					print '%s}' % (indent)
508					print '%selse {' % (indent)
509
510					self.large_emit_begin(indent, pixel_func, "opcode")
511					offset = self.pixel_emit_args(pixel_func, "pc", indent, adjust, dim, 1)
512
513					pixHeaderPtr = "pc + 8"
514					pcPtr = "pc + %u" % (s + 8)
515
516					print '%s    __glXSendLargeImage(gc, compsize, dim, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr)
517
518					print '%s}' % (indent)
519
520				if trailer: print trailer
521				print '}'
522				print ''
523
524
525
526			# Generate the real function as a call to the
527			# utility function.
528
529			self.common_func_print_just_header(f)
530
531			[dim, junk, junk, junk, junk] = f.dimensions()
532
533			p_string = ""
534			for p in gl_XML.glFunction.parameterIterator(f):
535				p_string += ", " + p.name
536
537				if f.pad_after(p):
538					p_string += ", 1"
539
540			print '    %s(%s, %u%s );' % (n, f.opcode_name(), dim, p_string)
541			print '}'
542			print ''
543			return
544
545
546		if self.common_func_print_header(f):
547			indent = "    "
548			trailer = "    }"
549		else:
550			indent = ""
551			trailer = None
552
553
554		if f.can_be_large:
555			print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
556			print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
557			print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
558			print '%s        }' % (indent)
559			indent += "    "
560
561		[dim, width, height, depth, extent] = f.dimensions()
562
563		if dim < 3:
564			adjust = 20 + 4
565		else:
566			adjust = 36 + 4
567
568
569		print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
570
571		offset = self.pixel_emit_args(f, "gc->pc", indent, adjust, dim, 0)
572
573		[s, junk] = f.command_payload_length()
574
575		pixHeaderPtr = "gc->pc + 4"
576		pcPtr = "gc->pc + %u" % (s + 4)
577
578		if f.image.img_send_null:
579			condition = '(compsize > 0) && (%s != NULL)' % (f.image.name)
580		else:
581			condition = 'compsize > 0'
582
583		print '%s    if (%s) {' % (indent, condition)
584		print '%s        (*gc->fillImage)(gc, %u, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr)
585		print '%s    }' % (indent)
586		print '%s    else {' % (indent)
587		print '%s        (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
588		print '%s    }' % (indent)
589
590		print '%s    gc->pc += cmdlen;' % (indent)
591		print '%s    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
592
593		if f.can_be_large:
594			adjust += 4
595
596			print '%s}' % (indent)
597			print '%selse {' % (indent)
598
599			self.large_emit_begin(indent, f)
600			offset = self.pixel_emit_args(f, "pc", indent, adjust, dim, 1)
601
602			pixHeaderPtr = "pc + 8"
603			pcPtr = "pc + %u" % (s + 8)
604
605			print '%s    __glXSendLargeImage(gc, compsize, %u, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr)
606
607			print '%s}' % (indent)
608
609		if trailer: print trailer
610		print '}'
611		print ''
612		return
613
614
615	def printRenderFunction(self, f):
616		# There is a class of GL functions that take a single pointer
617		# as a parameter.  This pointer points to a fixed-size chunk
618		# of data, and the protocol for this functions is very
619		# regular.  Since they are so regular and there are so many
620		# of them, special case them with generic functions.  On
621		# x86, this saves about 26KB in the libGL.so binary.
622
623		if f.variable_length_parameter() == None and len(f.fn_parameters) == 1:
624			p = f.fn_parameters[0]
625			if p.is_pointer:
626				[cmdlen, size_string] = f.command_payload_length()
627				if cmdlen in self.generic_sizes:
628					self.common_func_print_just_header(f)
629					print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
630					print '}'
631					print ''
632					return
633
634		if self.common_func_print_header(f):
635			indent = "    "
636			trailer = "    }"
637		else:
638			indent = ""
639			trailer = None
640
641		if f.can_be_large:
642			print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
643			print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
644			print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
645			print '%s        }' % (indent)
646			indent += "    "
647
648		print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
649
650		self.common_emit_args(f, "gc->pc", indent, 4, 0)
651		print '%s    gc->pc += cmdlen;' % (indent)
652		print '%s    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
653
654		if f.can_be_large:
655			print '%s}' % (indent)
656			print '%selse {' % (indent)
657
658			self.large_emit_begin(indent, f)
659			offset = self.common_emit_args(f, "pc", indent, 8, 1)
660
661			p = f.variable_length_parameter()
662			print '%s    __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, offset + 8, p.name, p.size_string())
663			print '%s}' % (indent)
664
665		if trailer: print trailer
666		print '}'
667		print ''
668		return
669
670
671class PrintGlxProtoInit_c(glX_XML.GlxProto):
672	def __init__(self):
673		glX_XML.GlxProto.__init__(self)
674		self.last_category = ""
675		self.license = license.bsd_license_template % ( \
676"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
677(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
678
679
680	def printRealHeader(self):
681		print """/**
682 * \\file indirect_init.c
683 * Initialize indirect rendering dispatch table.
684 *
685 * \\author Kevin E. Martin <kevin@precisioninsight.com>
686 * \\author Brian Paul <brian@precisioninsight.com>
687 * \\author Ian Romanick <idr@us.ibm.com>
688 */
689
690#include "indirect_init.h"
691#include "indirect.h"
692#include "glapi.h"
693
694
695/**
696 * No-op function used to initialize functions that have no GLX protocol
697 * support.
698 */
699static int NoOp(void)
700{
701    return 0;
702}
703
704/**
705 * Create and initialize a new GL dispatch table.  The table is initialized
706 * with GLX indirect rendering protocol functions.
707 */
708__GLapi * __glXNewIndirectAPI( void )
709{
710    __GLapi *glAPI;
711    GLuint entries;
712
713    entries = _glapi_get_dispatch_table_size();
714    glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
715
716    /* first, set all entries to point to no-op functions */
717    {
718       int i;
719       void **dispatch = (void **) glAPI;
720       for (i = 0; i < entries; i++) {
721          dispatch[i] = (void *) NoOp;
722       }
723    }
724
725    /* now, initialize the entries we understand */"""
726
727	def printRealFooter(self):
728		print """
729    return glAPI;
730}
731"""
732
733	def printFunction(self, f):
734		if f.fn_offset < 0 or f.ignore: return
735
736		if f.category != self.last_category:
737			self.last_category = f.category
738			print ''
739			print '    /* %s */' % (self.last_category)
740			print ''
741
742		print '    glAPI->%s = __indirect_gl%s;' % (f.name, f.name)
743
744
745class PrintGlxProtoInit_h(glX_XML.GlxProto):
746	def __init__(self):
747		glX_XML.GlxProto.__init__(self)
748		self.last_category = ""
749		self.license = license.bsd_license_template % ( \
750"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
751(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
752
753
754	def printRealHeader(self):
755		print """
756/**
757 * \\file
758 * Prototypes for indirect rendering functions.
759 *
760 * \\author Kevin E. Martin <kevin@precisioninsight.com>
761 * \\author Ian Romanick <idr@us.ibm.com>
762 */
763
764#if !defined( _INDIRECT_H_ )
765#  define _INDIRECT_H_
766
767"""
768		glX_XML.printVisibility( "HIDDEN", "hidden" )
769
770
771	def printRealFooter(self):
772		print "#  undef HIDDEN"
773		print "#endif /* !defined( _INDIRECT_H_ ) */"
774
775	def printFunction(self, f):
776		if f.fn_offset < 0 or f.ignore: return
777		print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string())
778
779
780class PrintGlxSizeStubs(glX_XML.GlxProto):
781	def __init__(self):
782		glX_XML.GlxProto.__init__(self)
783		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
784		self.aliases = []
785		self.glx_enum_sigs = {}
786
787	def printRealHeader(self):
788		print ''
789		print '#include <GL/gl.h>'
790		print '#include "indirect_size.h"'
791
792		print ''
793		glX_XML.printPure()
794		print ''
795		glX_XML.printFastcall()
796		print ''
797		glX_XML.printVisibility( "INTERNAL", "internal" )
798		print ''
799		print ''
800		print '#ifdef HAVE_ALIAS'
801		print '#  define ALIAS2(from,to) \\'
802		print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
803		print '        __attribute__ ((alias( # to )));'
804		print '#  define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
805		print '#else'
806		print '#  define ALIAS(from,to) \\'
807		print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
808		print '    { return __gl ## to ## _size( e ); }'
809		print '#endif'
810		print ''
811		print ''
812
813	def printRealFooter(self):
814		for a in self.aliases:
815			print a
816
817	def printFunction(self, f):
818		if self.glx_enum_functions.has_key(f.name):
819			ef = self.glx_enum_functions[f.name]
820
821			sig = ef.signature();
822			if self.glx_enum_sigs.has_key(sig):
823				n = self.glx_enum_sigs[sig];
824				a = 'ALIAS( %s, %s )' % (f.name, n)
825				self.aliases.append(a)
826			else:
827				ef.Print( f.name )
828				self.glx_enum_sigs[sig] = f.name;
829
830
831
832class PrintGlxSizeStubs_h(glX_XML.GlxProto):
833	def __init__(self):
834		glX_XML.GlxProto.__init__(self)
835		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
836		self.aliases = []
837		self.glx_enum_sigs = {}
838
839	def printRealHeader(self):
840		print """
841/**
842 * \\file
843 * Prototypes for functions used to determine the number of data elements in
844 * various GLX protocol messages.
845 *
846 * \\author Ian Romanick <idr@us.ibm.com>
847 */
848
849#if !defined( _GLXSIZE_H_ )
850#  define _GLXSIZE_H_
851
852"""
853		glX_XML.printPure();
854		print ''
855		glX_XML.printFastcall();
856		print ''
857		glX_XML.printVisibility( "INTERNAL", "internal" );
858		print ''
859
860	def printRealFooter(self):
861		print ''
862		print "#  undef INTERNAL"
863		print "#  undef PURE"
864		print "#  undef FASTCALL"
865		print "#endif /* !defined( _GLXSIZE_H_ ) */"
866
867
868	def printFunction(self, f):
869		if self.glx_enum_functions.has_key(f.name):
870			ef = self.glx_enum_functions[f.name]
871			print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name)
872
873
874def show_usage():
875	print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0]
876	sys.exit(1)
877
878
879if __name__ == '__main__':
880	file_name = "gl_API.xml"
881
882	try:
883		(args, trail) = getopt.getopt(sys.argv[1:], "f:m:")
884	except Exception,e:
885		show_usage()
886
887	mode = "proto"
888	for (arg,val) in args:
889		if arg == "-f":
890			file_name = val
891		elif arg == "-m":
892			mode = val
893
894	if mode == "proto":
895		dh = PrintGlxProtoStubs()
896	elif mode == "init_c":
897		dh = PrintGlxProtoInit_c()
898	elif mode == "init_h":
899		dh = PrintGlxProtoInit_h()
900	elif mode == "size_c":
901		dh = PrintGlxSizeStubs()
902	elif mode == "size_h":
903		dh = PrintGlxSizeStubs_h()
904	else:
905		show_usage()
906
907	parser = make_parser()
908	parser.setFeature(feature_namespaces, 0)
909	parser.setContentHandler(dh)
910
911	f = open(file_name)
912
913	dh.printHeader()
914	parser.parse(f)
915	dh.printFooter()
916