The opcode and command length fields of RenderLarge commands were
[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 glX_XML
34 import license
35 import sys, getopt
36
37
38 class 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
72 read_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.length > 0) || 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 < 4 ) {
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
98 static NOINLINE FASTCALL GLubyte *
99 setup_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
113 static NOINLINE FASTCALL GLubyte *
114 setup_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
146 generic_%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 large_emit_begin(self, indent, f):
185                 print '%s    const GLint op = %s;' % (indent, f.opcode_real_name())
186                 print '%s    const GLuint cmdlenLarge = cmdlen + 4;' % (indent)
187                 print '%s    GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
188                 print '%s    (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent)
189                 print '%s    (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent)
190                 return
191
192
193         def common_func_print_just_header(self, f):
194                 print '#define %s %d' % (f.opcode_name(), f.opcode_value())
195
196                 print '%s' % (f.fn_return_type)
197                 print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string())
198                 print '{'
199
200
201         def common_func_print_header(self, f):
202                 self.common_func_print_just_header(f)
203
204                 print '    __GLXcontext * const gc = __glXGetCurrentContext();'
205                 
206                 # The only reason that single and vendor private commands need
207                 # a variable called 'dpy' is becuase they use the SyncHandle
208                 # macro.  For whatever brain-dead reason, that macro is hard-
209                 # coded to use a variable called 'dpy' instead of taking a
210                 # parameter.
211
212                 if not f.glx_rop:
213                         print '    Display * const dpy = gc->currentDpy;'
214                         skip_condition = "dpy != NULL"
215                 elif f.can_be_large:
216                         skip_condition = "gc->currentDpy != NULL"
217                 else:
218                         skip_condition = None
219
220
221                 if f.fn_return_type != 'void':
222                         print '    %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type)
223
224                 if f.count_parameters != None:
225                         print '    const GLuint compsize = __gl%s_size(%s);' % (f.name, f.count_parameters)
226
227                 print '    const GLuint cmdlen = %s;' % (f.command_length())
228
229                 if f.counter:
230                         if skip_condition:
231                                 skip_condition = "(%s >= 0) && (%s)" % (f.counter, skip_condition)
232                         else:
233                                 skip_condition = "%s >= 0" % (f.counter)
234
235
236                 if skip_condition:
237                         print '    if (__builtin_expect(%s, 1)) {' % (skip_condition)
238                         return 1
239                 else:
240                         return 0
241
242
243         def printSingleFunction(self, f):
244                 self.common_func_print_header(f)
245
246                 if f.fn_parameters != []:
247                         pc_decl = "GLubyte const * pc ="
248                 else:
249                         pc_decl = "(void)"
250
251                 if f.glx_vendorpriv != 0:
252                         print '        %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
253                 else:
254                         print '        %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
255
256                 self.common_emit_args(f, "pc", "    ", 0, 0)
257
258                 if f.needs_reply():
259                         if f.output != None:
260                                 output_size = f.output.p_type.size
261                                 output_str = f.output.name
262                         else:
263                                 output_size = 0
264                                 output_str = "NULL"
265
266                         if f.fn_return_type != 'void':
267                                 return_str = " retval = (%s)" % (f.fn_return_type)
268                         else:
269                                 return_str = " (void)"
270
271                         if f.reply_always_array:
272                                 aa = "GL_TRUE"
273                         else:
274                                 aa = "GL_FALSE"
275
276                         print "       %s read_reply(dpy, %s, %s, %s);" % (return_str, output_size, output_str, aa)
277
278                 print '        UnlockDisplay(dpy); SyncHandle();'
279                 print '    }'
280                 print '    %s' % f.return_string()
281                 print '}'
282                 print ''
283                 return
284
285
286         def printRenderFunction(self, f):
287                 # There is a class of GL functions that take a single pointer
288                 # as a parameter.  This pointer points to a fixed-size chunk
289                 # of data, and the protocol for this functions is very
290                 # regular.  Since they are so regular and there are so many
291                 # of them, special case them with generic functions.  On
292                 # x86, this saves about 26KB in the libGL.so binary.
293
294                 if f.variable_length_parameter() == None and len(f.fn_parameters) == 1:
295                         p = f.fn_parameters[0]
296                         if p.is_pointer:
297                                 [cmdlen, size_string] = f.command_payload_length()
298                                 if cmdlen in self.generic_sizes:
299                                         self.common_func_print_just_header(f)
300                                         print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
301                                         print '}'
302                                         print ''
303                                         return
304
305                 if self.common_func_print_header(f):
306                         indent = "    "
307                         trailer = "    }"
308                 else:
309                         indent = ""
310                         trailer = None
311
312                 if f.can_be_large:
313                         print '%s    if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
314                         print '%s        if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
315                         print '%s            (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
316                         print '%s        }' % (indent)
317                         indent += "    "
318
319                 print '%s    emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
320
321                 self.common_emit_args(f, "gc->pc", indent, 4, 0)
322                 print '%s    gc->pc += cmdlen;' % (indent)
323                 print '%s    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
324
325                 if f.can_be_large:
326                         print '%s}' % (indent)
327                         print '%selse {' % (indent)
328
329                         self.large_emit_begin(indent, f)
330                         offset = self.common_emit_args(f, "pc", indent, 8, 1)
331                         
332                         p = f.variable_length_parameter()
333                         print '%s    __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, offset + 8, p.name, p.size_string())
334                         print '%s}' % (indent)
335
336                 if trailer: print trailer
337                 print '}'
338                 print ''
339                 return
340
341
342 class PrintGlxProtoInit_c(glX_XML.GlxProto):
343         def __init__(self):
344                 glX_XML.GlxProto.__init__(self)
345                 self.last_category = ""
346                 self.license = license.bsd_license_template % ( \
347 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
348 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
349
350
351         def printRealHeader(self):
352                 print """/**
353  * \\file indirect_init.c
354  * Initialize indirect rendering dispatch table.
355  *
356  * \\author Kevin E. Martin <kevin@precisioninsight.com>
357  * \\author Brian Paul <brian@precisioninsight.com>
358  * \\author Ian Romanick <idr@us.ibm.com>
359  */
360
361 #include "indirect_init.h"
362 #include "indirect.h"
363 #include "glapi.h"
364
365
366 /**
367  * No-op function used to initialize functions that have no GLX protocol
368  * support.
369  */
370 static int NoOp(void)
371 {
372     return 0;
373 }
374
375 /**
376  * Create and initialize a new GL dispatch table.  The table is initialized
377  * with GLX indirect rendering protocol functions.
378  */
379 __GLapi * __glXNewIndirectAPI( void )
380 {
381     __GLapi *glAPI;
382     GLuint entries;
383
384     entries = _glapi_get_dispatch_table_size();
385     glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
386
387     /* first, set all entries to point to no-op functions */
388     {
389        int i;
390        void **dispatch = (void **) glAPI;
391        for (i = 0; i < entries; i++) {
392           dispatch[i] = (void *) NoOp;
393        }
394     }
395
396     /* now, initialize the entries we understand */"""
397
398         def printRealFooter(self):
399                 print """
400     return glAPI;
401 }
402 """
403
404         def printFunction(self, f):
405                 if f.fn_offset < 0 or f.ignore: return
406                 
407                 if f.category != self.last_category:
408                         self.last_category = f.category
409                         print ''
410                         print '    /* %s */' % (self.last_category)
411                         print ''
412                         
413                 print '    glAPI->%s = __indirect_gl%s;' % (f.name, f.name)
414
415
416 class PrintGlxProtoInit_h(glX_XML.GlxProto):
417         def __init__(self):
418                 glX_XML.GlxProto.__init__(self)
419                 self.last_category = ""
420                 self.license = license.bsd_license_template % ( \
421 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
422 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
423
424
425         def printRealHeader(self):
426                 print """
427 /**
428  * \\file
429  * Prototypes for indirect rendering functions.
430  *
431  * \\author Kevin E. Martin <kevin@precisioninsight.com>
432  * \\author Ian Romanick <idr@us.ibm.com>
433  */
434
435 #if !defined( _INDIRECT_H_ )
436 #  define _INDIRECT_H_
437
438 """
439                 glX_XML.printVisibility( "HIDDEN", "hidden" )
440
441
442         def printRealFooter(self):
443                 print "#  undef HIDDEN"
444                 print "#endif /* !defined( _INDIRECT_H_ ) */"
445
446         def printFunction(self, f):
447                 if f.fn_offset < 0 or f.ignore: return
448                 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string())
449
450
451 class PrintGlxSizeStubs(glX_XML.GlxProto):
452         def __init__(self):
453                 glX_XML.GlxProto.__init__(self)
454                 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
455                 self.aliases = []
456                 self.glx_enum_sigs = {}
457
458         def printRealHeader(self):
459                 print ''
460                 print '#include <GL/gl.h>'
461                 print '#include "indirect_size.h"'
462                 
463                 print ''
464                 glX_XML.printPure()
465                 print ''
466                 glX_XML.printFastcall()
467                 print ''
468                 glX_XML.printVisibility( "INTERNAL", "internal" )
469                 print ''
470                 print ''
471                 print '#ifdef HAVE_ALIAS'
472                 print '#  define ALIAS2(from,to) \\'
473                 print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
474                 print '        __attribute__ ((alias( # to )));'
475                 print '#  define ALIAS(from,to) ALIAS2( from, __gl ## to ## _size )'
476                 print '#else'
477                 print '#  define ALIAS(from,to) \\'
478                 print '    INTERNAL PURE FASTCALL GLint __gl ## from ## _size( GLenum e ) \\'
479                 print '    { return __gl ## to ## _size( e ); }'
480                 print '#endif'
481                 print ''
482                 print ''
483
484         def printRealFooter(self):
485                 for a in self.aliases:
486                         print a
487
488         def printFunction(self, f):
489                 if self.glx_enum_functions.has_key(f.name):
490                         ef = self.glx_enum_functions[f.name]
491
492                         sig = ef.signature();
493                         if self.glx_enum_sigs.has_key(sig):
494                                 n = self.glx_enum_sigs[sig];
495                                 a = 'ALIAS( %s, %s )' % (f.name, n)
496                                 self.aliases.append(a)
497                         else:
498                                 ef.Print( f.name )
499                                 self.glx_enum_sigs[sig] = f.name;
500
501
502                                 
503 class PrintGlxSizeStubs_h(glX_XML.GlxProto):
504         def __init__(self):
505                 glX_XML.GlxProto.__init__(self)
506                 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004", "IBM")
507                 self.aliases = []
508                 self.glx_enum_sigs = {}
509
510         def printRealHeader(self):
511                 print """
512 /**
513  * \\file
514  * Prototypes for functions used to determine the number of data elements in
515  * various GLX protocol messages.
516  *
517  * \\author Ian Romanick <idr@us.ibm.com>
518  */
519
520 #if !defined( _GLXSIZE_H_ )
521 #  define _GLXSIZE_H_
522
523 """
524                 glX_XML.printPure();
525                 print ''
526                 glX_XML.printFastcall();
527                 print ''
528                 glX_XML.printVisibility( "INTERNAL", "internal" );
529                 print ''
530
531         def printRealFooter(self):
532                 print ''
533                 print "#  undef INTERNAL"
534                 print "#  undef PURE"
535                 print "#  undef FASTCALL"
536                 print "#endif /* !defined( _GLXSIZE_H_ ) */"
537
538
539         def printFunction(self, f):
540                 if self.glx_enum_functions.has_key(f.name):
541                         ef = self.glx_enum_functions[f.name]
542                         print 'extern INTERNAL PURE FASTCALL GLint __gl%s_size(GLenum);' % (f.name)
543
544
545 def show_usage():
546         print "Usage: %s [-f input_file_name] [-m output_mode]" % sys.argv[0]
547         sys.exit(1)
548
549
550 if __name__ == '__main__':
551         file_name = "gl_API.xml"
552
553         try:
554                 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:")
555         except Exception,e:
556                 show_usage()
557
558         mode = "proto"
559         for (arg,val) in args:
560                 if arg == "-f":
561                         file_name = val
562                 elif arg == "-m":
563                         mode = val
564
565         if mode == "proto":
566                 dh = PrintGlxProtoStubs()
567         elif mode == "init_c":
568                 dh = PrintGlxProtoInit_c()
569         elif mode == "init_h":
570                 dh = PrintGlxProtoInit_h()
571         elif mode == "size_c":
572                 dh = PrintGlxSizeStubs()
573         elif mode == "size_h":
574                 dh = PrintGlxSizeStubs_h()
575         else:
576                 show_usage()
577
578         parser = make_parser()
579         parser.setFeature(feature_namespaces, 0)
580         parser.setContentHandler(dh)
581
582         f = open(file_name)
583
584         dh.printHeader()
585         parser.parse(f)
586         dh.printFooter()