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