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 <[email protected]> 27# Jeremy Kolb <[email protected]> 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 <[email protected]> 922 * \\author Brian Paul <[email protected]> 923 * \\author Ian Romanick <[email protected]> 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 int o; 952 953 entries = _glapi_get_dispatch_table_size(); 954 table = malloc(entries * sizeof(_glapi_proc)); 955 if (table == NULL) 956 return NULL; 957 958 /* first, set all entries to point to no-op functions */ 959 for (i = 0; i < entries; i++) { 960 table[i] = (_glapi_proc) NoOp; 961 } 962 963 /* now, initialize the entries we understand */""") 964 965 def printRealFooter(self): 966 print(""" 967 return (struct _glapi_table *) table; 968} 969 970#endif 971""") 972 return 973 974 975 def printBody(self, api): 976 for [name, number] in api.categoryIterate(): 977 if number != None: 978 preamble = '\n /* %3u. %s */\n' % (int(number), name) 979 else: 980 preamble = '\n /* %s */\n' % (name) 981 982 for func in api.functionIterateByCategory(name): 983 if func.client_supported_for_indirect(): 984 if preamble: 985 print(preamble) 986 preamble = None 987 988 if func.is_abi(): 989 print(' table[{offset}] = (_glapi_proc) __indirect_gl{name};'.format(name = func.name, offset = func.offset)) 990 else: 991 print(' o = _glapi_get_proc_offset("gl{0}");'.format(func.name)) 992 print(' assert(o > 0);') 993 print(' table[o] = (_glapi_proc) __indirect_gl{0};'.format(func.name)) 994 995 return 996 997 998class PrintGlxProtoInit_h(gl_XML.gl_print_base): 999 def __init__(self): 1000 gl_XML.gl_print_base.__init__(self) 1001 1002 self.name = "glX_proto_send.py (from Mesa)" 1003 self.license = license.bsd_license_template % ( \ 1004"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 1005(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 1006 self.header_tag = "_INDIRECT_H_" 1007 1008 self.last_category = "" 1009 return 1010 1011 1012 def printRealHeader(self): 1013 print("""/** 1014 * \\file 1015 * Prototypes for indirect rendering functions. 1016 * 1017 * \\author Kevin E. Martin <[email protected]> 1018 * \\author Ian Romanick <[email protected]> 1019 */ 1020""") 1021 self.printFastcall() 1022 self.printNoinline() 1023 1024 print(""" 1025#include <X11/Xfuncproto.h> 1026#include "glxclient.h" 1027 1028extern _X_HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size, 1029 void * dest, GLboolean reply_is_always_array ); 1030 1031extern _X_HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy, 1032 struct glx_context * gc, unsigned max_dim, GLint width, GLint height, 1033 GLint depth, GLenum format, GLenum type, void * dest, 1034 GLboolean dimensions_in_reply ); 1035 1036extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest( 1037 struct glx_context * gc, GLint sop, GLint cmdlen ); 1038 1039extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest( 1040 struct glx_context * gc, GLint code, GLint vop, GLint cmdlen ); 1041""") 1042 1043 1044 def printBody(self, api): 1045 for func in api.functionIterateGlx(): 1046 params = func.get_parameter_string() 1047 1048 print('extern _X_HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params)) 1049 1050 for n in func.entry_points: 1051 if func.has_different_protocol(n): 1052 asdf = func.static_glx_name(n) 1053 if asdf not in func.static_entry_points: 1054 print('extern _X_HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params)) 1055 # give it a easy-to-remember name 1056 if func.client_handcode: 1057 print('#define gl_dispatch_stub_%s gl%s' % (n, asdf)) 1058 else: 1059 print('GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params)) 1060 1061 break 1062 1063 print('') 1064 print('#ifdef GLX_INDIRECT_RENDERING') 1065 print('extern _X_HIDDEN void (*__indirect_get_proc_address(const char *name))(void);') 1066 print('#endif') 1067 1068 1069def _parser(): 1070 """Parse input and returned a parsed namespace.""" 1071 parser = argparse.ArgumentParser() 1072 parser.add_argument('-f', 1073 default='gl_API.xml', 1074 dest='filename', 1075 help='An XML file describing an API') 1076 parser.add_argument('-m', 1077 required=True, 1078 dest='mode', 1079 choices=frozenset(['proto', 'init_c', 'init_h']), 1080 help='which file to generate') 1081 parser.add_argument('-d', 1082 action='store_true', 1083 dest='debug', 1084 help='turn debug mode on.') 1085 return parser.parse_args() 1086 1087 1088def main(): 1089 """Main function.""" 1090 args = _parser() 1091 1092 if args.mode == "proto": 1093 printer = PrintGlxProtoStubs() 1094 elif args.mode == "init_c": 1095 printer = PrintGlxProtoInit_c() 1096 elif args.mode == "init_h": 1097 printer = PrintGlxProtoInit_h() 1098 1099 printer.debug = args.debug 1100 api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory()) 1101 1102 printer.Print( api ) 1103 1104 1105if __name__ == '__main__': 1106 main() 1107