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 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, str[i:i+3].lower()) 41 i = i + 2; 42 elif str[i].isupper(): 43 tmp = '%s_%s' % (tmp, str[i].lower()) 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 = sorted(procs.keys()) 393 for i in range(len(names)): 394 comma = ',' if i < len(names) - 1 else '' 395 print(' { "%s", (_glapi_proc) gl%s }%s' % (names[i], procs[names[i]], comma)) 396 print("""}; 397 398static int 399__indirect_get_proc_compare(const void *key, const void *memb) 400{ 401 const struct proc_pair *pair = (const struct proc_pair *) memb; 402 return strcmp((const char *) key, pair->name); 403} 404 405_glapi_proc 406__indirect_get_proc_address(const char *name) 407{ 408 const struct proc_pair *pair; 409 410 /* skip "gl" */ 411 name += 2; 412 413 pair = (const struct proc_pair *) bsearch((const void *) name, 414 (const void *) proc_pairs, ARRAY_SIZE(proc_pairs), sizeof(proc_pairs[0]), 415 __indirect_get_proc_compare); 416 417 return (pair) ? pair->proc : NULL; 418} 419 420#endif /* GLX_INDIRECT_RENDERING */ 421""") 422 return 423 424 425 def printFunction(self, func, name): 426 footer = '}\n' 427 if func.glx_rop == ~0: 428 print('static %s' % (func.return_type)) 429 print('%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())) 430 print('{') 431 else: 432 if func.has_different_protocol(name): 433 if func.return_type == "void": 434 ret_string = '' 435 else: 436 ret_string = "return " 437 438 func_name = func.static_glx_name(name) 439 print('#define %s %d' % (func.opcode_vendor_name(name), func.glx_vendorpriv)) 440 print('%s gl%s(%s)' % (func.return_type, func_name, func.get_parameter_string())) 441 print('{') 442 print('#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)') 443 print(' if (((struct glx_context *)__glXGetCurrentContext())->isDirect) {') 444 print(' const _glapi_proc *const disp_table = (_glapi_proc *)GET_DISPATCH();') 445 print(' PFNGL%sPROC p =' % (name.upper())) 446 print(' (PFNGL%sPROC) disp_table[%d];' % (name.upper(), func.offset)) 447 print(' %sp(%s);' % (ret_string, func.get_called_parameter_string())) 448 print(' } else') 449 print('#endif') 450 print(' {') 451 452 footer = '}\n}\n' 453 else: 454 print('#define %s %d' % (func.opcode_name(), func.opcode_value())) 455 456 print('%s __indirect_gl%s(%s)' % (func.return_type, name, func.get_parameter_string())) 457 print('{') 458 459 460 if func.glx_rop != 0 or func.vectorequiv != None: 461 if len(func.images): 462 self.printPixelFunction(func) 463 else: 464 self.printRenderFunction(func) 465 elif func.glx_sop != 0 or func.glx_vendorpriv != 0: 466 self.printSingleFunction(func, name) 467 pass 468 else: 469 print("/* Missing GLX protocol for %s. */" % (name)) 470 471 print(footer) 472 return 473 474 475 def print_generic_function(self, n): 476 size = (n + 3) & ~3 477 print("""static FASTCALL NOINLINE void 478generic_%u_byte( GLint rop, const void * ptr ) 479{ 480 struct glx_context * const gc = __glXGetCurrentContext(); 481 const GLuint cmdlen = %u; 482 483 emit_header(gc->pc, rop, cmdlen); 484 (void) memcpy((void *)(gc->pc + 4), ptr, %u); 485 gc->pc += cmdlen; 486 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); } 487} 488""" % (n, size + 4, size)) 489 return 490 491 492 def common_emit_one_arg(self, p, pc, adjust, extra_offset): 493 if p.is_array(): 494 src_ptr = p.name 495 else: 496 src_ptr = "&" + p.name 497 498 if p.is_padding: 499 print('(void) memset((void *)(%s + %u), 0, %s);' \ 500 % (pc, p.offset + adjust, p.size_string() )) 501 elif not extra_offset: 502 print('(void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \ 503 % (pc, p.offset + adjust, src_ptr, p.size_string() )) 504 else: 505 print('(void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \ 506 % (pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() )) 507 508 def common_emit_args(self, f, pc, adjust, skip_vla): 509 extra_offset = None 510 511 for p in f.parameterIterateGlxSend( not skip_vla ): 512 if p.name != f.img_reset: 513 self.common_emit_one_arg(p, pc, adjust, extra_offset) 514 515 if p.is_variable_length(): 516 temp = p.size_string() 517 if extra_offset: 518 extra_offset += " + %s" % (temp) 519 else: 520 extra_offset = temp 521 522 return 523 524 525 def pixel_emit_args(self, f, pc, large): 526 """Emit the arguments for a pixel function. This differs from 527 common_emit_args in that pixel functions may require padding 528 be inserted (i.e., for the missing width field for 529 TexImage1D), and they may also require a 'NULL image' flag 530 be inserted before the image data.""" 531 532 if large: 533 adjust = 8 534 else: 535 adjust = 4 536 537 for param in f.parameterIterateGlxSend(): 538 if not param.is_image(): 539 self.common_emit_one_arg(param, pc, adjust, None) 540 541 if f.pad_after(param): 542 print('(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset + param.size()) + adjust)) 543 544 else: 545 [dim, width, height, depth, extent] = param.get_dimensions() 546 if f.glx_rop == ~0: 547 dim_str = "dim" 548 else: 549 dim_str = str(dim) 550 551 if param.is_padding: 552 print('(void) memset((void *)(%s + %u), 0, %s);' \ 553 % (pc, (param.offset - 4) + adjust, param.size_string() )) 554 555 if param.img_null_flag: 556 if large: 557 print('(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset - 4) + adjust)) 558 else: 559 print('(void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (pc, (param.offset - 4) + adjust, param.name)) 560 561 562 pixHeaderPtr = "%s + %u" % (pc, adjust) 563 pcPtr = "%s + %u" % (pc, param.offset + adjust) 564 565 if not large: 566 if param.img_send_null: 567 condition = '(compsize > 0) && (%s != NULL)' % (param.name) 568 else: 569 condition = 'compsize > 0' 570 571 print('if (%s) {' % (condition)) 572 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)) 573 print('} else {') 574 print(' (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (pixHeaderPtr, dim, dim)) 575 print('}') 576 else: 577 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)) 578 579 return 580 581 582 def large_emit_begin(self, f, op_name = None): 583 if not op_name: 584 op_name = f.opcode_real_name() 585 586 print('const GLint op = %s;' % (op_name)) 587 print('const GLuint cmdlenLarge = cmdlen + 4;') 588 print('GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);') 589 print('(void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);') 590 print('(void) memcpy((void *)(pc + 4), (void *)(&op), 4);') 591 return 592 593 594 def common_func_print_just_start(self, f, name): 595 print(' struct glx_context * const gc = __glXGetCurrentContext();') 596 597 # The only reason that single and vendor private commands need 598 # a variable called 'dpy' is because they use the SyncHandle 599 # macro. For whatever brain-dead reason, that macro is hard- 600 # coded to use a variable called 'dpy' instead of taking a 601 # parameter. 602 603 # FIXME Simplify the logic related to skip_condition and 604 # FIXME condition_list in this function. Basically, remove 605 # FIXME skip_condition, and just append the "dpy != NULL" type 606 # FIXME condition to condition_list from the start. The only 607 # FIXME reason it's done in this confusing way now is to 608 # FIXME minimize the diffs in the generated code. 609 610 if not f.glx_rop: 611 for p in f.parameterIterateOutputs(): 612 if p.is_image() and (p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP"): 613 print(' const __GLXattribute * const state = gc->client_state_private;') 614 break 615 616 print(' Display * const dpy = gc->currentDpy;') 617 skip_condition = "dpy != NULL" 618 elif f.can_be_large: 619 skip_condition = "gc->currentDpy != NULL" 620 else: 621 skip_condition = None 622 623 624 if f.return_type != 'void': 625 print(' %s retval = (%s) 0;' % (f.return_type, f.return_type)) 626 627 628 if name != None and name not in f.glx_vendorpriv_names: 629 print('#ifndef USE_XCB') 630 self.emit_packet_size_calculation(f, 0) 631 if name != None and name not in f.glx_vendorpriv_names: 632 print('#endif') 633 634 if f.command_variable_length() != "": 635 print(" if (0%s < 0) {" % f.command_variable_length()) 636 print(" __glXSetError(gc, GL_INVALID_VALUE);") 637 if f.return_type != 'void': 638 print(" return 0;") 639 else: 640 print(" return;") 641 print(" }") 642 643 condition_list = [] 644 for p in f.parameterIterateCounters(): 645 condition_list.append( "%s >= 0" % (p.name) ) 646 # 'counter' parameters cannot be negative 647 print(" if (%s < 0) {" % p.name) 648 print(" __glXSetError(gc, GL_INVALID_VALUE);") 649 if f.return_type != 'void': 650 print(" return 0;") 651 else: 652 print(" return;") 653 print(" }") 654 655 if skip_condition: 656 condition_list.append( skip_condition ) 657 658 if len( condition_list ) > 0: 659 if len( condition_list ) > 1: 660 skip_condition = "(%s)" % ") && (".join( condition_list ) 661 else: 662 skip_condition = "%s" % (condition_list.pop(0)) 663 664 print(' if (__builtin_expect(%s, 1)) {' % (skip_condition)) 665 return 1 666 else: 667 return 0 668 669 670 def printSingleFunction(self, f, name): 671 self.common_func_print_just_start(f, name) 672 673 if self.debug: 674 print(' printf( "Enter %%s...\\n", "gl%s" );' % (f.name)) 675 676 if name not in f.glx_vendorpriv_names: 677 678 # XCB specific: 679 print('#ifdef USE_XCB') 680 if self.debug: 681 print(' printf("\\tUsing XCB.\\n");') 682 print(' xcb_connection_t *c = XGetXCBConnection(dpy);') 683 print(' (void) __glXFlushRenderBuffer(gc, gc->pc);') 684 xcb_name = 'xcb_glx%s' % convertStringForXCB(name) 685 686 iparams=[] 687 extra_iparams = [] 688 output = None 689 for p in f.parameterIterator(): 690 if p.is_output: 691 output = p 692 693 if p.is_image(): 694 if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP": 695 extra_iparams.append("state->storePack.swapEndian") 696 else: 697 extra_iparams.append("0") 698 699 # Hardcode this in. lsb_first param (apparently always GL_FALSE) 700 # also present in GetPolygonStipple, but taken care of above. 701 if xcb_name == "xcb_glx_read_pixels": 702 extra_iparams.append("0") 703 else: 704 iparams.append(p.name) 705 706 707 xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams)) 708 709 if f.needs_reply(): 710 print(' %s_reply_t *reply = %s_reply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request)) 711 if output: 712 if output.is_image(): 713 [dim, w, h, d, junk] = output.get_dimensions() 714 if f.dimensions_in_reply: 715 w = "reply->width" 716 h = "reply->height" 717 d = "reply->depth" 718 if dim < 2: 719 h = "1" 720 else: 721 print(' if (%s == 0) { %s = 1; }' % (h, h)) 722 if dim < 3: 723 d = "1" 724 else: 725 print(' if (%s == 0) { %s = 1; }' % (d, d)) 726 727 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)) 728 else: 729 if f.reply_always_array: 730 print(' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())) 731 else: 732 print(' /* the XXX_data_length() xcb function name is misleading, it returns the number */') 733 print(' /* of elements, not the length of the data part. A single element is embedded. */') 734 print(' if (%s_data_length(reply) == 1)' % (xcb_name)) 735 print(' (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)) 736 print(' else') 737 print(' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())) 738 739 if f.return_type != 'void': 740 print(' retval = reply->ret_val;') 741 print(' free(reply);') 742 else: 743 print(' ' + xcb_request + ';') 744 print('#else') 745 # End of XCB specific. 746 747 748 if f.parameters != []: 749 pc_decl = "GLubyte const * pc =" 750 else: 751 pc_decl = "(void)" 752 753 if name in f.glx_vendorpriv_names: 754 print(' %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_vendor_name(name))) 755 else: 756 print(' %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())) 757 758 self.common_emit_args(f, "pc", 0, 0) 759 760 images = f.get_images() 761 762 for img in images: 763 if img.is_output: 764 o = f.command_fixed_length() - 4 765 print(' *(int32_t *)(pc + %u) = 0;' % (o)) 766 if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP": 767 print(' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)) 768 769 if f.img_reset: 770 print(' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)) 771 772 773 return_name = '' 774 if f.needs_reply(): 775 if f.return_type != 'void': 776 return_name = " retval" 777 return_str = " retval = (%s)" % (f.return_type) 778 else: 779 return_str = " (void)" 780 781 got_reply = 0 782 783 for p in f.parameterIterateOutputs(): 784 if p.is_image(): 785 [dim, w, h, d, junk] = p.get_dimensions() 786 if f.dimensions_in_reply: 787 print(" __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)) 788 else: 789 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)) 790 791 got_reply = 1 792 else: 793 if f.reply_always_array: 794 aa = "GL_TRUE" 795 else: 796 aa = "GL_FALSE" 797 798 # gl_parameter.size() returns the size 799 # of the entire data item. If the 800 # item is a fixed-size array, this is 801 # the size of the whole array. This 802 # is not what __glXReadReply wants. It 803 # wants the size of a single data 804 # element in the reply packet. 805 # Dividing by the array size (1 for 806 # non-arrays) gives us this. 807 808 s = p.size() // p.get_element_count() 809 print(" %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)) 810 got_reply = 1 811 812 813 # If a reply wasn't read to fill an output parameter, 814 # read a NULL reply to get the return value. 815 816 if not got_reply: 817 print(" %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)) 818 819 820 elif self.debug: 821 # Only emit the extra glFinish call for functions 822 # that don't already require a reply from the server. 823 print(' __indirect_glFinish();') 824 825 if self.debug: 826 print(' printf( "Exit %%s.\\n", "gl%s" );' % (name)) 827 828 829 print(' UnlockDisplay(dpy); SyncHandle();') 830 831 if name not in f.glx_vendorpriv_names: 832 print('#endif /* USE_XCB */') 833 834 print(' }') 835 print(' return%s;' % (return_name)) 836 return 837 838 839 def printPixelFunction(self, f): 840 if f.name in self.pixel_stubs: 841 # Normally gl_function::get_parameter_string could be 842 # used. However, this call needs to have the missing 843 # dimensions (e.g., a fake height value for 844 # glTexImage1D) added in. 845 846 p_string = "" 847 for param in f.parameterIterateGlxSend(): 848 if param.is_padding: 849 continue 850 851 p_string += ", " + param.name 852 853 if param.is_image(): 854 [dim, junk, junk, junk, junk] = param.get_dimensions() 855 856 if f.pad_after(param): 857 p_string += ", 1" 858 859 print(' %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)) 860 return 861 862 863 if self.common_func_print_just_start(f, None): 864 trailer = " }" 865 else: 866 trailer = None 867 868 869 if f.can_be_large: 870 print('if (cmdlen <= gc->maxSmallRenderCommandSize) {') 871 print(' if ( (gc->pc + cmdlen) > gc->bufEnd ) {') 872 print(' (void) __glXFlushRenderBuffer(gc, gc->pc);') 873 print(' }') 874 875 if f.glx_rop == ~0: 876 opcode = "opcode" 877 else: 878 opcode = f.opcode_real_name() 879 880 print('emit_header(gc->pc, %s, cmdlen);' % (opcode)) 881 882 self.pixel_emit_args( f, "gc->pc", 0 ) 883 print('gc->pc += cmdlen;') 884 print('if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }') 885 886 if f.can_be_large: 887 print('}') 888 print('else {') 889 890 self.large_emit_begin(f, opcode) 891 self.pixel_emit_args(f, "pc", 1) 892 893 print('}') 894 895 if trailer: print(trailer) 896 return 897 898 899 def printRenderFunction(self, f): 900 # There is a class of GL functions that take a single pointer 901 # as a parameter. This pointer points to a fixed-size chunk 902 # of data, and the protocol for this functions is very 903 # regular. Since they are so regular and there are so many 904 # of them, special case them with generic functions. On 905 # x86, this saves about 26KB in the libGL.so binary. 906 907 if f.variable_length_parameter() == None and len(f.parameters) == 1: 908 p = f.parameters[0] 909 if p.is_pointer(): 910 cmdlen = f.command_fixed_length() 911 if cmdlen in self.generic_sizes: 912 print(' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)) 913 return 914 915 if self.common_func_print_just_start(f, None): 916 trailer = " }" 917 else: 918 trailer = None 919 920 if self.debug: 921 print('printf( "Enter %%s...\\n", "gl%s" );' % (f.name)) 922 923 if f.can_be_large: 924 print('if (cmdlen <= gc->maxSmallRenderCommandSize) {') 925 print(' if ( (gc->pc + cmdlen) > gc->bufEnd ) {') 926 print(' (void) __glXFlushRenderBuffer(gc, gc->pc);') 927 print(' }') 928 929 print('emit_header(gc->pc, %s, cmdlen);' % (f.opcode_real_name())) 930 931 self.common_emit_args(f, "gc->pc", 4, 0) 932 print('gc->pc += cmdlen;') 933 print('if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }') 934 935 if f.can_be_large: 936 print('}') 937 print('else {') 938 939 self.large_emit_begin(f) 940 self.common_emit_args(f, "pc", 8, 1) 941 942 p = f.variable_length_parameter() 943 print(' __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (p.offset + 8, p.name, p.size_string())) 944 print('}') 945 946 if self.debug: 947 print('__indirect_glFinish();') 948 print('printf( "Exit %%s.\\n", "gl%s" );' % (f.name)) 949 950 if trailer: print(trailer) 951 return 952 953 954class PrintGlxProtoInit_c(gl_XML.gl_print_base): 955 def __init__(self): 956 gl_XML.gl_print_base.__init__(self) 957 958 self.name = "glX_proto_send.py (from Mesa)" 959 self.license = license.bsd_license_template % ( \ 960"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 961(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 962 return 963 964 965 def printRealHeader(self): 966 print("""/** 967 * \\file indirect_init.c 968 * Initialize indirect rendering dispatch table. 969 * 970 * \\author Kevin E. Martin <kevin@precisioninsight.com> 971 * \\author Brian Paul <brian@precisioninsight.com> 972 * \\author Ian Romanick <idr@us.ibm.com> 973 */ 974 975#include "indirect_init.h" 976#include "indirect.h" 977#include "glapi.h" 978#include <assert.h> 979 980#ifndef GLX_USE_APPLEGL 981 982/** 983 * No-op function used to initialize functions that have no GLX protocol 984 * support. 985 */ 986static int NoOp(void) 987{ 988 return 0; 989} 990 991/** 992 * Create and initialize a new GL dispatch table. The table is initialized 993 * with GLX indirect rendering protocol functions. 994 */ 995struct _glapi_table * __glXNewIndirectAPI( void ) 996{ 997 _glapi_proc *table; 998 unsigned entries; 999 unsigned i; 1000 int o; 1001 1002 entries = _glapi_get_dispatch_table_size(); 1003 table = malloc(entries * sizeof(_glapi_proc)); 1004 if (table == NULL) 1005 return NULL; 1006 1007 /* first, set all entries to point to no-op functions */ 1008 for (i = 0; i < entries; i++) { 1009 table[i] = (_glapi_proc) NoOp; 1010 } 1011 1012 /* now, initialize the entries we understand */""") 1013 1014 def printRealFooter(self): 1015 print(""" 1016 return (struct _glapi_table *) table; 1017} 1018 1019#endif 1020""") 1021 return 1022 1023 1024 def printBody(self, api): 1025 for [name, number] in api.categoryIterate(): 1026 if number != None: 1027 preamble = '\n /* %3u. %s */\n' % (int(number), name) 1028 else: 1029 preamble = '\n /* %s */\n' % (name) 1030 1031 for func in api.functionIterateByCategory(name): 1032 if func.client_supported_for_indirect(): 1033 if preamble: 1034 print(preamble) 1035 preamble = None 1036 1037 if func.is_abi(): 1038 print(' table[{offset}] = (_glapi_proc) __indirect_gl{name};'.format(name = func.name, offset = func.offset)) 1039 else: 1040 print(' o = _glapi_get_proc_offset("gl{0}");'.format(func.name)) 1041 print(' assert(o > 0);') 1042 print(' table[o] = (_glapi_proc) __indirect_gl{0};'.format(func.name)) 1043 1044 return 1045 1046 1047class PrintGlxProtoInit_h(gl_XML.gl_print_base): 1048 def __init__(self): 1049 gl_XML.gl_print_base.__init__(self) 1050 1051 self.name = "glX_proto_send.py (from Mesa)" 1052 self.license = license.bsd_license_template % ( \ 1053"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 1054(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 1055 self.header_tag = "_INDIRECT_H_" 1056 1057 self.last_category = "" 1058 return 1059 1060 1061 def printRealHeader(self): 1062 print("""/** 1063 * \\file 1064 * Prototypes for indirect rendering functions. 1065 * 1066 * \\author Kevin E. Martin <kevin@precisioninsight.com> 1067 * \\author Ian Romanick <idr@us.ibm.com> 1068 */ 1069""") 1070 self.printFastcall() 1071 self.printNoinline() 1072 1073 print(""" 1074#include <X11/Xfuncproto.h> 1075#include "glxclient.h" 1076 1077extern _X_HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size, 1078 void * dest, GLboolean reply_is_always_array ); 1079 1080extern _X_HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy, 1081 struct glx_context * gc, unsigned max_dim, GLint width, GLint height, 1082 GLint depth, GLenum format, GLenum type, void * dest, 1083 GLboolean dimensions_in_reply ); 1084 1085extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest( 1086 struct glx_context * gc, GLint sop, GLint cmdlen ); 1087 1088extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest( 1089 struct glx_context * gc, GLint code, GLint vop, GLint cmdlen ); 1090""") 1091 1092 1093 def printBody(self, api): 1094 for func in api.functionIterateGlx(): 1095 params = func.get_parameter_string() 1096 1097 print('extern _X_HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params)) 1098 1099 for n in func.entry_points: 1100 if func.has_different_protocol(n): 1101 asdf = func.static_glx_name(n) 1102 if asdf not in func.static_entry_points: 1103 print('extern _X_HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params)) 1104 # give it a easy-to-remember name 1105 if func.client_handcode: 1106 print('#define gl_dispatch_stub_%s gl%s' % (n, asdf)) 1107 else: 1108 print('GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params)) 1109 1110 break 1111 1112 print('') 1113 print('#ifdef GLX_INDIRECT_RENDERING') 1114 print('extern _X_HIDDEN void (*__indirect_get_proc_address(const char *name))(void);') 1115 print('#endif') 1116 1117 1118def _parser(): 1119 """Parse input and returned a parsed namespace.""" 1120 parser = argparse.ArgumentParser() 1121 parser.add_argument('-f', 1122 default='gl_API.xml', 1123 dest='filename', 1124 help='An XML file describing an API') 1125 parser.add_argument('-m', 1126 required=True, 1127 dest='mode', 1128 choices=frozenset(['proto', 'init_c', 'init_h']), 1129 help='which file to generate') 1130 parser.add_argument('-d', 1131 action='store_true', 1132 dest='debug', 1133 help='turn debug mode on.') 1134 return parser.parse_args() 1135 1136 1137def main(): 1138 """Main function.""" 1139 args = _parser() 1140 1141 if args.mode == "proto": 1142 printer = PrintGlxProtoStubs() 1143 elif args.mode == "init_c": 1144 printer = PrintGlxProtoInit_c() 1145 elif args.mode == "init_h": 1146 printer = PrintGlxProtoInit_h() 1147 1148 printer.debug = args.debug 1149 api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory()) 1150 1151 printer.Print( api ) 1152 1153 1154if __name__ == '__main__': 1155 main() 1156