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