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