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