glX_proto_send.py revision d2f19a554a9089fddb5e978e3a732bbf71d77f93
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#    Jeremy Kolb <jkolb@brandeis.edu>
28
29import gl_XML, glX_XML, glX_proto_common, license
30import sys, getopt, copy, string
31
32def convertStringForXCB(str):
33    tmp = ""
34    special = [ "ARB" ]
35    i = 0
36    while i < len(str):
37        if str[i:i+3] in special:
38            tmp = '%s_%s' % (tmp, string.lower(str[i:i+3]))
39            i = i + 2;
40        elif str[i].isupper():
41            tmp = '%s_%s' % (tmp, string.lower(str[i]))
42        else:
43            tmp = '%s%s' % (tmp, str[i])
44        i += 1
45    return tmp
46
47def hash_pixel_function(func):
48	"""Generate a 'unique' key for a pixel function.  The key is based on
49	the parameters written in the command packet.  This includes any
50	padding that might be added for the original function and the 'NULL
51	image' flag."""
52
53
54	h = ""
55	hash_pre = ""
56	hash_suf = ""
57	for param in func.parameterIterateGlxSend():
58		if param.is_image():
59			[dim, junk, junk, junk, junk] = param.get_dimensions()
60
61			d = (dim + 1) & ~1
62			hash_pre = "%uD%uD_" % (d - 1, d)
63
64			if param.img_null_flag:
65				hash_suf = "_NF"
66
67		h += "%u" % (param.size())
68
69		if func.pad_after(param):
70			h += "4"
71
72
73	n = func.name.replace("%uD" % (dim), "")
74	n = "__glx_%s_%uD%uD" % (n, d - 1, d)
75
76	h = hash_pre + h + hash_suf
77	return [h, n]
78
79
80class glx_pixel_function_stub(glX_XML.glx_function):
81	"""Dummy class used to generate pixel "utility" functions that are
82	shared by multiple dimension image functions.  For example, these
83	objects are used to generate shared functions used to send GLX
84	protocol for TexImage1D and TexImage2D, TexSubImage1D and
85	TexSubImage2D, etc."""
86
87	def __init__(self, func, name):
88		# The parameters to the utility function are the same as the
89		# parameters to the real function except for the added "pad"
90		# parameters.
91
92		self.name = name
93		self.images = []
94		self.parameters = []
95		self.parameters_by_name = {}
96		for _p in func.parameterIterator():
97			p = copy.copy(_p)
98			self.parameters.append(p)
99			self.parameters_by_name[ p.name ] = p
100
101
102			if p.is_image():
103				self.images.append(p)
104				p.height = "height"
105
106				if p.img_yoff == None:
107					p.img_yoff = "yoffset"
108
109				if p.depth:
110					if p.extent == None:
111						p.extent = "extent"
112
113					if p.img_woff == None:
114						p.img_woff = "woffset"
115
116
117			pad_name = func.pad_after(p)
118			if pad_name:
119				pad = copy.copy(p)
120				pad.name = pad_name
121				self.parameters.append(pad)
122				self.parameters_by_name[ pad.name ] = pad
123
124
125		self.return_type = func.return_type
126
127		self.glx_rop = ~0
128		self.glx_sop = 0
129		self.glx_vendorpriv = 0
130
131		self.glx_doubles_in_order = func.glx_doubles_in_order
132
133		self.vectorequiv = None
134		self.output = None
135		self.can_be_large = func.can_be_large
136		self.reply_always_array = func.reply_always_array
137		self.dimensions_in_reply = func.dimensions_in_reply
138		self.img_reset = None
139
140		self.server_handcode = 0
141		self.client_handcode = 0
142		self.ignore = 0
143
144		self.count_parameter_list = func.count_parameter_list
145		self.counter_list = func.counter_list
146		self.offsets_calculated = 0
147		return
148
149
150class PrintGlxProtoStubs(glX_proto_common.glx_print_proto):
151	def __init__(self):
152		glX_proto_common.glx_print_proto.__init__(self)
153		self.name = "glX_proto_send.py (from Mesa)"
154		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
155
156
157		self.last_category = ""
158		self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
159		self.pixel_stubs = {}
160		self.debug = 0
161		return
162
163	def printRealHeader(self):
164		print ''
165		print '#include <GL/gl.h>'
166		print '#include "indirect.h"'
167		print '#include "glxclient.h"'
168		print '#include "indirect_size.h"'
169		print '#include "dispatch.h"'
170		print '#include "glapi.h"'
171		print '#include "glthread.h"'
172		print '#include <GL/glxproto.h>'
173		print '#ifdef USE_XCB'
174		print '#include <X11/Xlib-xcb.h>'
175		print '#include <xcb/xcb.h>'
176		print '#include <xcb/glx.h>'
177		print '#endif /* USE_XCB */'
178
179		print ''
180		print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
181		print ''
182		self.printFastcall()
183		self.printNoinline()
184		print ''
185		print '#if !defined __GNUC__ || __GNUC__ < 3'
186		print '#  define __builtin_expect(x, y) x'
187		print '#endif'
188		print ''
189		print '/* If the size and opcode values are known at compile-time, this will, on'
190		print ' * x86 at least, emit them with a single instruction.'
191		print ' */'
192		print '#define emit_header(dest, op, size)            \\'
193		print '    do { union { short s[2]; int i; } temp;    \\'
194		print '         temp.s[0] = (size); temp.s[1] = (op); \\'
195		print '         *((int *)(dest)) = temp.i; } while(0)'
196		print ''
197		print """NOINLINE CARD32
198__glXReadReply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
199{
200    xGLXSingleReply reply;
201
202    (void) _XReply(dpy, (xReply *) & reply, 0, False);
203    if (size != 0) {
204        if ((reply.length > 0) || reply_is_always_array) {
205            const GLint bytes = (reply_is_always_array)
206              ? (4 * reply.length) : (reply.size * size);
207            const GLint extra = 4 - (bytes & 3);
208
209            _XRead(dpy, dest, bytes);
210            if ( extra < 4 ) {
211                _XEatData(dpy, extra);
212            }
213        }
214        else {
215            (void) memcpy( dest, &(reply.pad3), size);
216        }
217    }
218
219    return reply.retval;
220}
221
222NOINLINE void
223__glXReadPixelReply( Display *dpy, __GLXcontext * gc, unsigned max_dim,
224    GLint width, GLint height, GLint depth, GLenum format, GLenum type,
225    void * dest, GLboolean dimensions_in_reply )
226{
227    xGLXSingleReply reply;
228    GLint size;
229
230    (void) _XReply(dpy, (xReply *) & reply, 0, False);
231
232    if ( dimensions_in_reply ) {
233        width  = reply.pad3;
234        height = reply.pad4;
235        depth  = reply.pad5;
236
237	if ((height == 0) || (max_dim < 2)) { height = 1; }
238	if ((depth  == 0) || (max_dim < 3)) { depth  = 1; }
239    }
240
241    size = reply.length * 4;
242    if (size != 0) {
243        void * buf = Xmalloc( size );
244
245        if ( buf == NULL ) {
246            _XEatData(dpy, size);
247            __glXSetError(gc, GL_OUT_OF_MEMORY);
248        }
249        else {
250            const GLint extra = 4 - (size & 3);
251
252            _XRead(dpy, buf, size);
253            if ( extra < 4 ) {
254                _XEatData(dpy, extra);
255            }
256
257            __glEmptyImage(gc, 3, width, height, depth, format, type,
258                           buf, dest);
259            Xfree(buf);
260        }
261    }
262}
263
264#define X_GLXSingle 0
265
266NOINLINE FASTCALL GLubyte *
267__glXSetupSingleRequest( __GLXcontext * gc, GLint sop, GLint cmdlen )
268{
269    xGLXSingleReq * req;
270    Display * const dpy = gc->currentDpy;
271
272    (void) __glXFlushRenderBuffer(gc, gc->pc);
273    LockDisplay(dpy);
274    GetReqExtra(GLXSingle, cmdlen, req);
275    req->reqType = gc->majorOpcode;
276    req->contextTag = gc->currentContextTag;
277    req->glxCode = sop;
278    return (GLubyte *)(req) + sz_xGLXSingleReq;
279}
280
281NOINLINE FASTCALL GLubyte *
282__glXSetupVendorRequest( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
283{
284    xGLXVendorPrivateReq * req;
285    Display * const dpy = gc->currentDpy;
286
287    (void) __glXFlushRenderBuffer(gc, gc->pc);
288    LockDisplay(dpy);
289    GetReqExtra(GLXVendorPrivate, cmdlen, req);
290    req->reqType = gc->majorOpcode;
291    req->glxCode = code;
292    req->vendorCode = vop;
293    req->contextTag = gc->currentContextTag;
294    return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
295}
296
297const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
298
299#define zero                        (__glXDefaultPixelStore+0)
300#define one                         (__glXDefaultPixelStore+8)
301#define default_pixel_store_1D      (__glXDefaultPixelStore+4)
302#define default_pixel_store_1D_size 20
303#define default_pixel_store_2D      (__glXDefaultPixelStore+4)
304#define default_pixel_store_2D_size 20
305#define default_pixel_store_3D      (__glXDefaultPixelStore+0)
306#define default_pixel_store_3D_size 36
307#define default_pixel_store_4D      (__glXDefaultPixelStore+0)
308#define default_pixel_store_4D_size 36
309"""
310
311		for size in self.generic_sizes:
312			self.print_generic_function(size)
313		return
314
315
316	def printBody(self, api):
317
318		self.pixel_stubs = {}
319		generated_stubs = []
320
321		for func in api.functionIterateGlx():
322			if func.client_handcode: continue
323
324			# If the function is a pixel function with a certain
325			# GLX protocol signature, create a fake stub function
326			# for it.  For example, create a single stub function
327			# that is used to implement both glTexImage1D and
328			# glTexImage2D.
329
330			if func.glx_rop != 0:
331				do_it = 0
332				for image in func.get_images():
333					if image.img_pad_dimensions:
334						do_it = 1
335						break
336
337
338				if do_it:
339					[h, n] = hash_pixel_function(func)
340
341
342					self.pixel_stubs[ func.name ] = n
343					if h not in generated_stubs:
344						generated_stubs.append(h)
345
346						fake_func = glx_pixel_function_stub( func, n )
347						self.printFunction(fake_func, fake_func.name)
348
349
350			self.printFunction(func, func.name)
351			if func.glx_sop and func.glx_vendorpriv:
352				self.printFunction(func, func.glx_vendorpriv_names[0])
353
354		return
355
356
357	def printFunction(self, func, name):
358		footer = '}\n'
359		if func.glx_rop == ~0:
360			print 'static %s' % (func.return_type)
361			print '%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())
362			print '{'
363		else:
364			if func.has_different_protocol(name):
365				if func.return_type == "void":
366					ret_string = ''
367				else:
368					ret_string = "return "
369
370				func_name = func.static_glx_name(name)
371				print '#define %s %d' % (func.opcode_vendor_name(name), func.glx_vendorpriv)
372				print '%s gl%s(%s)' % (func.return_type, func_name, func.get_parameter_string())
373				print '{'
374				print '    __GLXcontext * const gc = __glXGetCurrentContext();'
375				print ''
376				print '    if (gc->isDirect) {'
377				print '    %sCALL_%s(GET_DISPATCH(), (%s));' % (ret_string, func.name, func.get_called_parameter_string())
378				print '    } else {'
379				footer = '}\n}\n'
380			else:
381				print '#define %s %d' % (func.opcode_name(), func.opcode_value())
382
383				print '%s __indirect_gl%s(%s)' % (func.return_type, name, func.get_parameter_string())
384				print '{'
385
386
387		if func.glx_rop != 0 or func.vectorequiv != None:
388			if len(func.images):
389				self.printPixelFunction(func)
390			else:
391				self.printRenderFunction(func)
392		elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
393			self.printSingleFunction(func, name)
394			pass
395		else:
396			print "/* Missing GLX protocol for %s. */" % (name)
397
398		print footer
399		return
400
401
402	def print_generic_function(self, n):
403		size = (n + 3) & ~3
404		print """static FASTCALL NOINLINE void
405generic_%u_byte( GLint rop, const void * ptr )
406{
407    __GLXcontext * const gc = __glXGetCurrentContext();
408    const GLuint cmdlen = %u;
409
410    emit_header(gc->pc, rop, cmdlen);
411    (void) memcpy((void *)(gc->pc + 4), ptr, %u);
412    gc->pc += cmdlen;
413    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
414}
415""" % (n, size + 4, size)
416		return
417
418
419	def common_emit_one_arg(self, p, pc, adjust, extra_offset):
420		if p.is_array():
421			src_ptr = p.name
422		else:
423			src_ptr = "&" + p.name
424
425		if not extra_offset:
426			print '(void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
427			    % (pc, p.offset + adjust, src_ptr, p.size_string() )
428		else:
429			print '(void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \
430			    % (pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() )
431
432	def common_emit_args(self, f, pc, adjust, skip_vla):
433		extra_offset = None
434
435		for p in f.parameterIterateGlxSend( not skip_vla ):
436			if p.name != f.img_reset:
437				self.common_emit_one_arg(p, pc, adjust, extra_offset)
438
439				if p.is_variable_length():
440					temp = p.size_string()
441					if extra_offset:
442						extra_offset += " + %s" % (temp)
443					else:
444						extra_offset = temp
445
446		return
447
448
449	def pixel_emit_args(self, f, pc, large):
450		"""Emit the arguments for a pixel function.  This differs from
451		common_emit_args in that pixel functions may require padding
452		be inserted (i.e., for the missing width field for
453		TexImage1D), and they may also require a 'NULL image' flag
454		be inserted before the image data."""
455
456		if large:
457			adjust = 8
458		else:
459			adjust = 4
460
461		for param in f.parameterIterateGlxSend():
462			if not param.is_image():
463				self.common_emit_one_arg(param, pc, adjust, None)
464
465				if f.pad_after(param):
466					print '(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset + param.size()) + adjust)
467
468			else:
469				[dim, width, height, depth, extent] = param.get_dimensions()
470				if f.glx_rop == ~0:
471					dim_str = "dim"
472				else:
473					dim_str = str(dim)
474
475				if param.img_null_flag:
476					if large:
477						print '(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset - 4) + adjust)
478					else:
479						print '(void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (pc, (param.offset - 4) + adjust, param.name)
480
481
482				pixHeaderPtr = "%s + %u" % (pc, adjust)
483				pcPtr = "%s + %u" % (pc, param.offset + adjust)
484
485				if not large:
486					if param.img_send_null:
487						condition = '(compsize > 0) && (%s != NULL)' % (param.name)
488					else:
489						condition = 'compsize > 0'
490
491					print 'if (%s) {' % (condition)
492					print '    (*gc->fillImage)(gc, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
493					print '} else {'
494					print '    (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (pixHeaderPtr, dim, dim)
495					print '}'
496				else:
497					print '__glXSendLargeImage(gc, compsize, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
498
499		return
500
501
502	def large_emit_begin(self, f, op_name = None):
503		if not op_name:
504			op_name = f.opcode_real_name()
505
506		print 'const GLint op = %s;' % (op_name)
507		print 'const GLuint cmdlenLarge = cmdlen + 4;'
508		print 'GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);'
509		print '(void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);'
510		print '(void) memcpy((void *)(pc + 4), (void *)(&op), 4);'
511		return
512
513
514	def common_func_print_just_start(self, f, name):
515		print '    __GLXcontext * const gc = __glXGetCurrentContext();'
516
517		# The only reason that single and vendor private commands need
518		# a variable called 'dpy' is becuase they use the SyncHandle
519		# macro.  For whatever brain-dead reason, that macro is hard-
520		# coded to use a variable called 'dpy' instead of taking a
521		# parameter.
522
523		# FIXME Simplify the logic related to skip_condition and
524		# FIXME condition_list in this function.  Basically, remove
525		# FIXME skip_condition, and just append the "dpy != NULL" type
526		# FIXME condition to condition_list from the start.  The only
527		# FIXME reason it's done in this confusing way now is to
528		# FIXME minimize the diffs in the generated code.
529
530		if not f.glx_rop:
531			for p in f.parameterIterateOutputs():
532				if p.is_image() and (p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP"):
533					print '    const __GLXattribute * const state = gc->client_state_private;'
534					break
535
536			print '    Display * const dpy = gc->currentDpy;'
537			skip_condition = "dpy != NULL"
538		elif f.can_be_large:
539			skip_condition = "gc->currentDpy != NULL"
540		else:
541			skip_condition = None
542
543
544		if f.return_type != 'void':
545			print '    %s retval = (%s) 0;' % (f.return_type, f.return_type)
546
547
548		if name != None and name not in f.glx_vendorpriv_names:
549			print '#ifndef USE_XCB'
550		self.emit_packet_size_calculation(f, 0)
551		if name != None and name not in f.glx_vendorpriv_names:
552			print '#endif'
553
554		condition_list = []
555		for p in f.parameterIterateCounters():
556			condition_list.append( "%s >= 0" % (p.name) )
557
558		if skip_condition:
559			condition_list.append( skip_condition )
560
561		if len( condition_list ) > 0:
562			if len( condition_list ) > 1:
563				skip_condition = "(%s)" % (string.join( condition_list, ") && (" ))
564			else:
565				skip_condition = "%s" % (condition_list.pop(0))
566
567			print '    if (__builtin_expect(%s, 1)) {' % (skip_condition)
568			return 1
569		else:
570			return 0
571
572
573	def printSingleFunction(self, f, name):
574		self.common_func_print_just_start(f, name)
575
576		if self.debug:
577			print '        printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
578
579		if name not in f.glx_vendorpriv_names:
580
581			# XCB specific:
582			print '#ifdef USE_XCB'
583			if self.debug:
584				print '        printf("\\tUsing XCB.\\n");'
585			print '        xcb_connection_t *c = XGetXCBConnection(dpy);'
586			print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
587			xcb_name = 'xcb_glx%s' % convertStringForXCB(name)
588
589			iparams=[]
590			extra_iparams = []
591			output = None
592			for p in f.parameterIterator():
593				if p.is_output:
594					output = p
595
596					if p.is_image():
597						if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP":
598							extra_iparams.append("state->storePack.swapEndian")
599						else:
600							extra_iparams.append("0")
601
602						# Hardcode this in.  lsb_first param (apparently always GL_FALSE)
603						# also present in GetPolygonStipple, but taken care of above.
604						if xcb_name == "xcb_glx_read_pixels":
605							extra_iparams.append("0")
606				else:
607					iparams.append(p.name)
608
609
610			xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams))
611
612			if f.needs_reply():
613				print '        %s_reply_t *reply = %s_reply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request)
614				if output and f.reply_always_array:
615					print '        (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
616
617				elif output and not f.reply_always_array:
618					if not output.is_image():
619						print '        if (%s_data_length(reply) == 0)' % (xcb_name)
620						print '            (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)
621						print '        else'
622					print '        (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
623
624
625				if f.return_type != 'void':
626					print '        retval = reply->ret_val;'
627				print '        free(reply);'
628			else:
629				print '        ' + xcb_request + ';'
630			print '#else'
631			# End of XCB specific.
632
633
634		if f.parameters != []:
635			pc_decl = "GLubyte const * pc ="
636		else:
637			pc_decl = "(void)"
638
639		if name in f.glx_vendorpriv_names:
640			print '        %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_vendor_name(name))
641		else:
642			print '        %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
643
644		self.common_emit_args(f, "pc", 0, 0)
645
646		images = f.get_images()
647
648		for img in images:
649			if img.is_output:
650				o = f.command_fixed_length() - 4
651				print '        *(int32_t *)(pc + %u) = 0;' % (o)
652				if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
653					print '        * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
654
655				if f.img_reset:
656					print '        * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
657
658
659		return_name = ''
660		if f.needs_reply():
661			if f.return_type != 'void':
662				return_name = " retval"
663				return_str = " retval = (%s)" % (f.return_type)
664			else:
665				return_str = " (void)"
666
667			got_reply = 0
668
669			for p in f.parameterIterateOutputs():
670				if p.is_image():
671					[dim, w, h, d, junk] = p.get_dimensions()
672					if f.dimensions_in_reply:
673						print "        __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)
674					else:
675						print "        __glXReadPixelReply(dpy, gc, %u, %s, %s, %s, %s, %s, %s, GL_FALSE);" % (dim, w, h, d, p.img_format, p.img_type, p.name)
676
677					got_reply = 1
678				else:
679					if f.reply_always_array:
680						aa = "GL_TRUE"
681					else:
682						aa = "GL_FALSE"
683
684					# gl_parameter.size() returns the size
685					# of the entire data item.  If the
686					# item is a fixed-size array, this is
687					# the size of the whole array.  This
688					# is not what __glXReadReply wants. It
689					# wants the size of a single data
690					# element in the reply packet.
691					# Dividing by the array size (1 for
692					# non-arrays) gives us this.
693
694					s = p.size() / p.get_element_count()
695					print "       %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)
696					got_reply = 1
697
698
699			# If a reply wasn't read to fill an output parameter,
700			# read a NULL reply to get the return value.
701
702			if not got_reply:
703				print "       %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)
704
705
706		elif self.debug:
707			# Only emit the extra glFinish call for functions
708			# that don't already require a reply from the server.
709			print '        __indirect_glFinish();'
710
711		if self.debug:
712			print '        printf( "Exit %%s.\\n", "gl%s" );' % (name)
713
714
715		print '        UnlockDisplay(dpy); SyncHandle();'
716
717		if name not in f.glx_vendorpriv_names:
718			print '#endif /* USE_XCB */'
719
720		print '    }'
721		print '    return%s;' % (return_name)
722		return
723
724
725	def printPixelFunction(self, f):
726		if self.pixel_stubs.has_key( f.name ):
727			# Normally gl_function::get_parameter_string could be
728			# used.  However, this call needs to have the missing
729			# dimensions (e.g., a fake height value for
730			# glTexImage1D) added in.
731
732			p_string = ""
733			for param in f.parameterIterateGlxSend():
734				p_string += ", " + param.name
735
736				if param.is_image():
737					[dim, junk, junk, junk, junk] = param.get_dimensions()
738
739				if f.pad_after(param):
740					p_string += ", 1"
741
742			print '    %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)
743			return
744
745
746		if self.common_func_print_just_start(f, None):
747			trailer = "    }"
748		else:
749			trailer = None
750
751
752		if f.can_be_large:
753			print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
754			print '    if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
755			print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
756			print '    }'
757
758		if f.glx_rop == ~0:
759			opcode = "opcode"
760		else:
761			opcode = f.opcode_real_name()
762
763		print 'emit_header(gc->pc, %s, cmdlen);' % (opcode)
764
765		self.pixel_emit_args( f, "gc->pc", 0 )
766		print 'gc->pc += cmdlen;'
767		print 'if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
768
769		if f.can_be_large:
770			print '}'
771			print 'else {'
772
773			self.large_emit_begin(f, opcode)
774			self.pixel_emit_args(f, "pc", 1)
775
776			print '}'
777
778		if trailer: print trailer
779		return
780
781
782	def printRenderFunction(self, f):
783		# There is a class of GL functions that take a single pointer
784		# as a parameter.  This pointer points to a fixed-size chunk
785		# of data, and the protocol for this functions is very
786		# regular.  Since they are so regular and there are so many
787		# of them, special case them with generic functions.  On
788		# x86, this saves about 26KB in the libGL.so binary.
789
790		if f.variable_length_parameter() == None and len(f.parameters) == 1:
791			p = f.parameters[0]
792			if p.is_pointer():
793				cmdlen = f.command_fixed_length()
794				if cmdlen in self.generic_sizes:
795					print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
796					return
797
798		if self.common_func_print_just_start(f, None):
799			trailer = "    }"
800		else:
801			trailer = None
802
803		if self.debug:
804			print 'printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
805
806		if f.can_be_large:
807			print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
808			print '    if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
809			print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
810			print '    }'
811
812		print 'emit_header(gc->pc, %s, cmdlen);' % (f.opcode_real_name())
813
814		self.common_emit_args(f, "gc->pc", 4, 0)
815		print 'gc->pc += cmdlen;'
816		print 'if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
817
818		if f.can_be_large:
819			print '}'
820			print 'else {'
821
822			self.large_emit_begin(f)
823			self.common_emit_args(f, "pc", 8, 1)
824
825			p = f.variable_length_parameter()
826			print '    __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (p.offset + 8, p.name, p.size_string())
827			print '}'
828
829		if self.debug:
830			print '__indirect_glFinish();'
831			print 'printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
832
833		if trailer: print trailer
834		return
835
836
837class PrintGlxProtoInit_c(gl_XML.gl_print_base):
838	def __init__(self):
839		gl_XML.gl_print_base.__init__(self)
840
841		self.name = "glX_proto_send.py (from Mesa)"
842		self.license = license.bsd_license_template % ( \
843"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
844(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
845		return
846
847
848	def printRealHeader(self):
849		print """/**
850 * \\file indirect_init.c
851 * Initialize indirect rendering dispatch table.
852 *
853 * \\author Kevin E. Martin <kevin@precisioninsight.com>
854 * \\author Brian Paul <brian@precisioninsight.com>
855 * \\author Ian Romanick <idr@us.ibm.com>
856 */
857
858#include "indirect_init.h"
859#include "indirect.h"
860#include "glapi.h"
861
862
863/**
864 * No-op function used to initialize functions that have no GLX protocol
865 * support.
866 */
867static int NoOp(void)
868{
869    return 0;
870}
871
872/**
873 * Create and initialize a new GL dispatch table.  The table is initialized
874 * with GLX indirect rendering protocol functions.
875 */
876__GLapi * __glXNewIndirectAPI( void )
877{
878    __GLapi *glAPI;
879    GLuint entries;
880
881    entries = _glapi_get_dispatch_table_size();
882    glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
883
884    /* first, set all entries to point to no-op functions */
885    {
886       int i;
887       void **dispatch = (void **) glAPI;
888       for (i = 0; i < entries; i++) {
889          dispatch[i] = (void *) NoOp;
890       }
891    }
892
893    /* now, initialize the entries we understand */"""
894
895	def printRealFooter(self):
896		print """
897    return glAPI;
898}
899"""
900		return
901
902
903	def printBody(self, api):
904		for [name, number] in api.categoryIterate():
905			if number != None:
906				preamble = '\n    /* %3u. %s */\n\n' % (int(number), name)
907			else:
908				preamble = '\n    /* %s */\n\n' % (name)
909
910			for func in api.functionIterateByCategory(name):
911				if func.client_supported_for_indirect():
912					print '%s    glAPI->%s = __indirect_gl%s;' % (preamble, func.name, func.name)
913					preamble = ''
914
915		return
916
917
918class PrintGlxProtoInit_h(gl_XML.gl_print_base):
919	def __init__(self):
920		gl_XML.gl_print_base.__init__(self)
921
922		self.name = "glX_proto_send.py (from Mesa)"
923		self.license = license.bsd_license_template % ( \
924"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
925(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
926		self.header_tag = "_INDIRECT_H_"
927
928		self.last_category = ""
929		return
930
931
932	def printRealHeader(self):
933		print """/**
934 * \\file
935 * Prototypes for indirect rendering functions.
936 *
937 * \\author Kevin E. Martin <kevin@precisioninsight.com>
938 * \\author Ian Romanick <idr@us.ibm.com>
939 */
940"""
941		self.printVisibility( "HIDDEN", "hidden" )
942		self.printFastcall()
943		self.printNoinline()
944
945		print """
946#include "glxclient.h"
947
948extern HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
949    void * dest, GLboolean reply_is_always_array );
950
951extern HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
952    __GLXcontext * gc, unsigned max_dim, GLint width, GLint height,
953    GLint depth, GLenum format, GLenum type, void * dest,
954    GLboolean dimensions_in_reply );
955
956extern HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
957    __GLXcontext * gc, GLint sop, GLint cmdlen );
958
959extern HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
960    __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen );
961"""
962
963
964	def printBody(self, api):
965		for func in api.functionIterateGlx():
966			params = func.get_parameter_string()
967
968			print 'extern HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params)
969
970			for n in func.entry_points:
971				if func.has_different_protocol(n):
972					asdf = func.static_glx_name(n)
973					if asdf not in func.static_entry_points:
974						print 'extern HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params)
975					else:
976						print 'GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params)
977
978					break
979
980
981
982def show_usage():
983	print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0]
984	print "    -m output_mode   Output mode can be one of 'proto', 'init_c' or 'init_h'."
985	print "    -d               Enable extra debug information in the generated code."
986	sys.exit(1)
987
988
989if __name__ == '__main__':
990	file_name = "gl_API.xml"
991
992	try:
993		(args, trail) = getopt.getopt(sys.argv[1:], "f:m:d")
994	except Exception,e:
995		show_usage()
996
997	debug = 0
998	mode = "proto"
999	for (arg,val) in args:
1000		if arg == "-f":
1001			file_name = val
1002		elif arg == "-m":
1003			mode = val
1004		elif arg == "-d":
1005			debug = 1
1006
1007	if mode == "proto":
1008		printer = PrintGlxProtoStubs()
1009	elif mode == "init_c":
1010		printer = PrintGlxProtoInit_c()
1011	elif mode == "init_h":
1012		printer = PrintGlxProtoInit_h()
1013	else:
1014		show_usage()
1015
1016
1017	printer.debug = debug
1018	api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() )
1019
1020	printer.Print( api )
1021