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