4f95da3aef7d86ac45739b013cbca8471045d212
[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_parameter_list = func.count_parameter_list
105 self.counter = func.counter
106 self.img_reset = None
107 return
108
109
110 class PrintGlxProtoStubs(glX_XML.GlxProto):
111 def __init__(self):
112 glX_XML.GlxProto.__init__(self)
113 self.last_category = ""
114 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
115 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
116 self.pixel_stubs = {}
117 self.debug = 0
118 return
119
120 def printRealHeader(self):
121 print ''
122 print '#include <GL/gl.h>'
123 print '#include "indirect.h"'
124 print '#include "glxclient.h"'
125 print '#include "indirect_size.h"'
126 print '#include <GL/glxproto.h>'
127 print ''
128 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
129 print ''
130 self.printFastcall()
131 self.printNoinline()
132 print ''
133 print '#if !defined __GNUC__ || __GNUC__ < 3'
134 print '# define __builtin_expect(x, y) x'
135 print '#endif'
136 print ''
137 print '/* If the size and opcode values are known at compile-time, this will, on'
138 print ' * x86 at least, emit them with a single instruction.'
139 print ' */'
140 print '#define emit_header(dest, op, size) \\'
141 print ' do { union { short s[2]; int i; } temp; \\'
142 print ' temp.s[0] = (size); temp.s[1] = (op); \\'
143 print ' *((int *)(dest)) = temp.i; } while(0)'
144 print ''
145 print """static NOINLINE CARD32
146 read_reply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
147 {
148 xGLXSingleReply reply;
149
150 (void) _XReply(dpy, (xReply *) & reply, 0, False);
151 if (size != 0) {
152 if ((reply.length > 0) || reply_is_always_array) {
153 const GLint bytes = (reply_is_always_array)
154 ? (4 * reply.length) : (reply.size * size);
155 const GLint extra = 4 - (bytes & 3);
156
157 _XRead(dpy, dest, bytes);
158 if ( extra < 4 ) {
159 _XEatData(dpy, extra);
160 }
161 }
162 else {
163 (void) memcpy( dest, &(reply.pad3), size);
164 }
165 }
166
167 return reply.retval;
168 }
169
170 static NOINLINE void
171 read_pixel_reply( Display *dpy, __GLXcontext * gc, unsigned max_dim,
172 GLint width, GLint height, GLint depth, GLenum format, GLenum type,
173 void * dest, GLboolean dimensions_in_reply )
174 {
175 xGLXSingleReply reply;
176 GLint size;
177
178 (void) _XReply(dpy, (xReply *) & reply, 0, False);
179
180 if ( dimensions_in_reply ) {
181 width = reply.pad3;
182 height = reply.pad4;
183 depth = reply.pad5;
184
185 if ((height == 0) || (max_dim < 2)) { height = 1; }
186 if ((depth == 0) || (max_dim < 3)) { depth = 1; }
187 }
188
189 size = reply.length * 4;
190 if (size != 0) {
191 void * buf = Xmalloc( size );
192
193 if ( buf == NULL ) {
194 _XEatData(dpy, size);
195 __glXSetError(gc, GL_OUT_OF_MEMORY);
196 }
197 else {
198 const GLint extra = 4 - (size & 3);
199
200 _XRead(dpy, buf, size);
201 if ( extra < 4 ) {
202 _XEatData(dpy, extra);
203 }
204
205 __glEmptyImage(gc, 3, width, height, depth, format, type,
206 buf, dest);
207 Xfree(buf);
208 }
209 }
210 }
211
212 #define X_GLXSingle 0
213
214 static NOINLINE FASTCALL GLubyte *
215 setup_single_request( __GLXcontext * gc, GLint sop, GLint cmdlen )
216 {
217 xGLXSingleReq * req;
218 Display * const dpy = gc->currentDpy;
219
220 (void) __glXFlushRenderBuffer(gc, gc->pc);
221 LockDisplay(dpy);
222 GetReqExtra(GLXSingle, cmdlen, req);
223 req->reqType = gc->majorOpcode;
224 req->contextTag = gc->currentContextTag;
225 req->glxCode = sop;
226 return (GLubyte *)(req) + sz_xGLXSingleReq;
227 }
228
229 static NOINLINE FASTCALL GLubyte *
230 setup_vendor_request( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
231 {
232 xGLXVendorPrivateReq * req;
233 Display * const dpy = gc->currentDpy;
234
235 (void) __glXFlushRenderBuffer(gc, gc->pc);
236 LockDisplay(dpy);
237 GetReqExtra(GLXVendorPrivate, cmdlen, req);
238 req->reqType = gc->majorOpcode;
239 req->glxCode = code;
240 req->vendorCode = vop;
241 req->contextTag = gc->currentContextTag;
242 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
243 }
244
245 const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
246
247 #define zero (__glXDefaultPixelStore+0)
248 #define one (__glXDefaultPixelStore+8)
249 #define default_pixel_store_1D (__glXDefaultPixelStore+4)
250 #define default_pixel_store_1D_size 20
251 #define default_pixel_store_2D (__glXDefaultPixelStore+4)
252 #define default_pixel_store_2D_size 20
253 #define default_pixel_store_3D (__glXDefaultPixelStore+0)
254 #define default_pixel_store_3D_size 36
255 #define default_pixel_store_4D (__glXDefaultPixelStore+0)
256 #define default_pixel_store_4D_size 36
257 """
258
259 for size in self.generic_sizes:
260 self.print_generic_function(size)
261 return
262
263 def printFunction(self, f):
264 if f.client_handcode: return
265
266 if f.glx_rop != 0 or f.vectorequiv != None:
267 if f.image:
268 self.printPixelFunction(f)
269 else:
270 self.printRenderFunction(f)
271 elif f.glx_sop != 0 or f.glx_vendorpriv != 0:
272 self.printSingleFunction(f)
273 else:
274 print "/* Missing GLX protocol for %s. */" % (f.name)
275
276 def print_generic_function(self, n):
277 size = (n + 3) & ~3
278 print """static FASTCALL NOINLINE void
279 generic_%u_byte( GLint rop, const void * ptr )
280 {
281 __GLXcontext * const gc = __glXGetCurrentContext();
282 const GLuint cmdlen = %u;
283
284 emit_header(gc->pc, rop, cmdlen);
285 (void) memcpy((void *)(gc->pc + 4), ptr, %u);
286 gc->pc += cmdlen;
287 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
288 }
289 """ % (n, size + 4, size)
290
291
292 def common_emit_one_arg(self, p, offset, pc, indent, adjust):
293 t = p.p_type
294 if p.is_array():
295 src_ptr = p.name
296 else:
297 src_ptr = "&" + p.name
298
299 print '%s (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
300 % (indent, pc, offset + adjust, src_ptr, p.size_string() )
301
302 def common_emit_args(self, f, pc, indent, adjust, skip_vla):
303 offset = 0
304
305 if skip_vla:
306 r = 1
307 else:
308 r = 2
309
310 for p in f.parameterIterator(1, r):
311 if p.name != f.img_reset:
312 self.common_emit_one_arg(p, offset, pc, indent, adjust)
313 offset += p.size()
314
315 return offset
316
317
318 def pixel_emit_args(self, f, pc, indent, adjust, dim, large):
319 """Emit the arguments for a pixel function. This differs from
320 common_emit_args in that pixel functions may require padding
321 be inserted (i.e., for the missing width field for
322 TexImage1D), and they may also require a 'NULL image' flag
323 be inserted before the image data."""
324
325 offset = 0
326 for p in f.parameterIterator(1, 1):
327 self.common_emit_one_arg(p, offset, pc, indent, adjust)
328 offset += p.size()
329
330 if f.pad_after(p):
331 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust)
332 offset += 4
333
334 if f.image.img_null_flag:
335 if large:
336 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, offset + adjust)
337 else:
338 print '%s (void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (indent, pc, offset + adjust, f.image.name)
339
340 offset += 4
341
342 return offset
343
344
345 def large_emit_begin(self, indent, f, op_name = None):
346 if not op_name:
347 op_name = f.opcode_real_name()
348
349 print '%s const GLint op = %s;' % (indent, op_name)
350 print '%s const GLuint cmdlenLarge = cmdlen + 4;' % (indent)
351 print '%s GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
352 print '%s (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent)
353 print '%s (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent)
354 return
355
356
357 def common_func_print_just_header(self, f):
358 print '#define %s %d' % (f.opcode_name(), f.opcode_value())
359
360 print '%s' % (f.fn_return_type)
361 print '__indirect_gl%s(%s)' % (f.name, f.get_parameter_string())
362 print '{'
363
364
365 def common_func_print_just_start(self, f):
366 print ' __GLXcontext * const gc = __glXGetCurrentContext();'
367
368 # The only reason that single and vendor private commands need
369 # a variable called 'dpy' is becuase they use the SyncHandle
370 # macro. For whatever brain-dead reason, that macro is hard-
371 # coded to use a variable called 'dpy' instead of taking a
372 # parameter.
373
374 if not f.glx_rop:
375 if f.image and f.image.is_output:
376 print ' const __GLXattribute * const state = gc->client_state_private;'
377
378 print ' Display * const dpy = gc->currentDpy;'
379 skip_condition = "dpy != NULL"
380 elif f.can_be_large:
381 skip_condition = "gc->currentDpy != NULL"
382 else:
383 skip_condition = None
384
385
386 if f.fn_return_type != 'void':
387 print ' %s retval = (%s) 0;' % (f.fn_return_type, f.fn_return_type)
388
389 if not f.output_parameter():
390 compsize = self.size_call( f )
391 if compsize:
392 print ' const GLuint compsize = %s;' % (compsize)
393
394 print ' const GLuint cmdlen = %s;' % (f.command_length())
395
396 if f.counter:
397 if skip_condition:
398 skip_condition = "(%s >= 0) && (%s)" % (f.counter, skip_condition)
399 else:
400 skip_condition = "%s >= 0" % (f.counter)
401
402
403 if skip_condition:
404 print ' if (__builtin_expect(%s, 1)) {' % (skip_condition)
405 return 1
406 else:
407 return 0
408
409
410 def common_func_print_header(self, f):
411 self.common_func_print_just_header(f)
412 return self.common_func_print_just_start(f)
413
414
415
416 def printSingleFunction(self, f):
417 self.common_func_print_header(f)
418
419 if self.debug:
420 print ' printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
421
422 if f.fn_parameters != []:
423 pc_decl = "GLubyte const * pc ="
424 else:
425 pc_decl = "(void)"
426
427 if f.glx_vendorpriv != 0:
428 print ' %s setup_vendor_request(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
429 else:
430 print ' %s setup_single_request(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
431
432 self.common_emit_args(f, "pc", " ", 0, 0)
433 if f.image and f.image.is_output:
434 o = f.command_fixed_length() - 4
435 print ' *(int32_t *)(pc + %u) = 0;' % (o)
436 if f.image.img_format != "GL_COLOR_INDEX" or f.image.img_type != "GL_BITMAP":
437 print ' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
438
439 if f.img_reset:
440 print ' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
441
442
443 if f.needs_reply():
444 if f.image and f.image.is_output:
445 [dim, w, h, d, junk] = f.dimensions()
446 if f.dimensions_in_reply:
447 print " read_pixel_reply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, f.image.img_format, f.image.img_type, f.image.name)
448 else:
449 print " read_pixel_reply(dpy, gc, %u, %s, %s, %s, %s, %s, %s, GL_FALSE);" % (dim, w, h, d, f.image.img_format, f.image.img_type, f.image.name)
450 else:
451 if f.output != None:
452 output_size = f.output.p_type.size
453 output_str = f.output.name
454 else:
455 output_size = 0
456 output_str = "NULL"
457
458 if f.fn_return_type != 'void':
459 return_str = " retval = (%s)" % (f.fn_return_type)
460 else:
461 return_str = " (void)"
462
463 if f.reply_always_array:
464 aa = "GL_TRUE"
465 else:
466 aa = "GL_FALSE"
467
468 print " %s read_reply(dpy, %s, %s, %s);" % (return_str, output_size, output_str, aa)
469
470 elif self.debug:
471 # Only emit the extra glFinish call for functions
472 # that don't already require a reply from the server.
473 print ' __indirect_glFinish();'
474
475 if self.debug:
476 print ' printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
477
478
479 print ' UnlockDisplay(dpy); SyncHandle();'
480 print ' }'
481 print ' %s' % f.return_string()
482 print '}'
483 print ''
484 return
485
486
487 def printPixelFunction(self, f):
488 """This function could use some major refactoring. :("""
489
490 # There is a code-space optimization that we can do here.
491 # Functions that are marked img_pad_dimensions have a version
492 # with an odd number of dimensions and an even number of
493 # dimensions. TexSubImage1D and TexSubImage2D are examples.
494 # We can emit a single function that does both, and have the
495 # real functions call the utility function with the correct
496 # parameters.
497 #
498 # The only quirk to this is that utility funcitons will be
499 # generated for 3D and 4D functions, but 4D (e.g.,
500 # GL_SGIS_texture4D) isn't typically supported. This is
501 # probably not an issue. However, it would be possible to
502 # look at the total set of functions and determine if there
503 # is another function that would actually use the utility
504 # function. If not, then fallback to the normal way of
505 # generating code.
506
507 if f.image.img_pad_dimensions:
508 # Determine the hash key and the name for the utility
509 # function that is used to implement the real
510 # function.
511
512 [h, n] = hash_pixel_function(f)
513
514
515 # If the utility function is not yet known, generate
516 # it.
517
518 if not self.pixel_stubs.has_key(h):
519 self.pixel_stubs[h] = n
520 pixel_func = glXPixelFunctionUtility(f, n)
521
522 print 'static void'
523 print '%s( unsigned opcode, unsigned dim, %s )' % (n, pixel_func.get_parameter_string())
524 print '{'
525
526 if self.common_func_print_just_start(pixel_func):
527 indent = " "
528 trailer = " }"
529 else:
530 indent = ""
531 trailer = None
532
533
534 if pixel_func.can_be_large:
535 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
536 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
537 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
538 print '%s }' % (indent)
539 indent += " "
540
541 [dim, width, height, depth, extent] = pixel_func.dimensions()
542 adjust = pixel_func.offset_of_first_parameter() + 4
543
544 print '%s emit_header(gc->pc, opcode, cmdlen);' % (indent)
545
546 offset = self.pixel_emit_args(pixel_func, "gc->pc", indent, adjust, dim, 0)
547
548 s = pixel_func.command_fixed_length()
549
550 pixHeaderPtr = "gc->pc + 4"
551 pcPtr = "gc->pc + %u" % (s + 4)
552
553 if pixel_func.image.img_send_null:
554 condition = '(compsize > 0) && (%s != NULL)' % (pixel_func.image.name)
555 else:
556 condition = 'compsize > 0'
557
558 print '%s if (%s) {' % (indent, condition)
559 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)
560 print '%s }' % (indent)
561 print '%s else {' % (indent)
562 print '%s (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
563 print '%s }' % (indent)
564
565 print '%s gc->pc += cmdlen;' % (indent)
566 print '%s if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
567
568 if f.can_be_large:
569 adjust += 4
570
571 print '%s}' % (indent)
572 print '%selse {' % (indent)
573
574 self.large_emit_begin(indent, pixel_func, "opcode")
575 offset = self.pixel_emit_args(pixel_func, "pc", indent, adjust, dim, 1)
576
577 pixHeaderPtr = "pc + 8"
578 pcPtr = "pc + %u" % (s + 8)
579
580 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)
581
582 print '%s}' % (indent)
583
584 if trailer: print trailer
585 print '}'
586 print ''
587
588
589
590 # Generate the real function as a call to the
591 # utility function.
592
593 self.common_func_print_just_header(f)
594
595 [dim, junk, junk, junk, junk] = f.dimensions()
596
597 p_string = ""
598 for p in gl_XML.glFunction.parameterIterator(f):
599 p_string += ", " + p.name
600
601 if f.pad_after(p):
602 p_string += ", 1"
603
604 print ' %s(%s, %u%s );' % (n, f.opcode_name(), dim, p_string)
605 print '}'
606 print ''
607 return
608
609
610 if self.common_func_print_header(f):
611 indent = " "
612 trailer = " }"
613 else:
614 indent = ""
615 trailer = None
616
617
618 if f.can_be_large:
619 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
620 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
621 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
622 print '%s }' % (indent)
623 indent += " "
624
625 [dim, width, height, depth, extent] = f.dimensions()
626 adjust = f.offset_of_first_parameter() + 4
627
628 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
629
630 offset = self.pixel_emit_args(f, "gc->pc", indent, adjust, dim, 0)
631
632 s = f.command_fixed_length()
633
634 pixHeaderPtr = "gc->pc + 4"
635 pcPtr = "gc->pc + %u" % (s + 4)
636
637 if f.image.img_send_null:
638 condition = '(compsize > 0) && (%s != NULL)' % (f.image.name)
639 else:
640 condition = 'compsize > 0'
641
642 print '%s if (%s) {' % (indent, condition)
643 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)
644 print '%s }' % (indent)
645 print '%s else {' % (indent)
646 print '%s (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
647 print '%s }' % (indent)
648
649 print '%s gc->pc += cmdlen;' % (indent)
650 print '%s if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
651
652 if f.can_be_large:
653 adjust += 4
654
655 print '%s}' % (indent)
656 print '%selse {' % (indent)
657
658 self.large_emit_begin(indent, f)
659 offset = self.pixel_emit_args(f, "pc", indent, adjust, dim, 1)
660
661 pixHeaderPtr = "pc + 8"
662 pcPtr = "pc + %u" % (s + 8)
663
664 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)
665
666 print '%s}' % (indent)
667
668 if trailer: print trailer
669 print '}'
670 print ''
671 return
672
673
674 def printRenderFunction(self, f):
675 # There is a class of GL functions that take a single pointer
676 # as a parameter. This pointer points to a fixed-size chunk
677 # of data, and the protocol for this functions is very
678 # regular. Since they are so regular and there are so many
679 # of them, special case them with generic functions. On
680 # x86, this saves about 26KB in the libGL.so binary.
681
682 if f.variable_length_parameter() == None and len(f.fn_parameters) == 1:
683 p = f.fn_parameters[0]
684 if p.is_pointer:
685 cmdlen = f.command_fixed_length()
686 if cmdlen in self.generic_sizes:
687 self.common_func_print_just_header(f)
688 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
689 print '}'
690 print ''
691 return
692
693 if self.common_func_print_header(f):
694 indent = " "
695 trailer = " }"
696 else:
697 indent = ""
698 trailer = None
699
700 if self.debug:
701 print '%s printf( "Enter %%s...\\n", "gl%s" );' % (indent, f.name)
702
703 if f.can_be_large:
704 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
705 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
706 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
707 print '%s }' % (indent)
708 indent += " "
709
710 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
711
712 self.common_emit_args(f, "gc->pc", indent, 4, 0)
713 print '%s gc->pc += cmdlen;' % (indent)
714 print '%s if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
715
716 if f.can_be_large:
717 print '%s}' % (indent)
718 print '%selse {' % (indent)
719
720 self.large_emit_begin(indent, f)
721 offset = self.common_emit_args(f, "pc", indent, 8, 1)
722
723 p = f.variable_length_parameter()
724 print '%s __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, offset + 8, p.name, p.size_string())
725 print '%s}' % (indent)
726
727 if self.debug:
728 print '%s __indirect_glFinish();' % (indent)
729 print '%s printf( "Exit %%s.\\n", "gl%s" );' % (indent, f.name)
730
731 if trailer: print trailer
732 print '}'
733 print ''
734 return
735
736
737 class PrintGlxProtoInit_c(glX_XML.GlxProto):
738 def __init__(self):
739 glX_XML.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.category != self.last_category:
801 self.last_category = f.category
802 print ''
803 print ' /* %s */' % (self.last_category)
804 print ''
805
806 print ' glAPI->%s = __indirect_gl%s;' % (f.name, f.name)
807
808
809 class PrintGlxProtoInit_h(glX_XML.GlxProto):
810 def __init__(self):
811 glX_XML.GlxProto.__init__(self)
812 self.last_category = ""
813 self.license = license.bsd_license_template % ( \
814 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
815 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
816 self.header_tag = "_INDIRECT_H_"
817
818 def printRealHeader(self):
819 print """/**
820 * \\file
821 * Prototypes for indirect rendering functions.
822 *
823 * \\author Kevin E. Martin <kevin@precisioninsight.com>
824 * \\author Ian Romanick <idr@us.ibm.com>
825 */
826 """
827 self.printVisibility( "HIDDEN", "hidden" )
828
829
830 def printFunction(self, f):
831 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (f.fn_return_type, f.name, f.get_parameter_string())
832
833
834 def show_usage():
835 print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0]
836 print " -m output_mode Output mode can be one of 'proto', 'init_c' or 'init_h'."
837 print " -d Enable extra debug information in the generated code."
838 sys.exit(1)
839
840
841 if __name__ == '__main__':
842 file_name = "gl_API.xml"
843
844 try:
845 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:d")
846 except Exception,e:
847 show_usage()
848
849 debug = 0
850 mode = "proto"
851 for (arg,val) in args:
852 if arg == "-f":
853 file_name = val
854 elif arg == "-m":
855 mode = val
856 elif arg == "-d":
857 debug = 1
858
859 if mode == "proto":
860 dh = PrintGlxProtoStubs()
861 elif mode == "init_c":
862 dh = PrintGlxProtoInit_c()
863 elif mode == "init_h":
864 dh = PrintGlxProtoInit_h()
865 else:
866 show_usage()
867
868 parser = make_parser()
869 parser.setFeature(feature_namespaces, 0)
870 parser.setContentHandler(dh)
871
872 f = open(file_name)
873
874 dh.debug = debug
875 dh.printHeader()
876 parser.parse(f)
877 dh.printFooter()