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