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 f.glx_rop or f.vectorequiv: 138 self.printRenderFunction(f) 139 elif f.glx_sop or f.glx_vendorpriv: 140 if len(f.get_images()) == 0: 141 self.printSingleFunction(f, name) 142 else: 143 print "/* Missing GLX protocol for %s. */" % (name) 144 145 print '}' 146 print '' 147 return 148 149 150 def swap_name(self, bytes): 151 return 'bswap_%u_array' % (8 * bytes) 152 153 154 def emit_swap_wrappers(self, api): 155 self.type_map = {} 156 already_done = [ ] 157 158 for t in api.typeIterate(): 159 te = t.get_type_expression() 160 t_size = te.get_element_size() 161 162 if t_size > 1 and t.glx_name: 163 164 t_name = "GL" + t.name 165 self.type_map[ t_name ] = t.glx_name 166 167 if t.glx_name not in already_done: 168 real_name = self.real_types[t_size] 169 170 print 'static _X_UNUSED %s' % (t_name) 171 print 'bswap_%s(const void * src)' % (t.glx_name) 172 print '{' 173 print ' union { %s dst; %s ret; } x;' % (real_name, t_name) 174 print ' x.dst = bswap_%u(*(%s *) src);' % (t_size * 8, real_name) 175 print ' return x.ret;' 176 print '}' 177 print '' 178 already_done.append( t.glx_name ) 179 180 for bits in [16, 32, 64]: 181 print 'static void *' 182 print 'bswap_%u_array(uint%u_t * src, unsigned count)' % (bits, bits) 183 print '{' 184 print ' unsigned i;' 185 print '' 186 print ' for (i = 0 ; i < count ; i++) {' 187 print ' uint%u_t temp = bswap_%u(src[i]);' % (bits, bits) 188 print ' src[i] = temp;' 189 print ' }' 190 print '' 191 print ' return src;' 192 print '}' 193 print '' 194 195 196 def fetch_param(self, param): 197 t = param.type_string() 198 o = param.offset 199 element_size = param.size() / param.get_element_count() 200 201 if self.do_swap and (element_size != 1): 202 if param.is_array(): 203 real_name = self.real_types[ element_size ] 204 205 swap_func = self.swap_name( element_size ) 206 return ' (%-8s)%s( (%s *) (pc + %2s), %s )' % (t, swap_func, real_name, o, param.count) 207 else: 208 t_name = param.get_base_type_string() 209 return ' (%-8s)bswap_%-7s( pc + %2s )' % (t, self.type_map[ t_name ], o) 210 else: 211 if param.is_array(): 212 return ' (%-8s)(pc + %2u)' % (t, o) 213 else: 214 return '*(%-8s *)(pc + %2u)' % (t, o) 215 216 return None 217 218 219 def emit_function_call(self, f, retval_assign, indent): 220 list = [] 221 222 for param in f.parameterIterator(): 223 if param.is_padding: 224 continue 225 226 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): 227 location = param.name 228 else: 229 location = self.fetch_param(param) 230 231 list.append( '%s %s' % (indent, location) ) 232 233 print '%s %sgl%s(%s);' % (indent, retval_assign, f.name, string.join(list, ',\n')) 234 235 236 def common_func_print_just_start(self, f, indent): 237 align64 = 0 238 need_blank = 0 239 240 241 f.calculate_offsets() 242 for param in f.parameterIterateGlxSend(): 243 # If any parameter has a 64-bit base type, then we 244 # have to do alignment magic for the while thing. 245 246 if param.is_64_bit(): 247 align64 = 1 248 249 250 # FIXME img_null_flag is over-loaded. In addition to 251 # FIXME being used for images, it is used to signify 252 # FIXME NULL data pointers for vertex buffer object 253 # FIXME related functions. Re-name it to null_data 254 # FIXME or something similar. 255 256 if param.img_null_flag: 257 print '%s const CARD32 ptr_is_null = *(CARD32 *)(pc + %s);' % (indent, param.offset - 4) 258 cond = '(ptr_is_null != 0) ? NULL : ' 259 else: 260 cond = "" 261 262 263 type_string = param.type_string() 264 265 if param.is_image(): 266 offset = f.offset_of( param.name ) 267 268 print '%s %s const %s = (%s) (%s(pc + %s));' % (indent, type_string, param.name, type_string, cond, offset) 269 270 if param.depth: 271 print '%s __GLXpixel3DHeader * const hdr = (__GLXpixel3DHeader *)(pc);' % (indent) 272 else: 273 print '%s __GLXpixelHeader * const hdr = (__GLXpixelHeader *)(pc);' % (indent) 274 275 need_blank = 1 276 elif param.is_counter or param.name in f.count_parameter_list: 277 location = self.fetch_param(param) 278 print '%s const %s %s = %s;' % (indent, type_string, param.name, location) 279 need_blank = 1 280 elif len(param.count_parameter_list): 281 if param.size() == 1 and not self.do_swap: 282 location = self.fetch_param(param) 283 print '%s %s %s = %s%s;' % (indent, type_string, param.name, cond, location) 284 else: 285 print '%s %s %s;' % (indent, type_string, param.name) 286 need_blank = 1 287 288 289 290 if need_blank: 291 print '' 292 293 if align64: 294 print '#ifdef __GLX_ALIGN64' 295 296 if f.has_variable_size_request(): 297 self.emit_packet_size_calculation(f, 4) 298 s = "cmdlen" 299 else: 300 s = str((f.command_fixed_length() + 3) & ~3) 301 302 print ' if ((unsigned long)(pc) & 7) {' 303 print ' (void) memmove(pc-4, pc, %s);' % (s) 304 print ' pc -= 4;' 305 print ' }' 306 print '#endif' 307 print '' 308 309 310 need_blank = 0 311 if self.do_swap: 312 for param in f.parameterIterateGlxSend(): 313 if param.count_parameter_list: 314 o = param.offset 315 count = param.get_element_count() 316 type_size = param.size() / count 317 318 if param.counter: 319 count_name = param.counter 320 else: 321 count_name = str(count) 322 323 # This is basically an ugly special- 324 # case for glCallLists. 325 326 if type_size == 1: 327 x = [] 328 x.append( [1, ['BYTE', 'UNSIGNED_BYTE', '2_BYTES', '3_BYTES', '4_BYTES']] ) 329 x.append( [2, ['SHORT', 'UNSIGNED_SHORT']] ) 330 x.append( [4, ['INT', 'UNSIGNED_INT', 'FLOAT']] ) 331 332 print ' switch(%s) {' % (param.count_parameter_list[0]) 333 for sub in x: 334 for t_name in sub[1]: 335 print ' case GL_%s:' % (t_name) 336 337 if sub[0] == 1: 338 print ' %s = (%s) (pc + %s); break;' % (param.name, param.type_string(), o) 339 else: 340 swap_func = self.swap_name(sub[0]) 341 print ' %s = (%s) %s( (%s *) (pc + %s), %s ); break;' % (param.name, param.type_string(), swap_func, self.real_types[sub[0]], o, count_name) 342 print ' default:' 343 print ' return;' 344 print ' }' 345 else: 346 swap_func = self.swap_name(type_size) 347 compsize = self.size_call(f, 1) 348 print ' %s = (%s) %s( (%s *) (pc + %s), %s );' % (param.name, param.type_string(), swap_func, self.real_types[type_size], o, compsize) 349 350 need_blank = 1 351 352 else: 353 for param in f.parameterIterateGlxSend(): 354 if param.count_parameter_list: 355 print '%s %s = (%s) (pc + %s);' % (indent, param.name, param.type_string(), param.offset) 356 need_blank = 1 357 358 359 if need_blank: 360 print '' 361 362 363 return 364 365 366 def printSingleFunction(self, f, name): 367 if name not in f.glx_vendorpriv_names: 368 print ' xGLXSingleReq * const req = (xGLXSingleReq *) pc;' 369 else: 370 print ' xGLXVendorPrivateReq * const req = (xGLXVendorPrivateReq *) pc;' 371 372 print ' int error;' 373 374 if self.do_swap: 375 print ' __GLXcontext * const cx = __glXForceCurrent(cl, bswap_CARD32( &req->contextTag ), &error);' 376 else: 377 print ' __GLXcontext * const cx = __glXForceCurrent(cl, req->contextTag, &error);' 378 379 print '' 380 if name not in f.glx_vendorpriv_names: 381 print ' pc += __GLX_SINGLE_HDR_SIZE;' 382 else: 383 print ' pc += __GLX_VENDPRIV_HDR_SIZE;' 384 385 print ' if ( cx != NULL ) {' 386 self.common_func_print_just_start(f, " ") 387 388 389 if f.return_type != 'void': 390 print ' %s retval;' % (f.return_type) 391 retval_string = "retval" 392 retval_assign = "retval = " 393 else: 394 retval_string = "0" 395 retval_assign = "" 396 397 398 type_size = 0 399 answer_string = "dummy_answer" 400 answer_count = "0" 401 is_array_string = "GL_FALSE" 402 403 for param in f.parameterIterateOutputs(): 404 answer_type = param.get_base_type_string() 405 if answer_type == "GLvoid": 406 answer_type = "GLubyte" 407 408 409 c = param.get_element_count() 410 type_size = (param.size() / c) 411 if type_size == 1: 412 size_scale = "" 413 else: 414 size_scale = " * %u" % (type_size) 415 416 417 if param.count_parameter_list: 418 print ' const GLuint compsize = %s;' % (self.size_call(f, 1)) 419 print ' %s answerBuffer[200];' % (answer_type) 420 print ' %s %s = __glXGetAnswerBuffer(cl, compsize%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, size_scale, type_size ) 421 answer_string = param.name 422 answer_count = "compsize" 423 424 print '' 425 print ' if (%s == NULL) return BadAlloc;' % (param.name) 426 print ' __glXClearErrorOccured();' 427 print '' 428 elif param.counter: 429 print ' %s answerBuffer[200];' % (answer_type) 430 print ' %s %s = __glXGetAnswerBuffer(cl, %s%s, answerBuffer, sizeof(answerBuffer), %u);' % (param.type_string(), param.name, param.counter, size_scale, type_size) 431 answer_string = param.name 432 answer_count = param.counter 433 print '' 434 print ' if (%s == NULL) return BadAlloc;' % (param.name) 435 print ' __glXClearErrorOccured();' 436 print '' 437 elif c >= 1: 438 print ' %s %s[%u];' % (answer_type, param.name, c) 439 answer_string = param.name 440 answer_count = "%u" % (c) 441 442 if f.reply_always_array: 443 is_array_string = "GL_TRUE" 444 445 446 self.emit_function_call(f, retval_assign, " ") 447 448 449 if f.needs_reply(): 450 if self.do_swap: 451 for param in f.parameterIterateOutputs(): 452 c = param.get_element_count() 453 type_size = (param.size() / c) 454 455 if type_size > 1: 456 swap_name = self.swap_name( type_size ) 457 print ' (void) %s( (uint%u_t *) %s, %s );' % (swap_name, 8 * type_size, param.name, answer_count) 458 459 460 reply_func = '__glXSendReplySwap' 461 else: 462 reply_func = '__glXSendReply' 463 464 print ' %s(cl->client, %s, %s, %u, %s, %s);' % (reply_func, answer_string, answer_count, type_size, is_array_string, retval_string) 465 #elif f.note_unflushed: 466 # print ' cx->hasUnflushedCommands = GL_TRUE;' 467 468 print ' error = Success;' 469 print ' }' 470 print '' 471 print ' return error;' 472 return 473 474 475 def printRenderFunction(self, f): 476 # There are 4 distinct phases in a rendering dispatch function. 477 # In the first phase we compute the sizes and offsets of each 478 # element in the command. In the second phase we (optionally) 479 # re-align 64-bit data elements. In the third phase we 480 # (optionally) byte-swap array data. Finally, in the fourth 481 # phase we actually dispatch the function. 482 483 self.common_func_print_just_start(f, "") 484 485 images = f.get_images() 486 if len(images): 487 if self.do_swap: 488 pre = "bswap_CARD32( & " 489 post = " )" 490 else: 491 pre = "" 492 post = "" 493 494 img = images[0] 495 496 # swapBytes and lsbFirst are single byte fields, so 497 # the must NEVER be byte-swapped. 498 499 if not (img.img_type == "GL_BITMAP" and img.img_format == "GL_COLOR_INDEX"): 500 print ' glPixelStorei(GL_UNPACK_SWAP_BYTES, hdr->swapBytes);' 501 502 print ' glPixelStorei(GL_UNPACK_LSB_FIRST, hdr->lsbFirst);' 503 504 print ' glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint) %shdr->rowLength%s);' % (pre, post) 505 if img.depth: 506 print ' glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, (GLint) %shdr->imageHeight%s);' % (pre, post) 507 print ' glPixelStorei(GL_UNPACK_SKIP_ROWS, (GLint) %shdr->skipRows%s);' % (pre, post) 508 if img.depth: 509 print ' glPixelStorei(GL_UNPACK_SKIP_IMAGES, (GLint) %shdr->skipImages%s);' % (pre, post) 510 print ' glPixelStorei(GL_UNPACK_SKIP_PIXELS, (GLint) %shdr->skipPixels%s);' % (pre, post) 511 print ' glPixelStorei(GL_UNPACK_ALIGNMENT, (GLint) %shdr->alignment%s);' % (pre, post) 512 print '' 513 514 515 self.emit_function_call(f, "", "") 516 return 517 518 519def _parser(): 520 """Parse any arguments passed and return a namespace.""" 521 parser = argparse.ArgumentParser() 522 parser.add_argument('-f', 523 dest='filename', 524 default='gl_API.xml', 525 help='an xml file describing an OpenGL API') 526 parser.add_argument('-m', 527 dest='mode', 528 default='dispatch_c', 529 choices=['dispatch_c', 'dispatch_h'], 530 help='what file to generate') 531 parser.add_argument('-s', 532 dest='swap', 533 action='store_true', 534 help='emit swap in GlXDispatchFunctions') 535 return parser.parse_args() 536 537 538def main(): 539 """Main function.""" 540 args = _parser() 541 542 if args.mode == "dispatch_c": 543 printer = PrintGlxDispatchFunctions(args.swap) 544 elif args.mode == "dispatch_h": 545 printer = PrintGlxDispatch_h() 546 547 api = gl_XML.parse_GL_API( 548 args.filename, glX_proto_common.glx_proto_item_factory()) 549 550 printer.Print(api) 551 552 553if __name__ == '__main__': 554 main() 555