glX_proto_send.py revision d863424032deb7c6bcb3a0b906be29b573f18c2d
1#!/usr/bin/python2 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 28from xml.sax import saxutils 29from xml.sax import make_parser 30from xml.sax.handler import feature_namespaces 31 32import gl_XML 33import glX_XML 34import license 35import sys, getopt, copy 36 37def hash_pixel_function(func): 38 """Generate a 'unique' key for a pixel function. The key is based on 39 the parameters written in the command packet. This includes any 40 padding that might be added for the original function and the 'NULL 41 image' flag.""" 42 43 [dim, junk, junk, junk, junk] = func.dimensions() 44 45 d = (dim + 1) & ~1 46 h = "%uD%uD_" % (d - 1, d) 47 48 for p in func.parameterIterator(1, 1): 49 h = "%s%u" % (h, p.size()) 50 51 if func.pad_after(p): 52 h += "4" 53 54 if func.image.img_null_flag: 55 h += "_NF" 56 57 n = func.name.replace("%uD" % (dim), "") 58 n = "__glx_%s_%uD%uD" % (n, d - 1, d) 59 return [h, n] 60 61 62class glXPixelFunctionUtility(glX_XML.glXFunction): 63 """Dummy class used to generate pixel "utility" functions that are 64 shared by multiple dimension image functions. For example, these 65 objects are used to generate shared functions used to send GLX 66 protocol for TexImage1D and TexImage2D, TexSubImage1D and 67 TexSubImage2D, etc.""" 68 69 def __init__(self, func, name): 70 # The parameters to the utility function are the same as the 71 # parameters to the real function except for the added "pad" 72 # parameters. 73 74 self.name = name 75 self.image = copy.copy(func.image) 76 self.fn_parameters = [] 77 for p in gl_XML.glFunction.parameterIterator(func): 78 self.fn_parameters.append(p) 79 80 pad_name = func.pad_after(p) 81 if pad_name: 82 pad = copy.copy(p) 83 pad.name = pad_name 84 self.fn_parameters.append(pad) 85 86 87 if self.image.height == None: 88 self.image.height = "height" 89 90 if self.image.img_yoff == None: 91 self.image.img_yoff = "yoffset" 92 93 if func.image.depth: 94 if self.image.extent == None: 95 self.image.extent = "extent" 96 97 if self.image.img_woff == None: 98 self.image.img_woff = "woffset" 99 100 101 self.set_return_type( func.fn_return_type ) 102 self.glx_rop = ~0 103 self.can_be_large = func.can_be_large 104 self.count_parameter_list = func.count_parameter_list 105 self.counter = func.counter 106 self.img_reset = None 107 return 108 109 110class PrintGlxProtoStubs(glX_XML.GlxProto): 111 def __init__(self): 112 glX_XML.GlxProto.__init__(self) 113 self.last_category = "" 114 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM") 115 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32] 116 self.pixel_stubs = {} 117 self.debug = 0 118 return 119 120 def printRealHeader(self): 121 print '' 122 print '#include <GL/gl.h>' 123 print '#include "indirect.h"' 124 print '#include "glxclient.h"' 125 print '#include "indirect_size.h"' 126 print '#include <GL/glxproto.h>' 127 print '' 128 print '#define __GLX_PAD(n) (((n) + 3) & ~3)' 129 print '' 130 self.printFastcall() 131 self.printNoinline() 132 print '' 133 print '#if !defined __GNUC__ || __GNUC__ < 3' 134 print '# define __builtin_expect(x, y) x' 135 print '#endif' 136 print '' 137 print '/* If the size and opcode values are known at compile-time, this will, on' 138 print ' * x86 at least, emit them with a single instruction.' 139 print ' */' 140 print '#define emit_header(dest, op, size) \\' 141 print ' do { union { short s[2]; int i; } temp; \\' 142 print ' temp.s[0] = (size); temp.s[1] = (op); \\' 143 print ' *((int *)(dest)) = temp.i; } while(0)' 144 print '' 145 print """static NOINLINE CARD32 146read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array ) 147{ 148 xGLXSingleReply reply; 149 150 (void) _XReply(dpy, (xReply *) & reply, 0, False); 151 if (size != 0) { 152 if ((reply.length > 0) || reply_is_always_array) { 153 const GLint bytes = (reply_is_always_array) 154 ? (4 * reply.length) : (reply.size * size); 155 const GLint extra = 4 - (bytes & 3); 156 157 _XRead(dpy, dest, bytes); 158 if ( extra < 4 ) { 159 _XEatData(dpy, extra); 160 } 161 } 162 else { 163 (void) memcpy( dest, &(reply.pad3), size); 164 } 165 } 166 167 return reply.retval; 168} 169 170static NOINLINE void 171read_pixel_reply( Display *dpy, __GLXcontext * gc, unsigned max_dim, 172 GLint width, GLint height, GLint depth, GLenum format, GLenum type, 173 void * dest, GLboolean dimensions_in_reply ) 174{ 175 xGLXSingleReply reply; 176 GLint size; 177 178 (void) _XReply(dpy, (xReply *) & reply, 0, False); 179 180 if ( dimensions_in_reply ) { 181 width = reply.pad3; 182 height = reply.pad4; 183 depth = reply.pad5; 184 185 if ((height == 0) || (max_dim < 2)) { height = 1; } 186 if ((depth == 0) || (max_dim < 3)) { depth = 1; } 187 } 188 189 size = reply.length * 4; 190 if (size != 0) { 191 void * buf = Xmalloc( size ); 192 193 if ( buf == NULL ) { 194 _XEatData(dpy, size); 195 __glXSetError(gc, GL_OUT_OF_MEMORY); 196 } 197 else { 198 const GLint extra = 4 - (size & 3); 199 200 _XRead(dpy, buf, size); 201 if ( extra < 4 ) { 202 _XEatData(dpy, extra); 203 } 204 205 __glEmptyImage(gc, 3, width, height, depth, format, type, 206 buf, dest); 207 Xfree(buf); 208 } 209 } 210} 211 212#define X_GLXSingle 0 213 214static NOINLINE FASTCALL GLubyte * 215setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen ) 216{ 217 xGLXSingleReq * req; 218 Display * const dpy = gc->currentDpy; 219 220 (void) __glXFlushRenderBuffer(gc, gc->pc); 221 LockDisplay(dpy); 222 GetReqExtra(GLXSingle, cmdlen, req); 223 req->reqType = gc->majorOpcode; 224 req->contextTag = gc->currentContextTag; 225 req->glxCode = sop; 226 return (GLubyte *)(req) + sz_xGLXSingleReq; 227} 228 229static NOINLINE FASTCALL GLubyte * 230setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen ) 231{ 232 xGLXVendorPrivateReq * req; 233 Display * const dpy = gc->currentDpy; 234 235 (void) __glXFlushRenderBuffer(gc, gc->pc); 236 LockDisplay(dpy); 237 GetReqExtra(GLXVendorPrivate, cmdlen, req); 238 req->reqType = gc->majorOpcode; 239 req->glxCode = code; 240 req->vendorCode = vop; 241 req->contextTag = gc->currentContextTag; 242 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq; 243} 244 245const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 }; 246 247#define zero (__glXDefaultPixelStore+0) 248#define one (__glXDefaultPixelStore+8) 249#define default_pixel_store_1D (__glXDefaultPixelStore+4) 250#define default_pixel_store_1D_size 20 251#define default_pixel_store_2D (__glXDefaultPixelStore+4) 252#define default_pixel_store_2D_size 20 253#define default_pixel_store_3D (__glXDefaultPixelStore+0) 254#define default_pixel_store_3D_size 36 255#define default_pixel_store_4D (__glXDefaultPixelStore+0) 256#define default_pixel_store_4D_size 36 257""" 258 259 for size in self.generic_sizes: 260 self.print_generic_function(size) 261 return 262 263 def printFunction(self, f): 264 if f.client_handcode: return 265 266 if f.glx_rop != 0 or f.vectorequiv != None: 267 if f.image: 268 self.printPixelFunction(f) 269 else: 270 self.printRenderFunction(f) 271 elif f.glx_sop != 0 or f.glx_vendorpriv != 0: 272 self.printSingleFunction(f) 273 else: 274 print "/* Missing GLX protocol for %s. */" % (f.name) 275 276 def print_generic_function(self, n): 277 size = (n + 3) & ~3 278 print """static FASTCALL NOINLINE void 279generic_%u_byte( GLint rop, const void * ptr ) 280{ 281 __GLXcontext * const gc = __glXGetCurrentContext(); 282 const GLuint cmdlen = %u; 283 284 emit_header(gc->pc, rop, cmdlen); 285 (void) memcpy((void *)(gc->pc + 4), ptr, %u); 286 gc->pc += cmdlen; 287 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); } 288} 289""" % (n, size + 4, size) 290 291 292 def common_emit_one_arg(self, p, offset, pc, indent, adjust): 293 t = p.p_type 294 if p.is_array(): 295 src_ptr = p.name 296 else: 297 src_ptr = "&" + p.name 298 299 print '%s (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \ 300 % (indent, pc, offset + adjust, src_ptr, p.size_string() ) 301 302 def common_emit_args(self, f, pc, indent, adjust, skip_vla): 303 offset = 0 304 305 if skip_vla: 306 r = 1 307 else: 308 r = 2 309 310 for p in f.parameterIterator(1, r): 311 if p.name != f.img_reset: 312 self.common_emit_one_arg(p, offset, pc, indent, adjust) 313 offset += p.size() 314 315 return offset 316 317 318 def pixel_emit_args(self, f, pc, indent, adjust, dim, large): 319 """Emit the arguments for a pixel function. This differs from 320 common_emit_args in that pixel functions may require padding 321 be inserted (i.e., for the missing width field for 322 TexImage1D), and they may also require a 'NULL image' flag 323 be inserted before the image data.""" 324 325 offset = 0 326 for p in f.parameterIterator(1, 1): 327 self.common_emit_one_arg(p, offset, pc, indent, adjust) 328 offset += p.size() 329 330 if f.pad_after(p): 331 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust) 332 offset += 4 333 334 if f.image.img_null_flag: 335 if large: 336 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust) 337 else: 338 print '%s (void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (indent, pc, offset + adjust, f.image.name) 339 340 offset += 4 341 342 return offset 343 344 345 def large_emit_begin(self, indent, f, op_name = None): 346 if not op_name: 347 op_name = f.opcode_real_name() 348 349 print '%s const GLint op = %s;' % (indent, op_name) 350 print '%s const GLuint cmdlenLarge = cmdlen + 4;' % (indent) 351 print '%s GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent) 352 print '%s (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent) 353 print '%s (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent) 354 return 355 356 357 def common_func_print_just_header(self, f): 358 print '#define %s %d' % (f.opcode_name(), f.opcode_value()) 359 360 print '%s' % (f.fn_return_type) 361 print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string()) 362 print '{' 363 364 365 def common_func_print_just_start(self, f): 366 print ' __GLXcontext * const gc = __glXGetCurrentContext();' 367 368 # The only reason that single and vendor private commands need 369 # a variable called 'dpy' is becuase they use the SyncHandle 370 # macro. For whatever brain-dead reason, that macro is hard- 371 # coded to use a variable called 'dpy' instead of taking a 372 # parameter. 373 374 if not f.glx_rop: 375 if f.image and f.image.is_output: 376 print ' const __GLXattribute * const state = gc->client_state_private;' 377 378 print ' Display * const dpy = gc->currentDpy;' 379 skip_condition = "dpy != NULL" 380 elif f.can_be_large: 381 skip_condition = "gc->currentDpy != NULL" 382 else: 383 skip_condition = None 384 385 386 if f.fn_return_type != 'void': 387 print ' %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type) 388 389 if not f.output_parameter(): 390 compsize = self.size_call( f ) 391 if compsize: 392 print ' const GLuint compsize = %s;' % (compsize) 393 394 print ' const GLuint cmdlen = %s;' % (f.command_length()) 395 396 if f.counter: 397 if skip_condition: 398 skip_condition = "(%s >= 0) && (%s)" % (f.counter, skip_condition) 399 else: 400 skip_condition = "%s >= 0" % (f.counter) 401 402 403 if skip_condition: 404 print ' if (__builtin_expect(%s, 1)) {' % (skip_condition) 405 return 1 406 else: 407 return 0 408 409 410 def common_func_print_header(self, f): 411 self.common_func_print_just_header(f) 412 return self.common_func_print_just_start(f) 413 414 415 416 def printSingleFunction(self, f): 417 self.common_func_print_header(f) 418 419 if self.debug: 420 print ' printf( "Enter %%s...\\n", "gl%s" );' % (f.name) 421 422 if f.fn_parameters != []: 423 pc_decl = "GLubyte const * pc =" 424 else: 425 pc_decl = "(void)" 426 427 if f.glx_vendorpriv != 0: 428 print ' %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name()) 429 else: 430 print ' %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name()) 431 432 self.common_emit_args(f, "pc", " ", 0, 0) 433 if f.image and f.image.is_output: 434 o = f.command_fixed_length() - 4 435 print ' *(int32_t *)(pc + %u) = 0;' % (o) 436 if f.image.img_format != "GL_COLOR_INDEX" or f.image.img_type != "GL_BITMAP": 437 print ' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o) 438 439 if f.img_reset: 440 print ' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset) 441 442 443 if f.needs_reply(): 444 if f.image and f.image.is_output: 445 [dim, w, h, d, junk] = f.dimensions() 446 if f.dimensions_in_reply: 447 print " read_pixel_reply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, f.image.img_format, f.image.img_type, f.image.name) 448 else: 449 print " read_pixel_reply(dpy, gc, %u, %s, %s, %s, %s, %s, %s, GL_FALSE);" % (dim, w, h, d, f.image.img_format, f.image.img_type, f.image.name) 450 else: 451 if f.output != None: 452 output_size = f.output.p_type.size 453 output_str = f.output.name 454 else: 455 output_size = 0 456 output_str = "NULL" 457 458 if f.fn_return_type != 'void': 459 return_str = " retval = (%s)" % (f.fn_return_type) 460 else: 461 return_str = " (void)" 462 463 if f.reply_always_array: 464 aa = "GL_TRUE" 465 else: 466 aa = "GL_FALSE" 467 468 print " %s read_reply(dpy, %s, %s, %s);" % (return_str, output_size, output_str, aa) 469 470 elif self.debug: 471 # Only emit the extra glFinish call for functions 472 # that don't already require a reply from the server. 473 print ' __indirect_glFinish();' 474 475 if self.debug: 476 print ' printf( "Exit %%s.\\n", "gl%s" );' % (f.name) 477 478 479 print ' UnlockDisplay(dpy); SyncHandle();' 480 print ' }' 481 print ' %s' % f.return_string() 482 print '}' 483 print '' 484 return 485 486 487 def printPixelFunction(self, f): 488 """This function could use some major refactoring. :(""" 489 490 # There is a code-space optimization that we can do here. 491 # Functions that are marked img_pad_dimensions have a version 492 # with an odd number of dimensions and an even number of 493 # dimensions. TexSubImage1D and TexSubImage2D are examples. 494 # We can emit a single function that does both, and have the 495 # real functions call the utility function with the correct 496 # parameters. 497 # 498 # The only quirk to this is that utility funcitons will be 499 # generated for 3D and 4D functions, but 4D (e.g., 500 # GL_SGIS_texture4D) isn't typically supported. This is 501 # probably not an issue. However, it would be possible to 502 # look at the total set of functions and determine if there 503 # is another function that would actually use the utility 504 # function. If not, then fallback to the normal way of 505 # generating code. 506 507 if f.image.img_pad_dimensions: 508 # Determine the hash key and the name for the utility 509 # function that is used to implement the real 510 # function. 511 512 [h, n] = hash_pixel_function(f) 513 514 515 # If the utility function is not yet known, generate 516 # it. 517 518 if not self.pixel_stubs.has_key(h): 519 self.pixel_stubs[h] = n 520 pixel_func = glXPixelFunctionUtility(f, n) 521 522 print 'static void' 523 print '%s( unsigned opcode, unsigned dim, %s )' % (n, pixel_func.get_parameter_string()) 524 print '{' 525 526 if self.common_func_print_just_start(pixel_func): 527 indent = " " 528 trailer = " }" 529 else: 530 indent = "" 531 trailer = None 532 533 534 if pixel_func.can_be_large: 535 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent) 536 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent) 537 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent) 538 print '%s }' % (indent) 539 indent += " " 540 541 [dim, width, height, depth, extent] = pixel_func.dimensions() 542 adjust = pixel_func.offset_of_first_parameter() + 4 543 544 print '%s emit_header(gc->pc, opcode, cmdlen);' % (indent) 545 546 offset = self.pixel_emit_args(pixel_func, "gc->pc", indent, adjust, dim, 0) 547 548 s = pixel_func.command_fixed_length() 549 550 pixHeaderPtr = "gc->pc + 4" 551 pcPtr = "gc->pc + %u" % (s + 4) 552 553 if pixel_func.image.img_send_null: 554 condition = '(compsize > 0) && (%s != NULL)' % (pixel_func.image.name) 555 else: 556 condition = 'compsize > 0' 557 558 print '%s if (%s) {' % (indent, condition) 559 print '%s (*gc->fillImage)(gc, dim, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, width, height, depth, pixel_func.image.img_format, pixel_func.image.img_type, pixel_func.image.name, pcPtr, pixHeaderPtr) 560 print '%s }' % (indent) 561 print '%s else {' % (indent) 562 print '%s (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim) 563 print '%s }' % (indent) 564 565 print '%s gc->pc += cmdlen;' % (indent) 566 print '%s if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent) 567 568 if f.can_be_large: 569 adjust += 4 570 571 print '%s}' % (indent) 572 print '%selse {' % (indent) 573 574 self.large_emit_begin(indent, pixel_func, "opcode") 575 offset = self.pixel_emit_args(pixel_func, "pc", indent, adjust, dim, 1) 576 577 pixHeaderPtr = "pc + 8" 578 pcPtr = "pc + %u" % (s + 8) 579 580 print '%s __glXSendLargeImage(gc, compsize, dim, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr) 581 582 print '%s}' % (indent) 583 584 if trailer: print trailer 585 print '}' 586 print '' 587 588 589 590 # Generate the real function as a call to the 591 # utility function. 592 593 self.common_func_print_just_header(f) 594 595 [dim, junk, junk, junk, junk] = f.dimensions() 596 597 p_string = "" 598 for p in gl_XML.glFunction.parameterIterator(f): 599 p_string += ", " + p.name 600 601 if f.pad_after(p): 602 p_string += ", 1" 603 604 print ' %s(%s, %u%s );' % (n, f.opcode_name(), dim, p_string) 605 print '}' 606 print '' 607 return 608 609 610 if self.common_func_print_header(f): 611 indent = " " 612 trailer = " }" 613 else: 614 indent = "" 615 trailer = None 616 617 618 if f.can_be_large: 619 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent) 620 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent) 621 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent) 622 print '%s }' % (indent) 623 indent += " " 624 625 [dim, width, height, depth, extent] = f.dimensions() 626 adjust = f.offset_of_first_parameter() + 4 627 628 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name()) 629 630 offset = self.pixel_emit_args(f, "gc->pc", indent, adjust, dim, 0) 631 632 s = f.command_fixed_length() 633 634 pixHeaderPtr = "gc->pc + 4" 635 pcPtr = "gc->pc + %u" % (s + 4) 636 637 if f.image.img_send_null: 638 condition = '(compsize > 0) && (%s != NULL)' % (f.image.name) 639 else: 640 condition = 'compsize > 0' 641 642 print '%s if (%s) {' % (indent, condition) 643 print '%s (*gc->fillImage)(gc, %u, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr) 644 print '%s }' % (indent) 645 print '%s else {' % (indent) 646 print '%s (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim) 647 print '%s }' % (indent) 648 649 print '%s gc->pc += cmdlen;' % (indent) 650 print '%s if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent) 651 652 if f.can_be_large: 653 adjust += 4 654 655 print '%s}' % (indent) 656 print '%selse {' % (indent) 657 658 self.large_emit_begin(indent, f) 659 offset = self.pixel_emit_args(f, "pc", indent, adjust, dim, 1) 660 661 pixHeaderPtr = "pc + 8" 662 pcPtr = "pc + %u" % (s + 8) 663 664 print '%s __glXSendLargeImage(gc, compsize, %u, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr) 665 666 print '%s}' % (indent) 667 668 if trailer: print trailer 669 print '}' 670 print '' 671 return 672 673 674 def printRenderFunction(self, f): 675 # There is a class of GL functions that take a single pointer 676 # as a parameter. This pointer points to a fixed-size chunk 677 # of data, and the protocol for this functions is very 678 # regular. Since they are so regular and there are so many 679 # of them, special case them with generic functions. On 680 # x86, this saves about 26KB in the libGL.so binary. 681 682 if f.variable_length_parameter() == None and len(f.fn_parameters) == 1: 683 p = f.fn_parameters[0] 684 if p.is_pointer: 685 cmdlen = f.command_fixed_length() 686 if cmdlen in self.generic_sizes: 687 self.common_func_print_just_header(f) 688 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name) 689 print '}' 690 print '' 691 return 692 693 if self.common_func_print_header(f): 694 indent = " " 695 trailer = " }" 696 else: 697 indent = "" 698 trailer = None 699 700 if self.debug: 701 print '%s printf( "Enter %%s...\\n", "gl%s" );' % (indent, f.name) 702 703 if f.can_be_large: 704 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent) 705 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent) 706 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent) 707 print '%s }' % (indent) 708 indent += " " 709 710 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name()) 711 712 self.common_emit_args(f, "gc->pc", indent, 4, 0) 713 print '%s gc->pc += cmdlen;' % (indent) 714 print '%s if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent) 715 716 if f.can_be_large: 717 print '%s}' % (indent) 718 print '%selse {' % (indent) 719 720 self.large_emit_begin(indent, f) 721 offset = self.common_emit_args(f, "pc", indent, 8, 1) 722 723 p = f.variable_length_parameter() 724 print '%s __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, offset + 8, p.name, p.size_string()) 725 print '%s}' % (indent) 726 727 if self.debug: 728 print '%s __indirect_glFinish();' % (indent) 729 print '%s printf( "Exit %%s.\\n", "gl%s" );' % (indent, f.name) 730 731 if trailer: print trailer 732 print '}' 733 print '' 734 return 735 736 737class PrintGlxProtoInit_c(glX_XML.GlxProto): 738 def __init__(self): 739 glX_XML.GlxProto.__init__(self) 740 self.last_category = "" 741 self.license = license.bsd_license_template % ( \ 742"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 743(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 744 745 746 def printRealHeader(self): 747 print """/** 748 * \\file indirect_init.c 749 * Initialize indirect rendering dispatch table. 750 * 751 * \\author Kevin E. Martin <kevin@precisioninsight.com> 752 * \\author Brian Paul <brian@precisioninsight.com> 753 * \\author Ian Romanick <idr@us.ibm.com> 754 */ 755 756#include "indirect_init.h" 757#include "indirect.h" 758#include "glapi.h" 759 760 761/** 762 * No-op function used to initialize functions that have no GLX protocol 763 * support. 764 */ 765static int NoOp(void) 766{ 767 return 0; 768} 769 770/** 771 * Create and initialize a new GL dispatch table. The table is initialized 772 * with GLX indirect rendering protocol functions. 773 */ 774__GLapi * __glXNewIndirectAPI( void ) 775{ 776 __GLapi *glAPI; 777 GLuint entries; 778 779 entries = _glapi_get_dispatch_table_size(); 780 glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *)); 781 782 /* first, set all entries to point to no-op functions */ 783 { 784 int i; 785 void **dispatch = (void **) glAPI; 786 for (i = 0; i < entries; i++) { 787 dispatch[i] = (void *) NoOp; 788 } 789 } 790 791 /* now, initialize the entries we understand */""" 792 793 def printRealFooter(self): 794 print """ 795 return glAPI; 796} 797""" 798 799 def printFunction(self, f): 800 if f.category != self.last_category: 801 self.last_category = f.category 802 print '' 803 print ' /* %s */' % (self.last_category) 804 print '' 805 806 print ' glAPI->%s = __indirect_gl%s;' % (f.name, f.name) 807 808 809class PrintGlxProtoInit_h(glX_XML.GlxProto): 810 def __init__(self): 811 glX_XML.GlxProto.__init__(self) 812 self.last_category = "" 813 self.license = license.bsd_license_template % ( \ 814"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 815(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 816 self.header_tag = "_INDIRECT_H_" 817 818 def printRealHeader(self): 819 print """/** 820 * \\file 821 * Prototypes for indirect rendering functions. 822 * 823 * \\author Kevin E. Martin <kevin@precisioninsight.com> 824 * \\author Ian Romanick <idr@us.ibm.com> 825 */ 826""" 827 self.printVisibility( "HIDDEN", "hidden" ) 828 829 830 def printFunction(self, f): 831 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string()) 832 833 834def show_usage(): 835 print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0] 836 print " -m output_mode Output mode can be one of 'proto', 'init_c' or 'init_h'." 837 print " -d Enable extra debug information in the generated code." 838 sys.exit(1) 839 840 841if __name__ == '__main__': 842 file_name = "gl_API.xml" 843 844 try: 845 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:d") 846 except Exception,e: 847 show_usage() 848 849 debug = 0 850 mode = "proto" 851 for (arg,val) in args: 852 if arg == "-f": 853 file_name = val 854 elif arg == "-m": 855 mode = val 856 elif arg == "-d": 857 debug = 1 858 859 if mode == "proto": 860 dh = PrintGlxProtoStubs() 861 elif mode == "init_c": 862 dh = PrintGlxProtoInit_c() 863 elif mode == "init_h": 864 dh = PrintGlxProtoInit_h() 865 else: 866 show_usage() 867 868 parser = make_parser() 869 parser.setFeature(feature_namespaces, 0) 870 parser.setContentHandler(dh) 871 872 f = open(file_name) 873 874 dh.debug = debug 875 dh.printHeader() 876 parser.parse(f) 877 dh.printFooter() 878