Refactor the code to emit multiple-inclusion protection to
[profile/ivi/mesa.git] / src / mesa / glapi / glX_proto_send.py
1 #!/usr/bin/python2
2
3 # (C) Copyright IBM Corporation 2004, 2005
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 glX_XML
34 import license
35 import sys, getopt, copy
36
37 def hash_pixel_function(func):
38         """Generate a 'unique' key for a pixel function.  The key is based on
39         the parameters written in the command packet.  This includes any
40         padding that might be added for the original function and the 'NULL
41         image' flag."""
42
43         [dim, junk, junk, junk, junk] = func.dimensions()
44
45         d = (dim + 1) & ~1
46         h = "%uD%uD_" % (d - 1, d)
47
48         for p in func.parameterIterator(1, 1):
49                 h = "%s%u" % (h, p.size())
50
51                 if func.pad_after(p):
52                         h += "4"
53
54         if func.image.img_null_flag:
55                 h += "_NF"
56
57         n = func.name.replace("%uD" % (dim), "")
58         n = "__glx_%s_%uD%uD" % (n, d - 1, d)
59         return [h, n]
60
61
62 class glXPixelFunctionUtility(glX_XML.glXFunction):
63         """Dummy class used to generate pixel "utility" functions that are
64         shared by multiple dimension image functions.  For example, these
65         objects are used to generate shared functions used to send GLX
66         protocol for TexImage1D and TexImage2D, TexSubImage1D and
67         TexSubImage2D, etc."""
68
69         def __init__(self, func, name):
70                 # The parameters to the utility function are the same as the
71                 # parameters to the real function except for the added "pad"
72                 # parameters.
73
74                 self.name = name
75                 self.image = copy.copy(func.image)
76                 self.fn_parameters = []
77                 for p in gl_XML.glFunction.parameterIterator(func):
78                         self.fn_parameters.append(p)
79
80                         pad_name = func.pad_after(p)
81                         if pad_name:
82                                 pad = copy.copy(p)
83                                 pad.name = pad_name
84                                 self.fn_parameters.append(pad)
85                                 
86
87                 if self.image.height == None:
88                         self.image.height = "height"
89
90                 if self.image.img_yoff == None:
91                         self.image.img_yoff = "yoffset"
92
93                 if func.image.depth:
94                         if self.image.extent == None:
95                                 self.image.extent = "extent"
96
97                         if self.image.img_woff == None:
98                                 self.image.img_woff = "woffset"
99
100
101                 self.set_return_type( func.fn_return_type )
102                 self.glx_rop = ~0
103                 self.can_be_large = func.can_be_large
104                 self.count_parameters = func.count_parameters
105                 self.counter = func.counter
106                 return
107
108
109 class PrintGlxProtoStubs(glX_XML.GlxProto):
110         def __init__(self):
111                 glX_XML.GlxProto.__init__(self)
112                 self.last_category = ""
113                 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
114                 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
115                 self.pixel_stubs = {}
116                 self.debug = 0
117                 return
118
119         def printRealHeader(self):
120                 print ''
121                 print '#include <GL/gl.h>'
122                 print '#include "indirect.h"'
123                 print '#include "glxclient.h"'
124                 print '#include "indirect_size.h"'
125                 print '#include <GL/glxproto.h>'
126                 print ''
127                 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
128                 print ''
129                 glX_XML.printFastcall()
130                 glX_XML.printNoinline()
131                 print ''
132                 print '#if !defined __GNUC__ || __GNUC__ < 3'
133                 print '#  define __builtin_expect(x, y) x'
134                 print '#endif'
135                 print ''
136                 print '/* If the size and opcode values are known at compile-time, this will, on'
137                 print ' * x86 at least, emit them with a single instruction.'
138                 print ' */'
139                 print '#define emit_header(dest, op, size)            \\'
140                 print '    do { union { short s[2]; int i; } temp;    \\'
141                 print '         temp.s[0] = (size); temp.s[1] = (op); \\'
142                 print '         *((int *)(dest)) = temp.i; } while(0)'
143                 print ''
144                 print """static NOINLINE CARD32
145 read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
146 {
147     xGLXSingleReply reply;
148     
149     (void) _XReply(dpy, (xReply *) & reply, 0, False);
150     if (size != 0) {
151         if ((reply.length > 0) || reply_is_always_array) {
152             const GLint bytes = (reply_is_always_array) 
153               ? (4 * reply.length) : (reply.size * size);
154             const GLint extra = 4 - (bytes & 3);
155
156             _XRead(dpy, dest, bytes);
157             if ( extra < 4 ) {
158                 _XEatData(dpy, extra);
159             }
160         }
161         else {
162             (void) memcpy( dest, &(reply.pad3), size);
163         }
164     }
165
166     return reply.retval;
167 }
168
169 #define X_GLXSingle 0
170
171 static NOINLINE FASTCALL GLubyte *
172 setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen )
173 {
174     xGLXSingleReq * req;
175     Display * const dpy = gc->currentDpy;
176
177     (void) __glXFlushRenderBuffer(gc, gc->pc);
178     LockDisplay(dpy);
179     GetReqExtra(GLXSingle, cmdlen, req);
180     req->reqType = gc->majorOpcode;
181     req->contextTag = gc->currentContextTag;
182     req->glxCode = sop;
183     return (GLubyte *)(req) + sz_xGLXSingleReq;
184 }
185
186 static NOINLINE FASTCALL GLubyte *
187 setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
188 {
189     xGLXVendorPrivateReq * req;
190     Display * const dpy = gc->currentDpy;
191
192     (void) __glXFlushRenderBuffer(gc, gc->pc);
193     LockDisplay(dpy);
194     GetReqExtra(GLXVendorPrivate, cmdlen, req);
195     req->reqType = gc->majorOpcode;
196     req->glxCode = code;
197     req->vendorCode = vop;
198     req->contextTag = gc->currentContextTag;
199     return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
200 }
201
202 const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
203
204 #define zero                        (__glXDefaultPixelStore+0)
205 #define one                         (__glXDefaultPixelStore+8)
206 #define default_pixel_store_1D      (__glXDefaultPixelStore+4)
207 #define default_pixel_store_1D_size 20
208 #define default_pixel_store_2D      (__glXDefaultPixelStore+4)
209 #define default_pixel_store_2D_size 20
210 #define default_pixel_store_3D      (__glXDefaultPixelStore+0)
211 #define default_pixel_store_3D_size 36
212 #define default_pixel_store_4D      (__glXDefaultPixelStore+0)
213 #define default_pixel_store_4D_size 36
214 """
215
216                 for size in self.generic_sizes:
217                         self.print_generic_function(size)
218                 return
219
220         def printFunction(self, f):
221                 if f.fn_offset < 0 or f.client_handcode or f.ignore: return
222
223                 if f.glx_rop != 0 or f.vectorequiv != None:
224                         if f.image:
225                                 self.printPixelFunction(f)
226                         else:
227                                 self.printRenderFunction(f)
228                 elif f.glx_sop != 0 or f.glx_vendorpriv != 0:
229                         self.printSingleFunction(f)
230                 else:
231                         print "/* Missing GLX protocol for %s. */" % (f.name)
232
233         def print_generic_function(self, n):
234                 size = (n + 3) & ~3
235                 print """static FASTCALL NOINLINE void
236 generic_%u_byte( GLint rop, const void * ptr )
237 {
238     __GLXcontext * const gc = __glXGetCurrentContext();
239     const GLuint cmdlen = %u;
240
241     emit_header(gc->pc, rop, cmdlen);
242     (void) memcpy((void *)(gc->pc + 4), ptr, %u);
243     gc->pc += cmdlen;
244     if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
245 }
246 """ % (n, size + 4, size)
247
248
249         def common_emit_one_arg(self, p, offset, pc, indent, adjust):
250                 t = p.p_type
251                 if p.is_array():
252                         src_ptr = p.name
253                 else:
254                         src_ptr = "&" + p.name
255
256                 print '%s    (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
257                         % (indent, pc, offset + adjust, src_ptr, p.size_string() )
258
259         def common_emit_args(self, f, pc, indent, adjust, skip_vla):
260                 offset = 0
261
262                 if skip_vla:
263                         r = 1
264                 else:
265                         r = 2
266
267                 for p in f.parameterIterator(1, r):
268                         self.common_emit_one_arg(p, offset, pc, indent, adjust)
269                         offset += p.size()
270
271                 return offset
272
273
274         def pixel_emit_args(self, f, pc, indent, adjust, dim, large):
275                 """Emit the arguments for a pixel function.  This differs from
276                 common_emit_args in that pixel functions may require padding
277                 be inserted (i.e., for the missing width field for
278                 TexImage1D), and they may also require a 'NULL image' flag
279                 be inserted before the image data."""
280
281                 offset = 0
282                 for p in f.parameterIterator(1, 1):
283                         self.common_emit_one_arg(p, offset, pc, indent, adjust)
284                         offset += p.size()
285
286                         if f.pad_after(p):
287                                 print '%s    (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust)
288                                 offset += 4
289
290                 if f.image.img_null_flag:
291                         if large:
292                                 print '%s    (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust)
293                         else:
294                                 print '%s    (void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (indent, pc, offset + adjust, f.image.name)
295
296                         offset += 4
297
298                 return offset
299
300
301         def large_emit_begin(self, indent, f, op_name = None):
302                 if not op_name:
303                         op_name = f.opcode_real_name()
304
305                 print '%s    const GLint op = %s;' % (indent, op_name)
306                 print '%s    const GLuint cmdlenLarge = cmdlen + 4;' % (indent)
307                 print '%s    GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
308                 print '%s    (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent)
309                 print '%s    (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent)
310                 return
311
312
313         def common_func_print_just_header(self, f):
314                 print '#define %s %d' % (f.opcode_name(), f.opcode_value())
315
316                 print '%s' % (f.fn_return_type)
317                 print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string())
318                 print '{'
319
320
321         def common_func_print_just_start(self, f):
322                 print '    __GLXcontext * const gc = __glXGetCurrentContext();'
323                 
324                 # The only reason that single and vendor private commands need
325                 # a variable called 'dpy' is becuase they use the SyncHandle
326                 # macro.  For whatever brain-dead reason, that macro is hard-
327                 # coded to use a variable called 'dpy' instead of taking a
328                 # parameter.
329
330                 if not f.glx_rop:
331                         print '    Display * const dpy = gc->currentDpy;'
332                         skip_condition = "dpy != NULL"
333                 elif f.can_be_large:
334                         skip_condition = "gc->currentDpy != NULL"
335                 else:
336                         skip_condition = None
337
338
339                 if f.fn_return_type != 'void':
340                         print '    %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type)
341
342                 if f.count_parameters and not f.output_parameter():
343                         print '    const GLuint compsize = __gl%s_size(%s);' % (f.name, f.count_parameters)
344                 elif f.image:
345                         [dim, w, h, d, junk] = f.dimensions()
346                         
347                         compsize = '__glImageSize(%s, %s, %s, %s, %s, %s)' % (w, h, d, f.image.img_format, f.image.img_type, f.image.img_target)
348                         if not f.image.img_send_null:
349                                 compsize = '(%s != NULL) ? %s : 0' % (f.image.name, compsize)
350
351                         print '    const GLuint compsize = %s;' % (compsize)
352
353
354                 print '    const GLuint cmdlen = %s;' % (f.command_length())
355
356                 if f.counter:
357                         if skip_condition:
358                                 skip_condition = "(%s >= 0) && (%s)" % (f.counter, skip_condition)
359                         else:
360                                 skip_condition = "%s >= 0" % (f.counter)
361
362
363                 if skip_condition:
364                         print '    if (__builtin_expect(%s, 1)) {' % (skip_condition)
365                         return 1
366                 else:
367                         return 0
368
369
370         def common_func_print_header(self, f):
371                 self.common_func_print_just_header(f)
372                 return self.common_func_print_just_start(f)
373
374
375
376         def printSingleFunction(self, f):
377                 self.common_func_print_header(f)
378
379                 if self.debug:
380                         print '        printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
381
382                 if f.fn_parameters != []:
383                         pc_decl = "GLubyte const * pc ="
384                 else:
385                         pc_decl = "(void)"
386
387                 if f.glx_vendorpriv != 0:
388                         print '        %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
389                 else:
390                         print '        %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
391
392                 self.common_emit_args(f, "pc", "    ", 0, 0)
393
394                 if f.needs_reply():
395                         if f.output != None:
396                                 output_size = f.output.p_type.size
397                                 output_str = f.output.name
398                         else:
399                                 output_size = 0
400                                 output_str = "NULL"
401
402                         if f.fn_return_type != 'void':
403                                 return_str = " retval = (%s)" % (f.fn_return_type)
404                         else:
405                                 return_str = " (void)"
406
407                         if f.reply_always_array:
408                                 aa = "GL_TRUE"
409                         else:
410                                 aa = "GL_FALSE"
411
412                         print "       %s read_reply(dpy, %s, %s, %s);" % (return_str, output_size, output_str, aa)
413                 elif self.debug:
414                         # Only emit the extra glFinish call for functions
415                         # that don't already require a reply from the server.
416                         print '        __indirect_glFinish();'
417
418                 if self.debug:
419                         print '        printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
420
421
422                 print '        UnlockDisplay(dpy); SyncHandle();'
423                 print '    }'
424                 print '    %s' % f.return_string()
425                 print '}'
426                 print ''
427                 return
428
429
430         def printPixelFunction(self, f):
431                 """This function could use some major refactoring. :("""
432
433                 # There is a code-space optimization that we can do here.
434                 # Functions that are marked img_pad_dimensions have a version
435                 # with an odd number of dimensions and an even number of
436                 # dimensions.  TexSubImage1D and TexSubImage2D are examples.
437                 # We can emit a single function that does both, and have the
438                 # real functions call the utility function with the correct
439                 # parameters.
440                 #
441                 # The only quirk to this is that utility funcitons will be
442                 # generated for 3D and 4D functions, but 4D (e.g.,
443                 # GL_SGIS_texture4D) isn't typically supported.  This is
444                 # probably not an issue.  However, it would be possible to
445                 # look at the total set of functions and determine if there
446                 # is another function that would actually use the utility
447                 # function.  If not, then fallback to the normal way of
448                 # generating code.
449
450                 if f.image.img_pad_dimensions:
451                         # Determine the hash key and the name for the utility
452                         # function that is used to implement the real
453                         # function.
454
455                         [h, n] = hash_pixel_function(f)
456
457                         
458                         # If the utility function is not yet known, generate
459                         # it.
460
461                         if not self.pixel_stubs.has_key(h):
462                                 self.pixel_stubs[h] = n
463                                 pixel_func = glXPixelFunctionUtility(f, n)
464
465                                 print 'static void'
466                                 print '%s( unsigned opcode, unsigned dim, %s )' % (n, pixel_func.get_parameter_string())
467                                 print '{'
468
469                                 if self.common_func_print_just_start(pixel_func):
470                                         indent = "    "
471                                         trailer = "    }"
472                                 else:
473                                         indent = ""
474                                         trailer = None
475
476
477                                 if pixel_func.can_be_large:
478                                         print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
479                                         print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
480                                         print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
481                                         print '%s        }' % (indent)
482                                         indent += "    "
483
484                                 [dim, width, height, depth, extent] = pixel_func.dimensions()
485                                 adjust = pixel_func.offset_of_first_parameter() + 4
486
487                                 print '%s    emit_header(gc->pc, opcode, cmdlen);' % (indent)
488
489                                 offset = self.pixel_emit_args(pixel_func, "gc->pc", indent, adjust, dim, 0)
490
491                                 s = pixel_func.command_fixed_length()
492
493                                 pixHeaderPtr = "gc->pc + 4"
494                                 pcPtr = "gc->pc + %u" % (s + 4)
495
496                                 if pixel_func.image.img_send_null:
497                                         condition = '(compsize > 0) && (%s != NULL)' % (pixel_func.image.name)
498                                 else:
499                                         condition = 'compsize > 0'
500
501                                 print '%s    if (%s) {' % (indent, condition)
502                                 print '%s        (*gc->fillImage)(gc, dim, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, width, height, depth, pixel_func.image.img_format, pixel_func.image.img_type, pixel_func.image.name, pcPtr, pixHeaderPtr)
503                                 print '%s    }' % (indent)
504                                 print '%s    else {' % (indent)
505                                 print '%s        (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
506                                 print '%s    }' % (indent)
507
508                                 print '%s    gc->pc += cmdlen;' % (indent)
509                                 print '%s    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
510
511                                 if f.can_be_large:
512                                         adjust += 4
513
514                                         print '%s}' % (indent)
515                                         print '%selse {' % (indent)
516
517                                         self.large_emit_begin(indent, pixel_func, "opcode")
518                                         offset = self.pixel_emit_args(pixel_func, "pc", indent, adjust, dim, 1)
519
520                                         pixHeaderPtr = "pc + 8"
521                                         pcPtr = "pc + %u" % (s + 8)
522
523                                         print '%s    __glXSendLargeImage(gc, compsize, dim, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr)
524
525                                         print '%s}' % (indent)
526
527                                 if trailer: print trailer
528                                 print '}'
529                                 print ''
530
531
532
533                         # Generate the real function as a call to the
534                         # utility function.
535
536                         self.common_func_print_just_header(f)
537
538                         [dim, junk, junk, junk, junk] = f.dimensions()
539
540                         p_string = ""
541                         for p in gl_XML.glFunction.parameterIterator(f):
542                                 p_string += ", " + p.name
543
544                                 if f.pad_after(p):
545                                         p_string += ", 1"
546
547                         print '    %s(%s, %u%s );' % (n, f.opcode_name(), dim, p_string)
548                         print '}'
549                         print ''
550                         return
551
552
553                 if self.common_func_print_header(f):
554                         indent = "    "
555                         trailer = "    }"
556                 else:
557                         indent = ""
558                         trailer = None
559
560
561                 if f.can_be_large:
562                         print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
563                         print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
564                         print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
565                         print '%s        }' % (indent)
566                         indent += "    "
567
568                 [dim, width, height, depth, extent] = f.dimensions()
569                 adjust = f.offset_of_first_parameter() + 4
570
571                 print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
572
573                 offset = self.pixel_emit_args(f, "gc->pc", indent, adjust, dim, 0)
574
575                 s = f.command_fixed_length()
576
577                 pixHeaderPtr = "gc->pc + 4"
578                 pcPtr = "gc->pc + %u" % (s + 4)
579
580                 if f.image.img_send_null:
581                         condition = '(compsize > 0) && (%s != NULL)' % (f.image.name)
582                 else:
583                         condition = 'compsize > 0'
584
585                 print '%s    if (%s) {' % (indent, condition)
586                 print '%s        (*gc->fillImage)(gc, %u, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr)
587                 print '%s    }' % (indent)
588                 print '%s    else {' % (indent)
589                 print '%s        (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
590                 print '%s    }' % (indent)
591
592                 print '%s    gc->pc += cmdlen;' % (indent)
593                 print '%s    if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
594
595                 if f.can_be_large:
596                         adjust += 4
597
598                         print '%s}' % (indent)
599                         print '%selse {' % (indent)
600
601                         self.large_emit_begin(indent, f)
602                         offset = self.pixel_emit_args(f, "pc", indent, adjust, dim, 1)
603
604                         pixHeaderPtr = "pc + 8"
605                         pcPtr = "pc + %u" % (s + 8)
606
607                         print '%s    __glXSendLargeImage(gc, compsize, %u, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim, width, height, depth, f.image.img_format, f.image.img_type, f.image.name, pcPtr, pixHeaderPtr)
608
609                         print '%s}' % (indent)
610
611                 if trailer: print trailer
612                 print '}'
613                 print ''
614                 return
615
616
617         def printRenderFunction(self, f):
618                 # There is a class of GL functions that take a single pointer
619                 # as a parameter.  This pointer points to a fixed-size chunk
620                 # of data, and the protocol for this functions is very
621                 # regular.  Since they are so regular and there are so many
622                 # of them, special case them with generic functions.  On
623                 # x86, this saves about 26KB in the libGL.so binary.
624
625                 if f.variable_length_parameter() == None and len(f.fn_parameters) == 1:
626                         p = f.fn_parameters[0]
627                         if p.is_pointer:
628                                 cmdlen = f.command_fixed_length()
629                                 if cmdlen in self.generic_sizes:
630                                         self.common_func_print_just_header(f)
631                                         print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
632                                         print '}'
633                                         print ''
634                                         return
635
636                 if self.common_func_print_header(f):
637                         indent = "    "
638                         trailer = "    }"
639                 else:
640                         indent = ""
641                         trailer = None
642
643                 if self.debug:
644                         print '%s    printf( "Enter %%s...\\n", "gl%s" );' % (indent, f.name)
645
646                 if f.can_be_large:
647                         print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
648                         print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
649                         print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
650                         print '%s        }' % (indent)
651                         indent += "    "
652
653                 print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
654
655                 self.common_emit_args(f, "gc->pc", indent, 4, 0)
656                 print '%s    gc->pc += cmdlen;' % (indent)
657                 print '%s    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
658
659                 if f.can_be_large:
660                         print '%s}' % (indent)
661                         print '%selse {' % (indent)
662
663                         self.large_emit_begin(indent, f)
664                         offset = self.common_emit_args(f, "pc", indent, 8, 1)
665
666                         p = f.variable_length_parameter()
667                         print '%s    __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, offset + 8, p.name, p.size_string())
668                         print '%s}' % (indent)
669
670                 if self.debug:
671                         print '%s    __indirect_glFinish();' % (indent)
672                         print '%s    printf( "Exit %%s.\\n", "gl%s" );' % (indent, f.name)
673
674                 if trailer: print trailer
675                 print '}'
676                 print ''
677                 return
678
679
680 class PrintGlxProtoInit_c(glX_XML.GlxProto):
681         def __init__(self):
682                 glX_XML.GlxProto.__init__(self)
683                 self.last_category = ""
684                 self.license = license.bsd_license_template % ( \
685 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
686 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
687
688
689         def printRealHeader(self):
690                 print """/**
691  * \\file indirect_init.c
692  * Initialize indirect rendering dispatch table.
693  *
694  * \\author Kevin E. Martin <kevin@precisioninsight.com>
695  * \\author Brian Paul <brian@precisioninsight.com>
696  * \\author Ian Romanick <idr@us.ibm.com>
697  */
698
699 #include "indirect_init.h"
700 #include "indirect.h"
701 #include "glapi.h"
702
703
704 /**
705  * No-op function used to initialize functions that have no GLX protocol
706  * support.
707  */
708 static int NoOp(void)
709 {
710     return 0;
711 }
712
713 /**
714  * Create and initialize a new GL dispatch table.  The table is initialized
715  * with GLX indirect rendering protocol functions.
716  */
717 __GLapi * __glXNewIndirectAPI( void )
718 {
719     __GLapi *glAPI;
720     GLuint entries;
721
722     entries = _glapi_get_dispatch_table_size();
723     glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
724
725     /* first, set all entries to point to no-op functions */
726     {
727        int i;
728        void **dispatch = (void **) glAPI;
729        for (i = 0; i < entries; i++) {
730           dispatch[i] = (void *) NoOp;
731        }
732     }
733
734     /* now, initialize the entries we understand */"""
735
736         def printRealFooter(self):
737                 print """
738     return glAPI;
739 }
740 """
741
742         def printFunction(self, f):
743                 if f.fn_offset < 0 or f.ignore: return
744                 
745                 if f.category != self.last_category:
746                         self.last_category = f.category
747                         print ''
748                         print '    /* %s */' % (self.last_category)
749                         print ''
750                         
751                 print '    glAPI->%s = __indirect_gl%s;' % (f.name, f.name)
752
753
754 class PrintGlxProtoInit_h(glX_XML.GlxProto):
755         def __init__(self):
756                 glX_XML.GlxProto.__init__(self)
757                 self.last_category = ""
758                 self.license = license.bsd_license_template % ( \
759 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
760 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
761                 self.header_tag = "_INDIRECT_H_"
762
763         def printRealHeader(self):
764                 print """/**
765  * \\file
766  * Prototypes for indirect rendering functions.
767  *
768  * \\author Kevin E. Martin <kevin@precisioninsight.com>
769  * \\author Ian Romanick <idr@us.ibm.com>
770  */
771 """
772                 glX_XML.printVisibility( "HIDDEN", "hidden" )
773
774
775         def printRealFooter(self):
776                 print "#  undef HIDDEN"
777
778
779         def printFunction(self, f):
780                 if f.fn_offset < 0 or f.ignore: return
781                 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string())
782
783
784 def show_usage():
785         print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0]
786         print "    -m output_mode   Output mode can be one of 'proto', 'init_c' or 'init_h'."
787         print "    -d               Enable extra debug information in the generated code."
788         sys.exit(1)
789
790
791 if __name__ == '__main__':
792         file_name = "gl_API.xml"
793
794         try:
795                 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:d")
796         except Exception,e:
797                 show_usage()
798
799         debug = 0
800         mode = "proto"
801         for (arg,val) in args:
802                 if arg == "-f":
803                         file_name = val
804                 elif arg == "-m":
805                         mode = val
806                 elif arg == "-d":
807                         debug = 1
808
809         if mode == "proto":
810                 dh = PrintGlxProtoStubs()
811         elif mode == "init_c":
812                 dh = PrintGlxProtoInit_c()
813         elif mode == "init_h":
814                 dh = PrintGlxProtoInit_h()
815         else:
816                 show_usage()
817
818         parser = make_parser()
819         parser.setFeature(feature_namespaces, 0)
820         parser.setContentHandler(dh)
821
822         f = open(file_name)
823
824         dh.debug = debug
825         dh.printHeader()
826         parser.parse(f)
827         dh.printFooter()