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