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