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