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