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