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