Python script to generate various bits of client-side GLX protocol code.
[profile/ivi/mesa.git] / src / mesa / glapi / glX_proto_send.py
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
28 from xml.sax import saxutils
29 from xml.sax import make_parser
30 from xml.sax.handler import feature_namespaces
31
32 import gl_XML
33 import license
34 import sys, getopt
35
36
37 def printPure():
38         print """#  if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 96)
39 #    define PURE __attribute__((pure))
40 #  else
41 #    define PURE
42 #  endif"""
43
44 def printFastcall():
45         print """#  if defined(__i386__) && defined(__GNUC__)
46 #    define FASTCALL __attribute__((fastcall))
47 #  else
48 #    define FASTCALL
49 #  endif"""
50
51 def printVisibility(S, s):
52         print """#  if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
53 #    define %s  __attribute__((visibility("%s")))
54 #  else
55 #    define %s
56 #  endif""" % (S, s, S)
57
58 def printNoinline():
59         print """#  if defined(__GNUC__)
60 #    define NOINLINE __attribute__((noinline))
61 #  else
62 #    define NOINLINE
63 #  endif"""
64
65
66 class glXItemFactory(gl_XML.glItemFactory):
67         """Factory to create GLX protocol oriented objects derived from glItem."""
68     
69         def create(self, context, name, attrs):
70                 if name == "function":
71                         return glXFunction(context, name, attrs)
72                 elif name == "enum":
73                         return glXEnum(context, name, attrs)
74                 elif name == "param":
75                         return glXParameter(context, name, attrs)
76                 else:
77                         return gl_XML.glItemFactory.create(self, context, name, attrs)
78
79 class glXEnumFunction:
80         def __init__(self, name):
81                 self.name = name
82                 
83                 # "enums" is a set of lists.  The element in the set is the
84                 # value of the enum.  The list is the list of names for that
85                 # value.  For example, [0x8126] = {"POINT_SIZE_MIN",
86                 # "POINT_SIZE_MIN_ARB", "POINT_SIZE_MIN_EXT",
87                 # "POINT_SIZE_MIN_SGIS"}.
88
89                 self.enums = {}
90
91                 # "count" is indexed by count values.  Each element of count
92                 # is a list of index to "enums" that have that number of
93                 # associated data elements.  For example, [4] = 
94                 # {GL_AMBIENT, GL_DIFFUSE, GL_SPECULAR, GL_EMISSION,
95                 # GL_AMBIENT_AND_DIFFUSE} (the enum names are used here,
96                 # but the actual hexadecimal values would be in the array).
97
98                 self.count = {}
99
100
101         def append(self, count, value, name):
102                 if self.enums.has_key( value ):
103                         self.enums[value].append(name)
104                 else:
105                         if not self.count.has_key(count):
106                                 self.count[count] = []
107
108                         self.enums[value] = []
109                         self.enums[value].append(name)
110                         self.count[count].append(value)
111
112
113         def signature( self ):
114                 sig = ""
115                 for i in self.count:
116                         for e in self.count[i]:
117                                 sig += "%04x,%u," % (e, i)
118         
119                 return sig;
120
121
122         def PrintUsingTable(self):
123                 """Emit the body of the __gl*_size function using a pair
124                 of look-up tables and a mask.  The mask is calculated such
125                 that (e & mask) is unique for all the valid values of e for
126                 this function.  The result of (e & mask) is used as an index
127                 into the first look-up table.  If it matches e, then the
128                 same entry of the second table is returned.  Otherwise zero
129                 is returned.
130                 
131                 It seems like this should cause better code to be generated.
132                 However, on x86 at least, the resulting .o file is about 20%
133                 larger then the switch-statment version.  I am leaving this
134                 code in because the results may be different on other
135                 platforms (e.g., PowerPC or x86-64)."""
136
137                 return 0
138                 count = 0
139                 for a in self.enums:
140                         count += 1
141
142                 # Determine if there is some mask M, such that M = (2^N) - 1,
143                 # that will generate unique values for all of the enums.
144
145                 mask = 0
146                 for i in [1, 2, 3, 4, 5, 6, 7, 8]:
147                         mask = (1 << i) - 1
148
149                         fail = 0;
150                         for a in self.enums:
151                                 for b in self.enums:
152                                         if a != b:
153                                                 if (a & mask) == (b & mask):
154                                                         fail = 1;
155
156                         if not fail:
157                                 break;
158                         else:
159                                 mask = 0
160
161                 if (mask != 0) and (mask < (2 * count)):
162                         masked_enums = {}
163                         masked_count = {}
164
165                         for i in range(0, mask):
166                                 masked_enums[i] = "0";
167                                 masked_count[i] = 0;
168
169                         for c in self.count:
170                                 for e in self.count[c]:
171                                         i = e & mask
172                                         masked_enums[i] = '0x%04x /* %s */' % (e, self.enums[e][0])
173                                         masked_count[i] = c
174
175
176                         print '    static const GLushort a[%u] = {' % (mask + 1)
177                         for e in masked_enums:
178                                 print '        %s, ' % (masked_enums[e])
179                         print '    };'
180
181                         print '    static const GLubyte b[%u] = {' % (mask + 1)
182                         for c in masked_count:
183                                 print '        %u, ' % (masked_count[c])
184                         print '    };'
185
186                         print '    const unsigned idx = (e & 0x%02xU);' % (mask)
187                         print ''
188                         print '    return (e == a[idx]) ? (GLint) b[idx] : 0;'
189                         return 1;
190                 else:
191                         return 0;
192
193         def PrintUsingSwitch(self):
194                 """Emit the body of the __gl*_size function using a 
195                 switch-statement."""
196
197                 print '    switch( e ) {'
198
199                 for c in self.count:
200                         for e in self.count[c]:
201                                 first = 1
202
203                                 # There may be multiple enums with the same
204                                 # value.  This happens has extensions are
205                                 # promoted from vendor-specific or EXT to
206                                 # ARB and to the core.  Emit the first one as
207                                 # a case label, and emit the others as
208                                 # commented-out case labels.
209
210                                 for j in self.enums[e]:
211                                         if first:
212                                                 print '        case %s:' % (j)
213                                                 first = 0
214                                         else:
215                                                 print '/*      case %s:*/' % (j)
216                                         
217                         print '            return %u;' % (c)
218                                         
219                 print '        default: return 0;'
220                 print '    }'
221
222
223         def Print(self, name):
224                 print 'INTERNAL PURE FASTCALL GLint'
225                 print '__gl%s_size( GLenum e )' % (name)
226                 print '{'
227
228                 if not self.PrintUsingTable():
229                         self.PrintUsingSwitch()
230
231                 print '}'
232                 print ''
233
234
235
236 class glXEnum(gl_XML.glEnum):
237         def __init__(self, context, name, attrs):
238                 gl_XML.glEnum.__init__(self, context, name, attrs)
239                 self.glx_functions = []
240
241         def startElement(self, name, attrs):
242                 if name == "size":
243                         n = attrs.get('name', None)
244                         if not self.context.glx_enum_functions.has_key( n ):
245                                 f = glXEnumFunction( n )
246                                 self.context.glx_enum_functions[ f.name ] = f
247
248                         temp = attrs.get('count', None)
249                         try:
250                                 c = int(temp)
251                         except Exception,e:
252                                 raise RuntimeError('Invalid count value "%s" for enum "%s" in function "%s" when an integer was expected.' % (temp, self.name, n))
253
254                         self.context.glx_enum_functions[ n ].append( c, self.value, self.name )
255                 else:
256                         gl_XML.glEnum.startElement(self, context, name, attrs)
257                 return
258
259
260 class glXParameter(gl_XML.glParameter):
261         def __init__(self, context, name, attrs):
262                 self.order = 1;
263                 gl_XML.glParameter.__init__(self, context, name, attrs);
264
265
266 class glXFunction(gl_XML.glFunction):
267         glx_rop = 0
268         glx_sop = 0
269         glx_vendorpriv = 0
270
271         # If this is set to true, it means that GLdouble parameters should be
272         # written to the GLX protocol packet in the order they appear in the
273         # prototype.  This is different from the "classic" ordering.  In the
274         # classic ordering GLdoubles are written to the protocol packet first,
275         # followed by non-doubles.  NV_vertex_program was the first extension
276         # to break with this tradition.
277
278         glx_doubles_in_order = 0
279
280         vectorequiv = None
281         handcode = 0
282         ignore = 0
283         can_be_large = 0
284
285         def __init__(self, context, name, attrs):
286                 self.vectorequiv = attrs.get('vectorequiv', None)
287                 self.count_parameters = None
288                 self.counter = None
289                 self.output = None
290                 self.can_be_large = 0
291                 self.reply_always_array = 0
292
293                 gl_XML.glFunction.__init__(self, context, name, attrs)
294                 return
295
296         def startElement(self, name, attrs):
297                 """Process elements within a function that are specific to GLX."""
298
299                 if name == "glx":
300                         self.glx_rop = int(attrs.get('rop', "0"))
301                         self.glx_sop = int(attrs.get('sop', "0"))
302                         self.glx_vendorpriv = int(attrs.get('vendorpriv', "0"))
303
304                         if attrs.get('handcode', "false") == "true":
305                                 self.handcode = 1
306                         else:
307                                 self.handcode = 0
308
309                         if attrs.get('ignore', "false") == "true":
310                                 self.ignore = 1
311                         else:
312                                 self.ignore = 0
313
314                         if attrs.get('large', "false") == "true":
315                                 self.can_be_large = 1
316                         else:
317                                 self.can_be_large = 0
318
319                         if attrs.get('doubles_in_order', "false") == "true":
320                                 self.glx_doubles_in_order = 1
321                         else:
322                                 self.glx_doubles_in_order = 0
323
324                         if attrs.get('always_array', "false") == "true":
325                                 self.reply_always_array = 1
326                         else:
327                                 self.reply_always_array = 0
328
329                 else:
330                         gl_XML.glFunction.startElement(self, name, attrs)
331
332
333         def append(self, tag_name, p):
334                 gl_XML.glFunction.append(self, tag_name, p)
335
336                 if p.is_variable_length_array():
337                         p.order = 2;
338                 elif not self.glx_doubles_in_order and p.p_type.size == 8:
339                         p.order = 0;
340
341                 if p.p_count_parameters != None:
342                         self.count_parameters = p.p_count_parameters
343                 
344                 if p.is_counter:
345                         self.counter = p.name
346                         
347                 if p.is_output:
348                         self.output = p
349
350                 return
351
352         def variable_length_parameter(self):
353                 for param in self.fn_parameters:
354                         if param.is_variable_length_array():
355                                 return param
356                         
357                 return None
358
359
360         def command_payload_length(self):
361                 size = 0
362                 size_string = ""
363                 for p in self:
364                         if p.is_output: continue
365                         temp = p.size_string()
366                         try:
367                                 s = int(temp)
368                                 size += s
369                         except Exception,e:
370                                 size_string = size_string + " + __GLX_PAD(%s)" % (temp)
371
372                 return [size, size_string]
373
374         def command_length(self):
375                 [size, size_string] = self.command_payload_length()
376
377                 if self.glx_rop != 0:
378                         size += 4
379
380                 size = ((size + 3) & ~3)
381                 return "%u%s" % (size, size_string)
382
383
384         def opcode_value(self):
385                 if self.glx_rop != 0:
386                         return self.glx_rop
387                 elif self.glx_sop != 0:
388                         return self.glx_sop
389                 elif self.glx_vendorpriv != 0:
390                         return self.glx_vendorpriv
391                 else:
392                         return -1
393         
394         def opcode_rop_basename(self):
395                 if self.vectorequiv == None:
396                         return self.name
397                 else:
398                         return self.vectorequiv
399
400         def opcode_name(self):
401                 if self.glx_rop != 0:
402                         return "X_GLrop_%s" % (self.opcode_rop_basename())
403                 elif self.glx_sop != 0:
404                         return "X_GLsop_%s" % (self.name)
405                 elif self.glx_vendorpriv != 0:
406                         return "X_GLvop_%s" % (self.name)
407                 else:
408                         return "ERROR"
409
410         def opcode_real_name(self):
411                 if self.glx_vendorpriv != 0:
412                         if self.needs_reply():
413                                 return "X_GLXVendorPrivateWithReply"
414                         else:
415                                 return "X_GLXVendorPrivate"
416                 else:
417                         return self.opcode_name()
418
419
420         def return_string(self):
421                 if self.fn_return_type != 'void':
422                         return "return retval;"
423                 else:
424                         return "return;"
425
426
427         def needs_reply(self):
428                 return self.fn_return_type != 'void' or self.output != None
429
430
431 class GlxProto(gl_XML.FilterGLAPISpecBase):
432         name = "glX_proto_send.py (from Mesa)"
433
434         def __init__(self):
435                 gl_XML.FilterGLAPISpecBase.__init__(self)
436                 self.factory = glXItemFactory()
437                 self.glx_enum_functions = {}
438
439
440         def endElement(self, name):
441                 if name == 'OpenGLAPI':
442                         # Once all the parsing is done, we have to go back and
443                         # fix-up some cross references between different
444                         # functions.
445
446                         for k in self.functions:
447                                 f = self.functions[k]
448                                 if f.vectorequiv != None:
449                                         equiv = self.find_function(f.vectorequiv)
450                                         if equiv != None:
451                                                 f.glx_doubles_in_order = equiv.glx_doubles_in_order
452                                                 f.glx_rop = equiv.glx_rop
453                                         else:
454                                                 raise RuntimeError("Could not find the vector equiv. function %s for %s!" % (f.name, f.vectorequiv))
455                 else:
456                         gl_XML.FilterGLAPISpecBase.endElement(self, name)
457                 return
458
459
460 class PrintGlxProtoStubs(GlxProto):
461         def __init__(self):
462                 GlxProto.__init__(self)
463                 self.last_category = ""
464                 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
465                 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
466                 return
467
468         def printRealHeader(self):
469                 print ''
470                 print '#include <GL/gl.h>'
471                 print '#include "indirect.h"'
472                 print '#include "glxclient.h"'
473                 print '#include "size.h"'
474                 print '#include <GL/glxproto.h>'
475                 print ''
476                 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
477                 print ''
478                 printFastcall()
479                 printNoinline()
480                 print ''
481                 print '/* If the size and opcode values are known at compile-time, this will, on'
482                 print ' * x86 at least, emit them with a single instruction.'
483                 print ' */'
484                 print '#define emit_header(dest, op, size)            \\'
485                 print '    do { union { short s[2]; int i; } temp;    \\'
486                 print '         temp.s[0] = (size); temp.s[1] = (op); \\'
487                 print '         *((int *)(dest)) = temp.i; } while(0)'
488                 print ''
489                 print """static NOINLINE CARD32
490 read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
491 {
492     xGLXSingleReply reply;
493     
494     (void) _XReply(dpy, (xReply *) & reply, 0, False);
495     if (size != 0) {
496         if ((reply.size >= 1) || reply_is_always_array) {
497             const GLint bytes = (reply_is_always_array) 
498               ? (4 * reply.length) : (reply.size * size);
499             const GLint extra = 4 - (bytes & 3);
500
501             _XRead(dpy, dest, bytes);
502             if ( extra != 0 ) {
503                 _XEatData(dpy, extra);
504             }
505         }
506         else {
507             (void) memcpy( dest, &(reply.pad3), size);
508         }
509     }
510
511     return reply.retval;
512 }
513
514 #define X_GLXSingle 0
515
516 static NOINLINE GLubyte *
517 setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen )
518 {
519     xGLXSingleReq * req;
520     Display * const dpy = gc->currentDpy;
521
522     (void) __glXFlushRenderBuffer(gc, gc->pc);
523     LockDisplay(dpy);
524     GetReqExtra(GLXSingle, cmdlen, req);
525     req->reqType = gc->majorOpcode;
526     req->contextTag = gc->currentContextTag;
527     req->glxCode = sop;
528     return (GLubyte *)(req) + sz_xGLXSingleReq;
529 }
530
531 static NOINLINE GLubyte *
532 setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
533 {
534     xGLXVendorPrivateReq * req;
535     Display * const dpy = gc->currentDpy;
536
537     (void) __glXFlushRenderBuffer(gc, gc->pc);
538     LockDisplay(dpy);
539     GetReqExtra(GLXVendorPrivate, cmdlen, req);
540     req->reqType = gc->majorOpcode;
541     req->glxCode = code;
542     req->vendorCode = vop;
543     req->contextTag = gc->currentContextTag;
544     return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
545 }
546 """
547
548                 for size in self.generic_sizes:
549                         self.print_generic_function(size)
550                 return
551
552         def printFunction(self, f):
553                 if f.fn_offset < 0 or f.handcode or f.ignore: return
554
555                 if f.glx_rop != 0 or f.vectorequiv != None:
556                         self.printRenderFunction(f)
557                 elif f.glx_sop != 0 or f.glx_vendorpriv != 0:
558                         self.printSingleFunction(f)
559                 else:
560                         print "/* Missing GLX protocol for %s. */" % (f.name)
561
562         def print_generic_function(self, n):
563                 print """static FASTCALL NOINLINE void
564 generic_%u_byte( GLint rop, const void * ptr )
565 {
566     __GLXcontext * const gc = __glXGetCurrentContext();
567     const GLuint cmdlen = %u;
568
569     emit_header(gc->pc, rop, cmdlen);
570     (void) memcpy((void *)(gc->pc + 4), ptr, %u);
571     gc->pc += cmdlen;
572     if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
573 }
574 """ % (n, n + 4, n)
575
576
577         def common_emit_one_arg(self, p, offset, pc, indent, adjust):
578                 if p.is_output: return
579
580                 t = p.p_type
581                 if p.is_array():
582                         src_ptr = p.name
583                 else:
584                         src_ptr = "&" + p.name
585
586                 print '%s    (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
587                         % (indent, pc, offset + adjust, src_ptr, p.size_string() )
588
589         def common_emit_args(self, f, pc, indent, adjust, skip_vla):
590                 # First emit all of the fixed-length 8-byte (i.e., GLdouble)
591                 # parameters.
592
593                 offset = 0
594
595                 if skip_vla:
596                         r = [0, 1]
597                 else:
598                         r = [0, 1, 2]
599
600                 for order in r:
601                         for p in f:
602                                 if p.is_output or p.order != order: continue
603
604                                 self.common_emit_one_arg(p, offset, pc, indent, adjust)
605                                 offset += p.size()
606
607
608                 return offset
609
610
611         def common_func_print_just_header(self, f):
612                 print '#define %s %d' % (f.opcode_name(), f.opcode_value())
613
614                 print '%s' % (f.fn_return_type)
615                 print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string())
616                 print '{'
617
618
619         def common_func_print_header(self, f):
620                 self.common_func_print_just_header(f)
621
622                 print '    __GLXcontext * const gc = __glXGetCurrentContext();'
623                 print '    Display * const dpy = gc->currentDpy;'
624                         
625                 if f.fn_return_type != 'void':
626                         print '    %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type)
627
628                 if f.count_parameters != None:
629                         print '    const GLuint compsize = __gl%s_size(%s);' % (f.name, f.count_parameters)
630
631                 print '    const GLuint cmdlen = %s;' % (f.command_length())
632
633                 if f.counter != None:
634                         print '    if (%s < 0) %s' % (f.counter, f.return_string())
635
636                 if f.can_be_large:
637                         print '    if (dpy == NULL) return;'
638                         print '    if ( ((gc->pc + cmdlen) > gc->bufEnd)'
639                         print '         || (cmdlen > gc->maxSmallRenderCommandSize)) {'
640                         print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
641                         print '    }'
642                 else:
643                         print '    (void) dpy;'
644
645                 return
646
647
648         def printSingleFunction(self, f):
649                 self.common_func_print_header(f)
650
651                 print '    if (dpy != NULL) {'
652
653                 if f.fn_parameters != []:
654                         pc_decl = "GLubyte const * pc ="
655                 else:
656                         pc_decl = "(void)"
657
658                 if f.glx_vendorpriv != 0:
659                         print '        %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
660                 else:
661                         print '        %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
662
663                 self.common_emit_args(f, "pc", "    ", 0, 0)
664
665                 if f.needs_reply():
666                         if f.output != None:
667                                 output_size = f.output.p_type.size
668                                 output_str = f.output.name
669                         else:
670                                 output_size = 0
671                                 output_str = "NULL"
672
673                         if f.fn_return_type != 'void':
674                                 return_str = " retval = (%s)" % (f.fn_return_type)
675                         else:
676                                 return_str = " (void)"
677
678                         if f.reply_always_array:
679                                 aa = "GL_TRUE"
680                         else:
681                                 aa = "GL_FALSE"
682
683                         print "       %s read_reply(gc->currentDpy, %s, %s, %s);" % (return_str, output_size, output_str, aa)
684
685                 print '        UnlockDisplay(gc->currentDpy); SyncHandle();'
686                 print '    }'
687                 print '    %s' % f.return_string()
688                 print '}'
689                 print ''
690                 return
691
692
693         def printRenderFunction(self, f):
694                 if f.variable_length_parameter() == None and len(f.fn_parameters) == 1:
695                         p = f.fn_parameters[0]
696                         if p.is_pointer:
697                                 [cmdlen, size_string] = f.command_payload_length()
698                                 if cmdlen in self.generic_sizes:
699                                         self.common_func_print_just_header(f)
700                                         print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
701                                         print '}'
702                                         print ''
703                                         return
704
705                 self.common_func_print_header(f)
706
707                 if f.can_be_large:
708                         print '    if (cmdlen <= gc->maxSmallRenderCommandSize) {'
709                         indent = "    "
710                 else:
711                         indent = ""
712
713                 print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
714
715                 self.common_emit_args(f, "gc->pc", indent, 4, 0)
716                 print '%s    gc->pc += cmdlen;' % (indent)
717                 print '%s    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
718
719                 if f.can_be_large:
720                         print '    }'
721                         print '    else {'
722                         print '        const GLint op = %s;' % (f.opcode_real_name())
723                         print '        const GLuint cmdlenLarge = cmdlen + 4;'
724                         print '        (void) memcpy((void *)(gc->pc + 0), (void *)(&op), 4);'
725                         print '        (void) memcpy((void *)(gc->pc + 4), (void *)(&cmdlenLarge), 4);'
726                         offset = self.common_emit_args(f, "gc->pc", indent, 8, 1)
727                         
728                         p = f.variable_length_parameter()
729                         print '        __glXSendLargeCommand(gc, gc->pc, %u, %s, %s);' % (offset + 8, p.name, p.size_string())
730                         print '    }'
731
732                 print '}'
733                 print ''
734                 return
735
736
737 class PrintGlxProtoInit_c(GlxProto):
738         def __init__(self):
739                 GlxProto.__init__(self)
740                 self.last_category = ""
741                 self.license = license.bsd_license_template % ( \
742 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
743 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
744
745
746         def printRealHeader(self):
747                 print """/**
748  * \\file indirect_init.c
749  * Initialize indirect rendering dispatch table.
750  *
751  * \\author Kevin E. Martin <kevin@precisioninsight.com>
752  * \\author Brian Paul <brian@precisioninsight.com>
753  * \\author Ian Romanick <idr@us.ibm.com>
754  */
755
756 #include "indirect_init.h"
757 #include "indirect.h"
758 #include "glapi.h"
759
760
761 /**
762  * No-op function used to initialize functions that have no GLX protocol
763  * support.
764  */
765 static int NoOp(void)
766 {
767     return 0;
768 }
769
770 /**
771  * Create and initialize a new GL dispatch table.  The table is initialized
772  * with GLX indirect rendering protocol functions.
773  */
774 __GLapi * __glXNewIndirectAPI( void )
775 {
776     __GLapi *glAPI;
777     GLuint entries;
778
779     entries = _glapi_get_dispatch_table_size();
780     glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
781
782     /* first, set all entries to point to no-op functions */
783     {
784        int i;
785        void **dispatch = (void **) glAPI;
786        for (i = 0; i < entries; i++) {
787           dispatch[i] = (void *) NoOp;
788        }
789     }
790
791     /* now, initialize the entries we understand */"""
792
793         def printRealFooter(self):
794                 print """
795     return glAPI;
796 }
797 """
798
799         def printFunction(self, f):
800                 if f.fn_offset < 0 or f.ignore: return
801                 
802                 if f.category != self.last_category:
803                         self.last_category = f.category
804                         print ''
805                         print '    /* %s */' % (self.last_category)
806                         print ''
807                         
808                 print '    glAPI->%s = __indirect_gl%s;' % (f.name, f.name)
809
810
811 class PrintGlxProtoInit_h(GlxProto):
812         def __init__(self):
813                 GlxProto.__init__(self)
814                 self.last_category = ""
815                 self.license = license.bsd_license_template % ( \
816 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
817 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
818
819
820         def printRealHeader(self):
821                 print """
822 /**
823  * \\file
824  * Prototypes for indirect rendering functions.
825  *
826  * \\author Kevin E. Martin <kevin@precisioninsight.com>
827  * \\author Ian Romanick <idr@us.ibm.com>
828  */
829
830 #if !defined( _INDIRECT_H_ )
831 #  define _INDIRECT_H_
832
833 """
834                 printVisibility( "HIDDEN", "hidden" )
835
836
837         def printRealFooter(self):
838                 print "#  undef HIDDEN"
839                 print "#endif /* !defined( _INDIRECT_H_ ) */"
840
841         def printFunction(self, f):
842                 if f.fn_offset < 0 or f.ignore: return
843                 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string())
844
845
846 class PrintGlxSizeStubs(GlxProto):
847         def __init__(self):
848                 GlxProto.__init__(self)
849                 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
850                 self.aliases = []
851                 self.glx_enum_sigs = {}
852
853         def printRealHeader(self):
854                 print ''
855                 print '#include <GL/gl.h>'
856                 print '#include "indirect_size.h"'
857                 
858                 print ''
859                 printPure()
860                 print ''
861                 printFastcall()
862                 print ''
863                 printVisibility( "INTERNAL", "internal" )
864                 print ''
865                 print ''
866                 print '#ifdef HAVE_ALIAS'
867                 print '#  define ALIAS2(from,to) \\'
868                 print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
869                 print '        __attribute__ ((alias( # to )));'
870                 print '#  define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
871                 print '#else'
872                 print '#  define ALIAS(from,to) \\'
873                 print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
874                 print '    { return __gl ## to ## _size( e ); }'
875                 print '#endif'
876                 print ''
877                 print ''
878
879         def printRealFooter(self):
880                 for a in self.aliases:
881                         print a
882
883         def printFunction(self, f):
884                 if self.glx_enum_functions.has_key(f.name):
885                         ef = self.glx_enum_functions[f.name]
886
887                         sig = ef.signature();
888                         if self.glx_enum_sigs.has_key(sig):
889                                 n = self.glx_enum_sigs[sig];
890                                 a = 'ALIAS( %s, %s )' % (f.name, n)
891                                 self.aliases.append(a)
892                         else:
893                                 ef.Print( f.name )
894                                 self.glx_enum_sigs[sig] = f.name;
895
896
897                                 
898 class PrintGlxSizeStubs_h(GlxProto):
899         def __init__(self):
900                 GlxProto.__init__(self)
901                 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
902                 self.aliases = []
903                 self.glx_enum_sigs = {}
904
905         def printRealHeader(self):
906                 print """
907 /**
908  * \\file
909  * Prototypes for functions used to determine the number of data elements in
910  * various GLX protocol messages.
911  *
912  * \\author Ian Romanick <idr@us.ibm.com>
913  */
914
915 #if !defined( _GLXSIZE_H_ )
916 #  define _GLXSIZE_H_
917
918 """
919                 printPure();
920                 print ''
921                 printFastcall();
922                 print ''
923                 printVisibility( "INTERNAL", "internal" );
924                 print ''
925
926         def printRealFooter(self):
927                 print ''
928                 print "#  undef INTERNAL"
929                 print "#  undef PURE"
930                 print "#  undef FASTCALL"
931                 print "#endif /* !defined( _GLXSIZE_H_ ) */"
932
933
934         def printFunction(self, f):
935                 if self.glx_enum_functions.has_key(f.name):
936                         ef = self.glx_enum_functions[f.name]
937                         print 'extern INTERNAL GLint __gl%s_size(GLenum) PURE FASTCALL;' % (f.name)
938
939
940 def show_usage():
941         print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0]
942         sys.exit(1)
943
944
945 if __name__ == '__main__':
946         file_name = "gl_API.xml"
947
948         try:
949                 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:")
950         except Exception,e:
951                 show_usage()
952
953         mode = "proto"
954         for (arg,val) in args:
955                 if arg == "-f":
956                         file_name = val
957                 elif arg == "-m":
958                         mode = val
959
960         if mode == "proto":
961                 dh = PrintGlxProtoStubs()
962         elif mode == "init_c":
963                 dh = PrintGlxProtoInit_c()
964         elif mode == "init_h":
965                 dh = PrintGlxProtoInit_h()
966         elif mode == "size_c":
967                 dh = PrintGlxSizeStubs()
968         elif mode == "size_h":
969                 dh = PrintGlxSizeStubs_h()
970         else:
971                 show_usage()
972
973         parser = make_parser()
974         parser.setFeature(feature_namespaces, 0)
975         parser.setContentHandler(dh)
976
977         f = open(file_name)
978
979         dh.printHeader()
980         parser.parse(f)
981         dh.printFooter()