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