Divide categories into four groups as they are processed from the XML. Add
[mesa.git] / src / mesa / glapi / glX_proto_send.py
1 #!/usr/bin/env python
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 # Jeremy Kolb <jkolb@brandeis.edu>
28
29 import gl_XML, glX_XML, glX_proto_common, license
30 import sys, getopt, copy, string
31
32 def convertStringForXCB(str):
33 tmp = ""
34 special = [ "ARB" ]
35 i = 0
36 while i < len(str):
37 if str[i:i+3] in special:
38 tmp = '%s_%s' % (tmp, string.lower(str[i:i+3]))
39 i = i + 2;
40 elif str[i].isupper():
41 tmp = '%s_%s' % (tmp, string.lower(str[i]))
42 else:
43 tmp = '%s%s' % (tmp, str[i])
44 i += 1
45 return tmp
46
47 def hash_pixel_function(func):
48 """Generate a 'unique' key for a pixel function. The key is based on
49 the parameters written in the command packet. This includes any
50 padding that might be added for the original function and the 'NULL
51 image' flag."""
52
53
54 h = ""
55 hash_pre = ""
56 hash_suf = ""
57 for param in func.parameterIterateGlxSend():
58 if param.is_image():
59 [dim, junk, junk, junk, junk] = param.get_dimensions()
60
61 d = (dim + 1) & ~1
62 hash_pre = "%uD%uD_" % (d - 1, d)
63
64 if param.img_null_flag:
65 hash_suf = "_NF"
66
67 h += "%u" % (param.size())
68
69 if func.pad_after(param):
70 h += "4"
71
72
73 n = func.name.replace("%uD" % (dim), "")
74 n = "__glx_%s_%uD%uD" % (n, d - 1, d)
75
76 h = hash_pre + h + hash_suf
77 return [h, n]
78
79
80 class glx_pixel_function_stub(glX_XML.glx_function):
81 """Dummy class used to generate pixel "utility" functions that are
82 shared by multiple dimension image functions. For example, these
83 objects are used to generate shared functions used to send GLX
84 protocol for TexImage1D and TexImage2D, TexSubImage1D and
85 TexSubImage2D, etc."""
86
87 def __init__(self, func, name):
88 # The parameters to the utility function are the same as the
89 # parameters to the real function except for the added "pad"
90 # parameters.
91
92 self.name = name
93 self.images = []
94 self.parameters = []
95 self.parameters_by_name = {}
96 for _p in func.parameterIterator():
97 p = copy.copy(_p)
98 self.parameters.append(p)
99 self.parameters_by_name[ p.name ] = p
100
101
102 if p.is_image():
103 self.images.append(p)
104 p.height = "height"
105
106 if p.img_yoff == None:
107 p.img_yoff = "yoffset"
108
109 if p.depth:
110 if p.extent == None:
111 p.extent = "extent"
112
113 if p.img_woff == None:
114 p.img_woff = "woffset"
115
116
117 pad_name = func.pad_after(p)
118 if pad_name:
119 pad = copy.copy(p)
120 pad.name = pad_name
121 self.parameters.append(pad)
122 self.parameters_by_name[ pad.name ] = pad
123
124
125 self.return_type = func.return_type
126
127 self.glx_rop = ~0
128 self.glx_sop = 0
129 self.glx_vendorpriv = 0
130
131 self.glx_doubles_in_order = func.glx_doubles_in_order
132
133 self.vectorequiv = None
134 self.output = None
135 self.can_be_large = func.can_be_large
136 self.reply_always_array = func.reply_always_array
137 self.dimensions_in_reply = func.dimensions_in_reply
138 self.img_reset = None
139
140 self.server_handcode = 0
141 self.client_handcode = 0
142 self.ignore = 0
143
144 self.count_parameter_list = func.count_parameter_list
145 self.counter_list = func.counter_list
146 self.offsets_calculated = 0
147 return
148
149
150 class PrintGlxProtoStubs(glX_proto_common.glx_print_proto):
151 def __init__(self):
152 glX_proto_common.glx_print_proto.__init__(self)
153 self.name = "glX_proto_send.py (from Mesa)"
154 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
155
156
157 self.last_category = ""
158 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
159 self.pixel_stubs = {}
160 self.debug = 0
161 return
162
163 def printRealHeader(self):
164 print ''
165 print '#include <GL/gl.h>'
166 print '#include "indirect.h"'
167 print '#include "glxclient.h"'
168 print '#include "indirect_size.h"'
169 print '#include <GL/glxproto.h>'
170 print '#ifdef USE_XCB'
171 print '#include <X11/xcl.h>'
172 print '#include <xcb/xcb.h>'
173 print '#include <xcb/glx.h>'
174 print '#endif /* USE_XCB */'
175
176 print ''
177 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
178 print ''
179 self.printFastcall()
180 self.printNoinline()
181 print ''
182 print '#if !defined __GNUC__ || __GNUC__ < 3'
183 print '# define __builtin_expect(x, y) x'
184 print '#endif'
185 print ''
186 print '/* If the size and opcode values are known at compile-time, this will, on'
187 print ' * x86 at least, emit them with a single instruction.'
188 print ' */'
189 print '#define emit_header(dest, op, size) \\'
190 print ' do { union { short s[2]; int i; } temp; \\'
191 print ' temp.s[0] = (size); temp.s[1] = (op); \\'
192 print ' *((int *)(dest)) = temp.i; } while(0)'
193 print ''
194 print """NOINLINE CARD32
195 __glXReadReply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
196 {
197 xGLXSingleReply reply;
198
199 (void) _XReply(dpy, (xReply *) & reply, 0, False);
200 if (size != 0) {
201 if ((reply.length > 0) || reply_is_always_array) {
202 const GLint bytes = (reply_is_always_array)
203 ? (4 * reply.length) : (reply.size * size);
204 const GLint extra = 4 - (bytes & 3);
205
206 _XRead(dpy, dest, bytes);
207 if ( extra < 4 ) {
208 _XEatData(dpy, extra);
209 }
210 }
211 else {
212 (void) memcpy( dest, &(reply.pad3), size);
213 }
214 }
215
216 return reply.retval;
217 }
218
219 NOINLINE void
220 __glXReadPixelReply( Display *dpy, __GLXcontext * gc, unsigned max_dim,
221 GLint width, GLint height, GLint depth, GLenum format, GLenum type,
222 void * dest, GLboolean dimensions_in_reply )
223 {
224 xGLXSingleReply reply;
225 GLint size;
226
227 (void) _XReply(dpy, (xReply *) & reply, 0, False);
228
229 if ( dimensions_in_reply ) {
230 width = reply.pad3;
231 height = reply.pad4;
232 depth = reply.pad5;
233
234 if ((height == 0) || (max_dim < 2)) { height = 1; }
235 if ((depth == 0) || (max_dim < 3)) { depth = 1; }
236 }
237
238 size = reply.length * 4;
239 if (size != 0) {
240 void * buf = Xmalloc( size );
241
242 if ( buf == NULL ) {
243 _XEatData(dpy, size);
244 __glXSetError(gc, GL_OUT_OF_MEMORY);
245 }
246 else {
247 const GLint extra = 4 - (size & 3);
248
249 _XRead(dpy, buf, size);
250 if ( extra < 4 ) {
251 _XEatData(dpy, extra);
252 }
253
254 __glEmptyImage(gc, 3, width, height, depth, format, type,
255 buf, dest);
256 Xfree(buf);
257 }
258 }
259 }
260
261 #define X_GLXSingle 0
262
263 NOINLINE FASTCALL GLubyte *
264 __glXSetupSingleRequest( __GLXcontext * gc, GLint sop, GLint cmdlen )
265 {
266 xGLXSingleReq * req;
267 Display * const dpy = gc->currentDpy;
268
269 (void) __glXFlushRenderBuffer(gc, gc->pc);
270 LockDisplay(dpy);
271 GetReqExtra(GLXSingle, cmdlen, req);
272 req->reqType = gc->majorOpcode;
273 req->contextTag = gc->currentContextTag;
274 req->glxCode = sop;
275 return (GLubyte *)(req) + sz_xGLXSingleReq;
276 }
277
278 NOINLINE FASTCALL GLubyte *
279 __glXSetupVendorRequest( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
280 {
281 xGLXVendorPrivateReq * req;
282 Display * const dpy = gc->currentDpy;
283
284 (void) __glXFlushRenderBuffer(gc, gc->pc);
285 LockDisplay(dpy);
286 GetReqExtra(GLXVendorPrivate, cmdlen, req);
287 req->reqType = gc->majorOpcode;
288 req->glxCode = code;
289 req->vendorCode = vop;
290 req->contextTag = gc->currentContextTag;
291 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
292 }
293
294 const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
295
296 #define zero (__glXDefaultPixelStore+0)
297 #define one (__glXDefaultPixelStore+8)
298 #define default_pixel_store_1D (__glXDefaultPixelStore+4)
299 #define default_pixel_store_1D_size 20
300 #define default_pixel_store_2D (__glXDefaultPixelStore+4)
301 #define default_pixel_store_2D_size 20
302 #define default_pixel_store_3D (__glXDefaultPixelStore+0)
303 #define default_pixel_store_3D_size 36
304 #define default_pixel_store_4D (__glXDefaultPixelStore+0)
305 #define default_pixel_store_4D_size 36
306 """
307
308 for size in self.generic_sizes:
309 self.print_generic_function(size)
310 return
311
312
313 def printBody(self, api):
314
315 self.pixel_stubs = {}
316 generated_stubs = []
317
318 for func in api.functionIterateGlx():
319 if func.client_handcode: continue
320
321 # If the function is a pixel function with a certain
322 # GLX protocol signature, create a fake stub function
323 # for it. For example, create a single stub function
324 # that is used to implement both glTexImage1D and
325 # glTexImage2D.
326
327 if func.glx_rop != 0:
328 do_it = 0
329 for image in func.get_images():
330 if image.img_pad_dimensions:
331 do_it = 1
332 break
333
334
335 if do_it:
336 [h, n] = hash_pixel_function(func)
337
338
339 self.pixel_stubs[ func.name ] = n
340 if h not in generated_stubs:
341 generated_stubs.append(h)
342
343 fake_func = glx_pixel_function_stub( func, n )
344 self.printFunction( fake_func )
345
346
347 self.printFunction( func )
348
349 return
350
351
352 def printFunction(self, func):
353 if func.glx_rop == ~0:
354 print 'static %s' % (func.return_type)
355 print '%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())
356 else:
357 print '#define %s %d' % (func.opcode_name(), func.opcode_value())
358
359 print '%s' % (func.return_type)
360 print '__indirect_gl%s(%s)' % (func.name, func.get_parameter_string())
361
362
363 print '{'
364
365
366 if func.glx_rop != 0 or func.vectorequiv != None:
367 if len(func.images):
368 self.printPixelFunction(func)
369 else:
370 self.printRenderFunction(func)
371 elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
372 self.printSingleFunction(func)
373 pass
374 else:
375 print "/* Missing GLX protocol for %s. */" % (func.name)
376
377 print '}'
378 print ''
379
380 return
381
382
383 def print_generic_function(self, n):
384 size = (n + 3) & ~3
385 print """static FASTCALL NOINLINE void
386 generic_%u_byte( GLint rop, const void * ptr )
387 {
388 __GLXcontext * const gc = __glXGetCurrentContext();
389 const GLuint cmdlen = %u;
390
391 emit_header(gc->pc, rop, cmdlen);
392 (void) memcpy((void *)(gc->pc + 4), ptr, %u);
393 gc->pc += cmdlen;
394 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
395 }
396 """ % (n, size + 4, size)
397 return
398
399
400 def common_emit_one_arg(self, p, pc, indent, adjust, extra_offset):
401 if p.is_array():
402 src_ptr = p.name
403 else:
404 src_ptr = "&" + p.name
405
406 if not extra_offset:
407 print '%s (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
408 % (indent, pc, p.offset + adjust, src_ptr, p.size_string() )
409 else:
410 print '%s (void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \
411 % (indent, pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() )
412
413 def common_emit_args(self, f, pc, indent, adjust, skip_vla):
414 extra_offset = None
415
416 for p in f.parameterIterateGlxSend( not skip_vla ):
417 if p.name != f.img_reset:
418 self.common_emit_one_arg(p, pc, indent, adjust, extra_offset)
419
420 if p.is_variable_length():
421 temp = p.size_string()
422 if extra_offset:
423 extra_offset += " + %s" % (temp)
424 else:
425 extra_offset = temp
426
427 return
428
429
430 def pixel_emit_args(self, f, pc, indent, large):
431 """Emit the arguments for a pixel function. This differs from
432 common_emit_args in that pixel functions may require padding
433 be inserted (i.e., for the missing width field for
434 TexImage1D), and they may also require a 'NULL image' flag
435 be inserted before the image data."""
436
437 if large:
438 adjust = 8
439 else:
440 adjust = 4
441
442 for param in f.parameterIterateGlxSend():
443 if not param.is_image():
444 self.common_emit_one_arg(param, pc, indent, adjust, None)
445
446 if f.pad_after(param):
447 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, (param.offset + param.size()) + adjust)
448
449 else:
450 [dim, width, height, depth, extent] = param.get_dimensions()
451 if f.glx_rop == ~0:
452 dim_str = "dim"
453 else:
454 dim_str = str(dim)
455
456 if param.img_null_flag:
457 if large:
458 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, (param.offset - 4) + adjust)
459 else:
460 print '%s (void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (indent, pc, (param.offset - 4) + adjust, param.name)
461
462
463 pixHeaderPtr = "%s + %u" % (pc, adjust)
464 pcPtr = "%s + %u" % (pc, param.offset + adjust)
465
466 if not large:
467 if param.img_send_null:
468 condition = '(compsize > 0) && (%s != NULL)' % (param.name)
469 else:
470 condition = 'compsize > 0'
471
472 print '%s if (%s) {' % (indent, condition)
473 print '%s (*gc->fillImage)(gc, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
474 print '%s }' % (indent)
475 print '%s else {' % (indent)
476 print '%s (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
477 print '%s }' % (indent)
478 else:
479 print '%s __glXSendLargeImage(gc, compsize, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
480
481 return
482
483
484 def large_emit_begin(self, indent, f, op_name = None):
485 if not op_name:
486 op_name = f.opcode_real_name()
487
488 print '%s const GLint op = %s;' % (indent, op_name)
489 print '%s const GLuint cmdlenLarge = cmdlen + 4;' % (indent)
490 print '%s GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
491 print '%s (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent)
492 print '%s (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent)
493 return
494
495
496 def common_func_print_just_start(self, f):
497 print ' __GLXcontext * const gc = __glXGetCurrentContext();'
498
499 # The only reason that single and vendor private commands need
500 # a variable called 'dpy' is becuase they use the SyncHandle
501 # macro. For whatever brain-dead reason, that macro is hard-
502 # coded to use a variable called 'dpy' instead of taking a
503 # parameter.
504
505 # FIXME Simplify the logic related to skip_condition and
506 # FIXME condition_list in this function. Basically, remove
507 # FIXME skip_condition, and just append the "dpy != NULL" type
508 # FIXME condition to condition_list from the start. The only
509 # FIXME reason it's done in this confusing way now is to
510 # FIXME minimize the diffs in the generated code.
511
512 if not f.glx_rop:
513 for p in f.parameterIterateOutputs():
514 if p.is_image():
515 print ' const __GLXattribute * const state = gc->client_state_private;'
516 break
517
518 print ' Display * const dpy = gc->currentDpy;'
519 skip_condition = "dpy != NULL"
520 elif f.can_be_large:
521 skip_condition = "gc->currentDpy != NULL"
522 else:
523 skip_condition = None
524
525
526 if f.return_type != 'void':
527 print ' %s retval = (%s) 0;' % (f.return_type, f.return_type)
528
529
530 self.emit_packet_size_calculation(f, 0)
531
532 condition_list = []
533 for p in f.parameterIterateCounters():
534 condition_list.append( "%s >= 0" % (p.name) )
535
536 if skip_condition:
537 condition_list.append( skip_condition )
538
539 if len( condition_list ) > 0:
540 if len( condition_list ) > 1:
541 skip_condition = "(%s)" % (string.join( condition_list, ") && (" ))
542 else:
543 skip_condition = "%s" % (condition_list.pop(0))
544
545 print ' if (__builtin_expect(%s, 1)) {' % (skip_condition)
546 return 1
547 else:
548 return 0
549
550
551 def printSingleFunction(self, f):
552 self.common_func_print_just_start(f)
553
554 if self.debug:
555 print ' printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
556
557 if f.glx_vendorpriv == 0:
558
559 # XCB specific:
560 print '#ifdef USE_XCB'
561 if self.debug:
562 print ' printf("\\tUsing XCB.\\n");'
563 print ' xcb_connection_t *c = XGetXCBConnection(dpy);'
564 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
565 xcb_name = 'xcb_glx%s' % convertStringForXCB(f.name)
566
567 iparams=[]
568 extra_iparams = []
569 output = None
570 for p in f.parameterIterator():
571 if p.is_output:
572 output = p
573
574 if p.is_image():
575 if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP":
576 extra_iparams.append("state->storePack.swapEndian")
577 else:
578 extra_iparams.append("0")
579
580 # Hardcode this in. lsb_first param (apparently always GL_FALSE)
581 # also present in GetPolygonStipple, but taken care of above.
582 if xcb_name == "xcb_glx_read_pixels":
583 extra_iparams.append("0")
584 else:
585 iparams.append(p.name)
586
587
588 xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams))
589
590 if f.needs_reply():
591 print ' %s_reply_t *reply = %s_reply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request)
592 if output and f.reply_always_array:
593 print ' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
594
595 elif output and not f.reply_always_array:
596 if not output.is_image():
597 print ' if (%s_data_length(reply) == 0)' % (xcb_name)
598 print ' (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)
599 print ' else'
600 print ' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
601
602
603 if f.return_type != 'void':
604 print ' retval = reply->ret_val;'
605 print ' free(reply);'
606 else:
607 print ' ' + xcb_request + ';'
608 print '#else'
609 # End of XCB specific.
610
611
612 if f.parameters != []:
613 pc_decl = "GLubyte const * pc ="
614 else:
615 pc_decl = "(void)"
616
617 if f.glx_vendorpriv != 0:
618 print ' %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
619 else:
620 print ' %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
621
622 self.common_emit_args(f, "pc", " ", 0, 0)
623
624 images = f.get_images()
625
626 for img in images:
627 if img.is_output:
628 o = f.command_fixed_length() - 4
629 print ' *(int32_t *)(pc + %u) = 0;' % (o)
630 if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
631 print ' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
632
633 if f.img_reset:
634 print ' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
635
636
637 return_name = ''
638 if f.needs_reply():
639 if f.return_type != 'void':
640 return_name = " retval"
641 return_str = " retval = (%s)" % (f.return_type)
642 else:
643 return_str = " (void)"
644
645 got_reply = 0
646
647 for p in f.parameterIterateOutputs():
648 if p.is_image():
649 [dim, w, h, d, junk] = p.get_dimensions()
650 if f.dimensions_in_reply:
651 print " __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)
652 else:
653 print " __glXReadPixelReply(dpy, gc, %u, %s, %s, %s, %s, %s, %s, GL_FALSE);" % (dim, w, h, d, p.img_format, p.img_type, p.name)
654
655 got_reply = 1
656 else:
657 if f.reply_always_array:
658 aa = "GL_TRUE"
659 else:
660 aa = "GL_FALSE"
661
662 # gl_parameter.size() returns the size
663 # of the entire data item. If the
664 # item is a fixed-size array, this is
665 # the size of the whole array. This
666 # is not what __glXReadReply wants. It
667 # wants the size of a single data
668 # element in the reply packet.
669 # Dividing by the array size (1 for
670 # non-arrays) gives us this.
671
672 s = p.size() / p.get_element_count()
673 print " %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)
674 got_reply = 1
675
676
677 # If a reply wasn't read to fill an output parameter,
678 # read a NULL reply to get the return value.
679
680 if not got_reply:
681 print " %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)
682
683
684 elif self.debug:
685 # Only emit the extra glFinish call for functions
686 # that don't already require a reply from the server.
687 print ' __indirect_glFinish();'
688
689 if self.debug:
690 print ' printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
691
692
693 print ' UnlockDisplay(dpy); SyncHandle();'
694
695 if f.glx_vendorpriv == 0:
696 print '#endif /* USE_XCB */'
697
698 print ' }'
699 print ' return%s;' % (return_name)
700 return
701
702
703 def printPixelFunction(self, f):
704 if self.pixel_stubs.has_key( f.name ):
705 # Normally gl_function::get_parameter_string could be
706 # used. However, this call needs to have the missing
707 # dimensions (e.g., a fake height value for
708 # glTexImage1D) added in.
709
710 p_string = ""
711 for param in f.parameterIterateGlxSend():
712 p_string += ", " + param.name
713
714 if param.is_image():
715 [dim, junk, junk, junk, junk] = param.get_dimensions()
716
717 if f.pad_after(param):
718 p_string += ", 1"
719
720 print ' %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)
721 return
722
723
724 if self.common_func_print_just_start(f):
725 indent = " "
726 trailer = " }"
727 else:
728 indent = ""
729 trailer = None
730
731
732 if f.can_be_large:
733 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
734 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
735 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
736 print '%s }' % (indent)
737 indent += " "
738
739 if f.glx_rop == ~0:
740 opcode = "opcode"
741 else:
742 opcode = f.opcode_real_name()
743
744 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, opcode)
745
746 self.pixel_emit_args( f, "gc->pc", indent, 0 )
747 print '%s gc->pc += cmdlen;' % (indent)
748 print '%s if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
749
750 if f.can_be_large:
751 print '%s}' % (indent)
752 print '%selse {' % (indent)
753
754 self.large_emit_begin(indent, f, opcode)
755 self.pixel_emit_args( f, "pc", indent, 1 )
756
757 print '%s}' % (indent)
758
759 if trailer: print trailer
760 return
761
762
763 def printRenderFunction(self, f):
764 # There is a class of GL functions that take a single pointer
765 # as a parameter. This pointer points to a fixed-size chunk
766 # of data, and the protocol for this functions is very
767 # regular. Since they are so regular and there are so many
768 # of them, special case them with generic functions. On
769 # x86, this saves about 26KB in the libGL.so binary.
770
771 if f.variable_length_parameter() == None and len(f.parameters) == 1:
772 p = f.parameters[0]
773 if p.is_pointer():
774 cmdlen = f.command_fixed_length()
775 if cmdlen in self.generic_sizes:
776 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
777 return
778
779 if self.common_func_print_just_start(f):
780 indent = " "
781 trailer = " }"
782 else:
783 indent = ""
784 trailer = None
785
786 if self.debug:
787 print '%s printf( "Enter %%s...\\n", "gl%s" );' % (indent, f.name)
788
789 if f.can_be_large:
790 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
791 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
792 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
793 print '%s }' % (indent)
794 indent += " "
795
796 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
797
798 self.common_emit_args(f, "gc->pc", indent, 4, 0)
799 print '%s gc->pc += cmdlen;' % (indent)
800 print '%s if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
801
802 if f.can_be_large:
803 print '%s}' % (indent)
804 print '%selse {' % (indent)
805
806 self.large_emit_begin(indent, f)
807 self.common_emit_args(f, "pc", indent, 8, 1)
808
809 p = f.variable_length_parameter()
810 print '%s __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, p.offset + 8, p.name, p.size_string())
811 print '%s}' % (indent)
812
813 if self.debug:
814 print '%s __indirect_glFinish();' % (indent)
815 print '%s printf( "Exit %%s.\\n", "gl%s" );' % (indent, f.name)
816
817 if trailer: print trailer
818 return
819
820
821 class PrintGlxProtoInit_c(gl_XML.gl_print_base):
822 def __init__(self):
823 gl_XML.gl_print_base.__init__(self)
824
825 self.name = "glX_proto_send.py (from Mesa)"
826 self.license = license.bsd_license_template % ( \
827 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
828 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
829 return
830
831
832 def printRealHeader(self):
833 print """/**
834 * \\file indirect_init.c
835 * Initialize indirect rendering dispatch table.
836 *
837 * \\author Kevin E. Martin <kevin@precisioninsight.com>
838 * \\author Brian Paul <brian@precisioninsight.com>
839 * \\author Ian Romanick <idr@us.ibm.com>
840 */
841
842 #include "indirect_init.h"
843 #include "indirect.h"
844 #include "glapi.h"
845
846
847 /**
848 * No-op function used to initialize functions that have no GLX protocol
849 * support.
850 */
851 static int NoOp(void)
852 {
853 return 0;
854 }
855
856 /**
857 * Create and initialize a new GL dispatch table. The table is initialized
858 * with GLX indirect rendering protocol functions.
859 */
860 __GLapi * __glXNewIndirectAPI( void )
861 {
862 __GLapi *glAPI;
863 GLuint entries;
864
865 entries = _glapi_get_dispatch_table_size();
866 glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
867
868 /* first, set all entries to point to no-op functions */
869 {
870 int i;
871 void **dispatch = (void **) glAPI;
872 for (i = 0; i < entries; i++) {
873 dispatch[i] = (void *) NoOp;
874 }
875 }
876
877 /* now, initialize the entries we understand */"""
878
879 def printRealFooter(self):
880 print """
881 return glAPI;
882 }
883 """
884 return
885
886
887 def printBody(self, api):
888 for [name, number] in api.categoryIterate():
889 if number != None:
890 preamble = '\n /* %3u. %s */\n\n' % (int(number), name)
891 else:
892 preamble = '\n /* %s */\n\n' % (name)
893
894 for func in api.functionIterateByCategory(name):
895 if func.client_supported_for_indirect():
896 print '%s glAPI->%s = __indirect_gl%s;' % (preamble, func.name, func.name)
897 preamble = ''
898
899 return
900
901
902 class PrintGlxProtoInit_h(gl_XML.gl_print_base):
903 def __init__(self):
904 gl_XML.gl_print_base.__init__(self)
905
906 self.name = "glX_proto_send.py (from Mesa)"
907 self.license = license.bsd_license_template % ( \
908 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
909 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
910 self.header_tag = "_INDIRECT_H_"
911
912 self.last_category = ""
913 return
914
915
916 def printRealHeader(self):
917 print """/**
918 * \\file
919 * Prototypes for indirect rendering functions.
920 *
921 * \\author Kevin E. Martin <kevin@precisioninsight.com>
922 * \\author Ian Romanick <idr@us.ibm.com>
923 */
924 """
925 self.printVisibility( "HIDDEN", "hidden" )
926 self.printFastcall()
927 self.printNoinline()
928
929 print """
930 #include "glxclient.h"
931
932 extern HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
933 void * dest, GLboolean reply_is_always_array );
934
935 extern HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
936 __GLXcontext * gc, unsigned max_dim, GLint width, GLint height,
937 GLint depth, GLenum format, GLenum type, void * dest,
938 GLboolean dimensions_in_reply );
939
940 extern HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
941 __GLXcontext * gc, GLint sop, GLint cmdlen );
942
943 extern HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
944 __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen );
945 """
946
947
948 def printBody(self, api):
949 for func in api.functionIterateGlx():
950 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, func.get_parameter_string())
951
952
953 def show_usage():
954 print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0]
955 print " -m output_mode Output mode can be one of 'proto', 'init_c' or 'init_h'."
956 print " -d Enable extra debug information in the generated code."
957 sys.exit(1)
958
959
960 if __name__ == '__main__':
961 file_name = "gl_API.xml"
962
963 try:
964 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:d")
965 except Exception,e:
966 show_usage()
967
968 debug = 0
969 mode = "proto"
970 for (arg,val) in args:
971 if arg == "-f":
972 file_name = val
973 elif arg == "-m":
974 mode = val
975 elif arg == "-d":
976 debug = 1
977
978 if mode == "proto":
979 printer = PrintGlxProtoStubs()
980 elif mode == "init_c":
981 printer = PrintGlxProtoInit_c()
982 elif mode == "init_h":
983 printer = PrintGlxProtoInit_h()
984 else:
985 show_usage()
986
987
988 printer.debug = debug
989 api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() )
990
991 printer.Print( api )