glX_proto_send.py revision 990dec7ea0ad9eca8340d39fd022baa151c05a03
1#!/usr/bin/python2 2 3# (C) Copyright IBM Corporation 2004 4# All Rights Reserved. 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 28from xml.sax import saxutils 29from xml.sax import make_parser 30from xml.sax.handler import feature_namespaces 31 32import gl_XML 33import glX_XML 34import license 35import sys, getopt 36 37 38class PrintGlxProtoStubs(glX_XML.GlxProto): 39 def __init__(self): 40 glX_XML.GlxProto.__init__(self) 41 self.last_category = "" 42 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM") 43 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32] 44 return 45 46 def printRealHeader(self): 47 print '' 48 print '#include <GL/gl.h>' 49 print '#include "indirect.h"' 50 print '#include "glxclient.h"' 51 print '#include "size.h"' 52 print '#include <GL/glxproto.h>' 53 print '' 54 print '#define __GLX_PAD(n) (((n) + 3) & ~3)' 55 print '' 56 glX_XML.printFastcall() 57 glX_XML.printNoinline() 58 print '' 59 print '#if !defined __GNUC__ || __GNUC__ < 3' 60 print '# define __builtin_expect(x, y) x' 61 print '#endif' 62 print '' 63 print '/* If the size and opcode values are known at compile-time, this will, on' 64 print ' * x86 at least, emit them with a single instruction.' 65 print ' */' 66 print '#define emit_header(dest, op, size) \\' 67 print ' do { union { short s[2]; int i; } temp; \\' 68 print ' temp.s[0] = (size); temp.s[1] = (op); \\' 69 print ' *((int *)(dest)) = temp.i; } while(0)' 70 print '' 71 print """static NOINLINE CARD32 72read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array ) 73{ 74 xGLXSingleReply reply; 75 76 (void) _XReply(dpy, (xReply *) & reply, 0, False); 77 if (size != 0) { 78 if ((reply.size >= 1) || reply_is_always_array) { 79 const GLint bytes = (reply_is_always_array) 80 ? (4 * reply.length) : (reply.size * size); 81 const GLint extra = 4 - (bytes & 3); 82 83 _XRead(dpy, dest, bytes); 84 if ( extra != 0 ) { 85 _XEatData(dpy, extra); 86 } 87 } 88 else { 89 (void) memcpy( dest, &(reply.pad3), size); 90 } 91 } 92 93 return reply.retval; 94} 95 96#define X_GLXSingle 0 97 98static NOINLINE FASTCALL GLubyte * 99setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen ) 100{ 101 xGLXSingleReq * req; 102 Display * const dpy = gc->currentDpy; 103 104 (void) __glXFlushRenderBuffer(gc, gc->pc); 105 LockDisplay(dpy); 106 GetReqExtra(GLXSingle, cmdlen, req); 107 req->reqType = gc->majorOpcode; 108 req->contextTag = gc->currentContextTag; 109 req->glxCode = sop; 110 return (GLubyte *)(req) + sz_xGLXSingleReq; 111} 112 113static NOINLINE FASTCALL GLubyte * 114setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen ) 115{ 116 xGLXVendorPrivateReq * req; 117 Display * const dpy = gc->currentDpy; 118 119 (void) __glXFlushRenderBuffer(gc, gc->pc); 120 LockDisplay(dpy); 121 GetReqExtra(GLXVendorPrivate, cmdlen, req); 122 req->reqType = gc->majorOpcode; 123 req->glxCode = code; 124 req->vendorCode = vop; 125 req->contextTag = gc->currentContextTag; 126 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq; 127} 128""" 129 130 for size in self.generic_sizes: 131 self.print_generic_function(size) 132 return 133 134 def printFunction(self, f): 135 if f.fn_offset < 0 or f.handcode or f.ignore: return 136 137 if f.glx_rop != 0 or f.vectorequiv != None: 138 self.printRenderFunction(f) 139 elif f.glx_sop != 0 or f.glx_vendorpriv != 0: 140 self.printSingleFunction(f) 141 else: 142 print "/* Missing GLX protocol for %s. */" % (f.name) 143 144 def print_generic_function(self, n): 145 print """static FASTCALL NOINLINE void 146generic_%u_byte( GLint rop, const void * ptr ) 147{ 148 __GLXcontext * const gc = __glXGetCurrentContext(); 149 const GLuint cmdlen = %u; 150 151 emit_header(gc->pc, rop, cmdlen); 152 (void) memcpy((void *)(gc->pc + 4), ptr, %u); 153 gc->pc += cmdlen; 154 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); } 155} 156""" % (n, n + 4, n) 157 158 159 def common_emit_one_arg(self, p, offset, pc, indent, adjust): 160 t = p.p_type 161 if p.is_array(): 162 src_ptr = p.name 163 else: 164 src_ptr = "&" + p.name 165 166 print '%s (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \ 167 % (indent, pc, offset + adjust, src_ptr, p.size_string() ) 168 169 def common_emit_args(self, f, pc, indent, adjust, skip_vla): 170 offset = 0 171 172 if skip_vla: 173 r = 1 174 else: 175 r = 2 176 177 for p in f.parameterIterator(1, r): 178 self.common_emit_one_arg(p, offset, pc, indent, adjust) 179 offset += p.size() 180 181 return offset 182 183 184 def common_func_print_just_header(self, f): 185 print '#define %s %d' % (f.opcode_name(), f.opcode_value()) 186 187 print '%s' % (f.fn_return_type) 188 print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string()) 189 print '{' 190 191 192 def common_func_print_header(self, f): 193 self.common_func_print_just_header(f) 194 195 print ' __GLXcontext * const gc = __glXGetCurrentContext();' 196 197 # The only reason that single and vendor private commands need 198 # a variable called 'dpy' is becuase they use the SyncHandle 199 # macro. For whatever brain-dead reason, that macro is hard- 200 # coded to use a variable called 'dpy' instead of taking a 201 # parameter. 202 203 if not f.glx_rop: 204 print ' Display * const dpy = gc->currentDpy;' 205 skip_condition = "dpy != NULL" 206 elif f.can_be_large: 207 skip_condition = "gc->currentDpy != NULL" 208 else: 209 skip_condition = None 210 211 212 if f.fn_return_type != 'void': 213 print ' %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type) 214 215 if f.count_parameters != None: 216 print ' const GLuint compsize = __gl%s_size(%s);' % (f.name, f.count_parameters) 217 218 print ' const GLuint cmdlen = %s;' % (f.command_length()) 219 220 if f.counter: 221 if skip_condition: 222 skip_condition = "(%s >= 0) && (%s)" % (f.counter, skip_condition) 223 else: 224 skip_condition = "%s >= 0" % (f.counter) 225 226 227 if skip_condition: 228 print ' if (__builtin_expect(%s, 1)) {' % (skip_condition) 229 return 1 230 else: 231 return 0 232 233 234 def printSingleFunction(self, f): 235 self.common_func_print_header(f) 236 237 if f.fn_parameters != []: 238 pc_decl = "GLubyte const * pc =" 239 else: 240 pc_decl = "(void)" 241 242 if f.glx_vendorpriv != 0: 243 print ' %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name()) 244 else: 245 print ' %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name()) 246 247 self.common_emit_args(f, "pc", " ", 0, 0) 248 249 if f.needs_reply(): 250 if f.output != None: 251 output_size = f.output.p_type.size 252 output_str = f.output.name 253 else: 254 output_size = 0 255 output_str = "NULL" 256 257 if f.fn_return_type != 'void': 258 return_str = " retval = (%s)" % (f.fn_return_type) 259 else: 260 return_str = " (void)" 261 262 if f.reply_always_array: 263 aa = "GL_TRUE" 264 else: 265 aa = "GL_FALSE" 266 267 print " %s read_reply(dpy, %s, %s, %s);" % (return_str, output_size, output_str, aa) 268 269 print ' UnlockDisplay(dpy); SyncHandle();' 270 print ' }' 271 print ' %s' % f.return_string() 272 print '}' 273 print '' 274 return 275 276 277 def printRenderFunction(self, f): 278 # There is a class of GL functions that take a single pointer 279 # as a parameter. This pointer points to a fixed-size chunk 280 # of data, and the protocol for this functions is very 281 # regular. Since they are so regular and there are so many 282 # of them, special case them with generic functions. On 283 # x86, this saves about 26KB in the libGL.so binary. 284 285 if f.variable_length_parameter() == None and len(f.fn_parameters) == 1: 286 p = f.fn_parameters[0] 287 if p.is_pointer: 288 [cmdlen, size_string] = f.command_payload_length() 289 if cmdlen in self.generic_sizes: 290 self.common_func_print_just_header(f) 291 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name) 292 print '}' 293 print '' 294 return 295 296 if self.common_func_print_header(f): 297 indent = " " 298 trailer = " }" 299 else: 300 indent = "" 301 trailer = None 302 303 if f.can_be_large: 304 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent) 305 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent) 306 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent) 307 print '%s }' % (indent) 308 indent += " " 309 310 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name()) 311 312 self.common_emit_args(f, "gc->pc", indent, 4, 0) 313 print '%s gc->pc += cmdlen;' % (indent) 314 print '%s if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent) 315 316 if f.can_be_large: 317 print '%s}' % (indent) 318 print '%selse {' % (indent) 319 print '%s const GLint op = %s;' % (indent, f.opcode_real_name()) 320 print '%s const GLuint cmdlenLarge = cmdlen + 4;' % (indent) 321 print '%s GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent) 322 print '%s (void) memcpy((void *)(pc + 0), (void *)(&op), 4);' % (indent) 323 print '%s (void) memcpy((void *)(pc + 4), (void *)(&cmdlenLarge), 4);' % (indent) 324 offset = self.common_emit_args(f, "pc", indent, 8, 1) 325 326 p = f.variable_length_parameter() 327 print '%s __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, offset + 8, p.name, p.size_string()) 328 print '%s}' % (indent) 329 330 if trailer: print trailer 331 print '}' 332 print '' 333 return 334 335 336class PrintGlxProtoInit_c(glX_XML.GlxProto): 337 def __init__(self): 338 glX_XML.GlxProto.__init__(self) 339 self.last_category = "" 340 self.license = license.bsd_license_template % ( \ 341"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 342(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 343 344 345 def printRealHeader(self): 346 print """/** 347 * \\file indirect_init.c 348 * Initialize indirect rendering dispatch table. 349 * 350 * \\author Kevin E. Martin <kevin@precisioninsight.com> 351 * \\author Brian Paul <brian@precisioninsight.com> 352 * \\author Ian Romanick <idr@us.ibm.com> 353 */ 354 355#include "indirect_init.h" 356#include "indirect.h" 357#include "glapi.h" 358 359 360/** 361 * No-op function used to initialize functions that have no GLX protocol 362 * support. 363 */ 364static int NoOp(void) 365{ 366 return 0; 367} 368 369/** 370 * Create and initialize a new GL dispatch table. The table is initialized 371 * with GLX indirect rendering protocol functions. 372 */ 373__GLapi * __glXNewIndirectAPI( void ) 374{ 375 __GLapi *glAPI; 376 GLuint entries; 377 378 entries = _glapi_get_dispatch_table_size(); 379 glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *)); 380 381 /* first, set all entries to point to no-op functions */ 382 { 383 int i; 384 void **dispatch = (void **) glAPI; 385 for (i = 0; i < entries; i++) { 386 dispatch[i] = (void *) NoOp; 387 } 388 } 389 390 /* now, initialize the entries we understand */""" 391 392 def printRealFooter(self): 393 print """ 394 return glAPI; 395} 396""" 397 398 def printFunction(self, f): 399 if f.fn_offset < 0 or f.ignore: return 400 401 if f.category != self.last_category: 402 self.last_category = f.category 403 print '' 404 print ' /* %s */' % (self.last_category) 405 print '' 406 407 print ' glAPI->%s = __indirect_gl%s;' % (f.name, f.name) 408 409 410class PrintGlxProtoInit_h(glX_XML.GlxProto): 411 def __init__(self): 412 glX_XML.GlxProto.__init__(self) 413 self.last_category = "" 414 self.license = license.bsd_license_template % ( \ 415"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 416(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM") 417 418 419 def printRealHeader(self): 420 print """ 421/** 422 * \\file 423 * Prototypes for indirect rendering functions. 424 * 425 * \\author Kevin E. Martin <kevin@precisioninsight.com> 426 * \\author Ian Romanick <idr@us.ibm.com> 427 */ 428 429#if !defined( _INDIRECT_H_ ) 430# define _INDIRECT_H_ 431 432""" 433 glX_XML.printVisibility( "HIDDEN", "hidden" ) 434 435 436 def printRealFooter(self): 437 print "# undef HIDDEN" 438 print "#endif /* !defined( _INDIRECT_H_ ) */" 439 440 def printFunction(self, f): 441 if f.fn_offset < 0 or f.ignore: return 442 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string()) 443 444 445class PrintGlxSizeStubs(glX_XML.GlxProto): 446 def __init__(self): 447 glX_XML.GlxProto.__init__(self) 448 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM") 449 self.aliases = [] 450 self.glx_enum_sigs = {} 451 452 def printRealHeader(self): 453 print '' 454 print '#include <GL/gl.h>' 455 print '#include "indirect_size.h"' 456 457 print '' 458 glX_XML.printPure() 459 print '' 460 glX_XML.printFastcall() 461 print '' 462 glX_XML.printVisibility( "INTERNAL", "internal" ) 463 print '' 464 print '' 465 print '#ifdef HAVE_ALIAS' 466 print '# define ALIAS2(from,to) \\' 467 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\' 468 print ' __attribute__ ((alias( # to )));' 469 print '# define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )' 470 print '#else' 471 print '# define ALIAS(from,to) \\' 472 print ' INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\' 473 print ' { return __gl ## to ## _size( e ); }' 474 print '#endif' 475 print '' 476 print '' 477 478 def printRealFooter(self): 479 for a in self.aliases: 480 print a 481 482 def printFunction(self, f): 483 if self.glx_enum_functions.has_key(f.name): 484 ef = self.glx_enum_functions[f.name] 485 486 sig = ef.signature(); 487 if self.glx_enum_sigs.has_key(sig): 488 n = self.glx_enum_sigs[sig]; 489 a = 'ALIAS( %s, %s )' % (f.name, n) 490 self.aliases.append(a) 491 else: 492 ef.Print( f.name ) 493 self.glx_enum_sigs[sig] = f.name; 494 495 496 497class PrintGlxSizeStubs_h(glX_XML.GlxProto): 498 def __init__(self): 499 glX_XML.GlxProto.__init__(self) 500 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM") 501 self.aliases = [] 502 self.glx_enum_sigs = {} 503 504 def printRealHeader(self): 505 print """ 506/** 507 * \\file 508 * Prototypes for functions used to determine the number of data elements in 509 * various GLX protocol messages. 510 * 511 * \\author Ian Romanick <idr@us.ibm.com> 512 */ 513 514#if !defined( _GLXSIZE_H_ ) 515# define _GLXSIZE_H_ 516 517""" 518 glX_XML.printPure(); 519 print '' 520 glX_XML.printFastcall(); 521 print '' 522 glX_XML.printVisibility( "INTERNAL", "internal" ); 523 print '' 524 525 def printRealFooter(self): 526 print '' 527 print "# undef INTERNAL" 528 print "# undef PURE" 529 print "# undef FASTCALL" 530 print "#endif /* !defined( _GLXSIZE_H_ ) */" 531 532 533 def printFunction(self, f): 534 if self.glx_enum_functions.has_key(f.name): 535 ef = self.glx_enum_functions[f.name] 536 print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name) 537 538 539def show_usage(): 540 print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0] 541 sys.exit(1) 542 543 544if __name__ == '__main__': 545 file_name = "gl_API.xml" 546 547 try: 548 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:") 549 except Exception,e: 550 show_usage() 551 552 mode = "proto" 553 for (arg,val) in args: 554 if arg == "-f": 555 file_name = val 556 elif arg == "-m": 557 mode = val 558 559 if mode == "proto": 560 dh = PrintGlxProtoStubs() 561 elif mode == "init_c": 562 dh = PrintGlxProtoInit_c() 563 elif mode == "init_h": 564 dh = PrintGlxProtoInit_h() 565 elif mode == "size_c": 566 dh = PrintGlxSizeStubs() 567 elif mode == "size_h": 568 dh = PrintGlxSizeStubs_h() 569 else: 570 show_usage() 571 572 parser = make_parser() 573 parser.setFeature(feature_namespaces, 0) 574 parser.setContentHandler(dh) 575 576 f = open(file_name) 577 578 dh.printHeader() 579 parser.parse(f) 580 dh.printFooter() 581