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