1#!/usr/bin/env python 2 3# (C) Copyright IBM Corporation 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 28import gl_XML, glX_XML, glX_proto_common, license 29import sys, getopt, string 30 31 32class PrintGlxDispatch_h(gl_XML.gl_print_base): 33 def __init__(self): 34 gl_XML.gl_print_base.__init__(self) 35 36 self.name = "glX_proto_recv.py (from Mesa)" 37 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM") 38 39 self.header_tag = "_INDIRECT_DISPATCH_H_" 40 return 41 42 43 def printRealHeader(self): 44 print '# include <X11/Xfuncproto.h>' 45 print '' 46 print 'struct __GLXclientStateRec;' 47 print '' 48 return 49 50 51 def printBody(self, api): 52 for func in api.functionIterateAll(): 53 if not func.ignore and not func.vectorequiv: 54 if func.glx_rop: 55 print 'extern _X_HIDDEN void __glXDisp_%s(GLbyte * pc);' % (func.name) 56 print 'extern _X_HIDDEN void __glXDispSwap_%s(GLbyte * pc);' % (func.name) 57 elif func.glx_sop or func.glx_vendorpriv: 58 print 'extern _X_HIDDEN int __glXDisp_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name) 59 print 'extern _X_HIDDEN int __glXDispSwap_%s(struct __GLXclientStateRec *, GLbyte *);' % (func.name) 60 61 if func.glx_sop and func.glx_vendorpriv: 62 n = func.glx_vendorpriv_names[0] 63 print 'extern _X_HIDDEN int __glXDisp_%s(struct __GLXclientStateRec *, GLbyte *);' % (n) 64 print 'extern _X_HIDDEN int __glXDispSwap_%s(struct __GLXclientStateRec *, GLbyte *);' % (n) 65 66 return 67 68 69class PrintGlxDispatchFunctions(glX_proto_common.glx_print_proto): 70 def __init__(self, do_swap): 71 gl_XML.gl_print_base.__init__(self) 72 self.name = "glX_proto_recv.py (from Mesa)" 73 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005", "IBM") 74 75 self.real_types = [ '', '', 'uint16_t', '', 'uint32_t', '', '', '', 'uint64_t' ] 76 self.do_swap = do_swap 77 return 78 79 80 def printRealHeader(self): 81 print '#include <X11/Xmd.h>' 82 print '#include <GL/gl.h>' 83 print '#include <GL/glxproto.h>' 84 85 print '#include <inttypes.h>' 86 print '#include "indirect_size.h"' 87 print '#include "indirect_size_get.h"' 88 print '#include "indirect_dispatch.h"' 89 print '#include "glxserver.h"' 90 print '#include "glxbyteorder.h"' 91 print '#include "indirect_util.h"' 92 print '#include "singlesize.h"' 93 print '#include "glapi.h"' 94 print '#include "glapitable.h"' 95 print '#include "glthread.h"' 96 print '#include "dispatch.h"' 97 print '' 98 print '#define __GLX_PAD(x) (((x) + 3) & ~3)' 99 print '' 100 print 'typedef struct {' 101 print ' __GLX_PIXEL_3D_HDR;' 102 print '} __GLXpixel3DHeader;' 103 print '' 104 print 'extern GLboolean __glXErrorOccured( void );' 105 print 'extern void __glXClearErrorOccured( void );' 106 print '' 107 print 'static const unsigned dummy_answer[2] = {0, 0};' 108 print '' 109 return 110 111 112 def printBody(self, api): 113 if self.do_swap: 114 self.emit_swap_wrappers(api) 115 116 117 for func in api.functionIterateByOffset(): 118 if not func.ignore and not func.server_handcode and not func.vectorequiv and (func.glx_rop or func.glx_sop or func.glx_vendorpriv): 119 self.printFunction(func, func.name) 120 if func.glx_sop and func.glx_vendorpriv: 121 self.printFunction(func, func.glx_vendorpriv_names[0]) 122 123 124 return 125 126 127 def printFunction(self, f, name): 128 if (f.glx_sop or f.glx_vendorpriv) and (len(f.get_images()) != 0): 129 return 130 131 if not self.do_swap: 132 base = '__glXDisp' 133 else: 134 base = '__glXDispSwap' 135 136 if f.glx_rop: 137 print 'void %s_%s(GLbyte * pc)' % (base, name) 138 else: 139 print 'int %s_%s(__GLXclientState *cl, GLbyte *pc)' % (base, name) 140 141 print '{' 142 143 if f.glx_rop or f.vectorequiv: 144 self.printRenderFunction(f) 145 elif f.glx_sop or f.glx_vendorpriv: 146 if len(f.get_images()) == 0: 147 self.printSingleFunction(f, name) 148 else: 149 print "/* Missing GLX protocol for %s. */" % (name) 150 151 print '}' 152 print '' 153 return 154 155 156 def swap_name(self, bytes): 157 return 'bswap_%u_array' % (8 * bytes) 158 159 160 def emit_swap_wrappers(self, api): 161 self.type_map = {} 162 already_done = [ ] 163 164 for t in api.typeIterate(): 165 te = t.get_type_expression() 166 t_size = te.get_element_size() 167 168 if t_size > 1 and t.glx_name: 169 170 t_name = "GL" + t.name 171 self.type_map[ t_name ] = t.glx_name 172 173 if t.glx_name not in already_done: 174 real_name = self.real_types[t_size] 175 176 print 'static %s' % (t_name) 177 print 'bswap_%s( const void * src )' % (t.glx_name) 178 print '{' 179 print ' union { %s dst; %s ret; } x;' % (real_name, t_name) 180 print ' x.dst = bswap_%u( *(%s *) src );' % (t_size * 8, real_name) 181 print ' return x.ret;' 182 print '}' 183 print '' 184 already_done.append( t.glx_name ) 185 186 for bits in [16, 32, 64]: 187 print 'static void *' 188 print 'bswap_%u_array( uint%u_t * src, unsigned count )' % (bits, bits) 189 print '{' 190 print ' unsigned i;' 191 print '' 192 print ' for ( i = 0 ; i < count ; i++ ) {' 193 print ' uint%u_t temp = bswap_%u( src[i] );' % (bits, bits) 194 print ' src[i] = temp;' 195 print ' }' 196 print '' 197 print ' return src;' 198 print '}' 199 print '' 200 201 202 def fetch_param(self, param): 203 t = param.type_string() 204 o = param.offset 205 element_size = param.size() / param.get_element_count() 206 207 if self.do_swap and (element_size != 1): 208 if param.is_array(): 209 real_name = self.real_types[ element_size ] 210 211 swap_func = self.swap_name( element_size ) 212 return ' (%-8s)%s( (%s *) (pc + %2s), %s )' % (t, swap_func, real_name, o, param.count) 213 else: 214 t_name = param.get_base_type_string() 215 return ' (%-8s)bswap_%-7s( pc + %2s )' % (t, self.type_map[ t_name ], o) 216 else: 217 if param.is_array(): 218 return ' (%-8s)(pc + %2u)' % (t, o) 219 else: 220 return '*(%-8s *)(pc + %2u)' % (t, o) 221 222 return None 223 224 225 def emit_function_call(self, f, retval_assign, indent): 226 list = [] 227 228 for param in f.parameterIterator(): 229 if param.is_padding: 230 continue 231 232 if param.is_counter or param.is_image() or param.is_output or param.name in f.count_parameter_list or len(param.count_parameter_list): 233 location = param.name 234 else: 235 location = self.fetch_param(param) 236 237 list.append( '%s %s' % (indent, location) ) 238 239 240 if len( list ): 241 print '%s %sCALL_%s( GET_DISPATCH(), (' % (indent, retval_assign, f.name) 242 print string.join( list, ",\n" ) 243 print '%s ) );' % (indent) 244 else: 245 print '%s %sCALL_%s( GET_DISPATCH(), () );' % (indent, retval_assign, f.name) 246 return 247 248 249 def common_func_print_just_start(self, f, indent): 250 align64 = 0 251 need_blank = 0 252 253 254 f.calculate_offsets() 255 for param in f.parameterIterateGlxSend(): 256 # If any parameter has a 64-bit base type, then we 257 # have to do alignment magic for the while thing. 258 259 if param.is_64_bit(): 260 align64 = 1 261 262 263 # FIXME img_null_flag is over-loaded. In addition to 264 # FIXME being used for images, it is used to signify 265 # FIXME NULL data pointers for vertex buffer object 266 # FIXME related functions. Re-name it to null_data 267 # FIXME or something similar. 268 269 if param.img_null_flag: 270 print '%s const CARD32 ptr_is_null = *(CARD32 *)(pc + %s);' % (indent, param.offset - 4) 271 cond = '(ptr_is_null != 0) ? NULL : ' 272 else: 273 cond = "" 274 275 276 type_string = param.type_string() 277 278 if param.is_image(): 279 offset = f.offset_of( param.name ) 280 281 print '%s %s const %s = (%s) (%s(pc + %s));' % (indent, type_string, param.name, type_string, cond, offset) 282 283 if param.depth: 284 print '%s __GLXpixel3DHeader * const hdr = (__GLXpixel3DHeader *)(pc);' % (indent) 285 else: 286 print '%s __GLXpixelHeader * const hdr = (__GLXpixelHeader *)(pc);' % (indent) 287 288 need_blank = 1 289 elif param.is_counter or param.name in f.count_parameter_list: 290 location = self.fetch_param(param) 291 print '%s const %s %s = %s;' % (indent, type_string, param.name, location) 292 need_blank = 1 293 elif len(param.count_parameter_list): 294 if param.size() == 1 and not self.do_swap: 295 location = self.fetch_param(param) 296 print '%s %s %s = %s%s;' % (indent, type_string, param.name, cond, location) 297 else: 298 print '%s %s %s;' % (indent, type_string, param.name) 299 need_blank = 1 300 301 302 303 if need_blank: 304 print '' 305 306 if align64: 307 print '#ifdef __GLX_ALIGN64' 308 309 if f.has_variable_size_request(): 310 self.emit_packet_size_calculation(f, 4) 311 s = "cmdlen" 312 else: 313 s = str((f.command_fixed_length() + 3) & ~3) 314 315 print ' if ((unsigned long)(pc) & 7) {' 316 print ' (void) memmove(pc-4, pc, %s);' % (s) 317 print ' pc -= 4;' 318 print ' }' 319 print '#endif' 320 print '' 321 322 323 need_blank = 0 324 if self.do_swap: 325 for param in f.parameterIterateGlxSend(): 326 if param.count_parameter_list: 327 o = param.offset 328 count = param.get_element_count() 329 type_size = param.size() / count 330 331 if param.counter: 332 count_name = param.counter 333 else: 334 count_name = str(count) 335 336 # This is basically an ugly special- 337 # case for glCallLists. 338 339 if type_size == 1: 340 x = [] 341 x.append( [1, ['BYTE', 'UNSIGNED_BYTE', '2_BYTES', '3_BYTES', '4_BYTES']] ) 342 x.append( [2, ['SHORT', 'UNSIGNED_SHORT']] ) 343 x.append( [4, ['INT', 'UNSIGNED_INT', 'FLOAT']] ) 344 345 print ' switch(%s) {' % (param.count_parameter_list[0]) 346 for sub in x: 347 for t_name in sub[1]: 348 print ' case GL_%s:' % (t_name) 349 350 if sub[0] == 1: 351 print ' %s = (%s) (pc + %s); break;' % (param.name, param.type_string(), o) 352 else: 353 swap_func = self.swap_name(sub[0]) 354 print ' %s = (%s) %s( (%s *) (pc + %s), %s ); break;' % (param.name, param.type_string(), swap_func, self.real_types[sub[0]], o, count_name) 355 print ' default:' 356 print ' return;' 357 print ' }' 358 else: 359 swap_func = self.swap_name(type_size) 360 compsize = self.size_call(f, 1) 361 print ' %s = (%s) %s( (%s *) (pc + %s), %s );' % (param.name, param.type_string(), swap_func, self.real_types[type_size], o, compsize) 362 363 need_blank = 1 364 365 else: 366 for param in f.parameterIterateGlxSend(): 367 if param.count_parameter_list: 368 print '%s %s = (%s) (pc + %s);' % (indent, param.name, param.type_string(), param.offset) 369 need_blank = 1 370 371 372 if need_blank: 373 print '' 374 375 376 return 377 378 379 def printSingleFunction(self, f, name): 380 if name not in f.glx_vendorpriv_names: 381 print ' xGLXSingleReq * const req = (xGLXSingleReq *) pc;' 382 else: 383 print ' xGLXVendorPrivateReq * const req = (xGLXVendorPrivateReq *) pc;' 384 385 print ' int error;' 386 387 if self.do_swap: 388 print ' __GLXcontext * const cx = __glXForceCurrent(cl, bswap_CARD32( &req->contextTag ), &error);' 389 else: 390 print ' __GLXcontext * const cx = __glXForceCurrent(cl, req->contextTag, &error);' 391 392 print '' 393 if name not in f.glx_vendorpriv_names: 394 print ' pc += __GLX_SINGLE_HDR_SIZE;' 395 else: 396 print ' pc += __GLX_VENDPRIV_HDR_SIZE;' 397 398 print ' if ( cx != NULL ) {' 399 self.common_func_print_just_start(f, " ") 400 401 402 if f.return_type != 'void': 403 print ' %s retval;' % (f.return_type) 404 retval_string = "retval" 405 retval_assign = "retval = " 406 else: 407 retval_string = "0" 408 retval_assign = "" 409 410 411 type_size = 0 412 answer_string = "dummy_answer" 413 answer_count = "0" 414 is_array_string = "GL_FALSE" 415 416 for param in f.parameterIterateOutputs(): 417 answer_type = param.get_base_type_string() 418 if answer_type == "GLvoid": 419 answer_type = "GLubyte" 420 421 422 c = param.get_element_count() 423 type_size = (param.size() / c) 424 if type_size == 1: 425 size_scale = "" 426 else: 427 size_scale = " * %u" % (type_size) 428 429 430 if param.count_parameter_list: 431 print ' const GLuint compsize = %s;' % (self.size_call(f, 1)) 432 print ' %s answerBuffer[200];' % (answer_type) 433 print ' %s %s = __glXGetAnswerBuffer(cl, compsize%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, size_scale, type_size ) 434 answer_string = param.name 435 answer_count = "compsize" 436 437 print '' 438 print ' if (%s == NULL) return BadAlloc;' % (param.name) 439 print ' __glXClearErrorOccured();' 440 print '' 441 elif param.counter: 442 print ' %s answerBuffer[200];' % (answer_type) 443 print ' %s %s = __glXGetAnswerBuffer(cl, %s%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, param.counter, size_scale, type_size) 444 answer_string = param.name 445 answer_count = param.counter 446 elif c >= 1: 447 print ' %s %s[%u];' % (answer_type, param.name, c) 448 answer_string = param.name 449 answer_count = "%u" % (c) 450 451 if f.reply_always_array: 452 is_array_string = "GL_TRUE" 453 454 455 self.emit_function_call(f, retval_assign, " ") 456 457 458 if f.needs_reply(): 459 if self.do_swap: 460 for param in f.parameterIterateOutputs(): 461 c = param.get_element_count() 462 type_size = (param.size() / c) 463 464 if type_size > 1: 465 swap_name = self.swap_name( type_size ) 466 print ' (void) %s( (uint%u_t *) %s, %s );' % (swap_name, 8 * type_size, param.name, answer_count) 467 468 469 reply_func = '__glXSendReplySwap' 470 else: 471 reply_func = '__glXSendReply' 472 473 print ' %s(cl->client, %s, %s, %u, %s, %s);' % (reply_func, answer_string, answer_count, type_size, is_array_string, retval_string) 474 #elif f.note_unflushed: 475 # print ' cx->hasUnflushedCommands = GL_TRUE;' 476 477 print ' error = Success;' 478 print ' }' 479 print '' 480 print ' return error;' 481 return 482 483 484 def printRenderFunction(self, f): 485 # There are 4 distinct phases in a rendering dispatch function. 486 # In the first phase we compute the sizes and offsets of each 487 # element in the command. In the second phase we (optionally) 488 # re-align 64-bit data elements. In the third phase we 489 # (optionally) byte-swap array data. Finally, in the fourth 490 # phase we actually dispatch the function. 491 492 self.common_func_print_just_start(f, "") 493 494 images = f.get_images() 495 if len(images): 496 if self.do_swap: 497 pre = "bswap_CARD32( & " 498 post = " )" 499 else: 500 pre = "" 501 post = "" 502 503 img = images[0] 504 505 # swapBytes and lsbFirst are single byte fields, so 506 # the must NEVER be byte-swapped. 507 508 if not (img.img_type == "GL_BITMAP" and img.img_format == "GL_COLOR_INDEX"): 509 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, hdr->swapBytes) );' 510 511 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, hdr->lsbFirst) );' 512 513 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, (GLint) %shdr->rowLength%s) );' % (pre, post) 514 if img.depth: 515 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_IMAGE_HEIGHT, (GLint) %shdr->imageHeight%s) );' % (pre, post) 516 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, (GLint) %shdr->skipRows%s) );' % (pre, post) 517 if img.depth: 518 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_IMAGES, (GLint) %shdr->skipImages%s) );' % (pre, post) 519 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, (GLint) %shdr->skipPixels%s) );' % (pre, post) 520 print ' CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, (GLint) %shdr->alignment%s) );' % (pre, post) 521 print '' 522 523 524 self.emit_function_call(f, "", "") 525 return 526 527 528if __name__ == '__main__': 529 file_name = "gl_API.xml" 530 531 try: 532 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:s") 533 except Exception,e: 534 show_usage() 535 536 mode = "dispatch_c" 537 do_swap = 0 538 for (arg,val) in args: 539 if arg == "-f": 540 file_name = val 541 elif arg == "-m": 542 mode = val 543 elif arg == "-s": 544 do_swap = 1 545 546 if mode == "dispatch_c": 547 printer = PrintGlxDispatchFunctions(do_swap) 548 elif mode == "dispatch_h": 549 printer = PrintGlxDispatch_h() 550 else: 551 show_usage() 552 553 api = gl_XML.parse_GL_API( file_name, glX_proto_common.glx_proto_item_factory() ) 554 555 printer.Print( api ) 556