Fix a few typos
[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 <GL/glxproto.h>'
171 print '#include <X11/Xlib-xcb.h>'
172 print '#include <xcb/xcb.h>'
173 print '#include <xcb/glx.h>'
174
175 print ''
176 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
177 print ''
178 self.printFastcall()
179 self.printNoinline()
180 print ''
181 print '#ifndef __GNUC__'
182 print '# define __builtin_expect(x, y) x'
183 print '#endif'
184 print ''
185 print '/* If the size and opcode values are known at compile-time, this will, on'
186 print ' * x86 at least, emit them with a single instruction.'
187 print ' */'
188 print '#define emit_header(dest, op, size) \\'
189 print ' do { union { short s[2]; int i; } temp; \\'
190 print ' temp.s[0] = (size); temp.s[1] = (op); \\'
191 print ' *((int *)(dest)) = temp.i; } while(0)'
192 print ''
193 print """NOINLINE CARD32
194 __glXReadReply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
195 {
196 xGLXSingleReply reply;
197
198 (void) _XReply(dpy, (xReply *) & reply, 0, False);
199 if (size != 0) {
200 if ((reply.length > 0) || reply_is_always_array) {
201 const GLint bytes = (reply_is_always_array)
202 ? (4 * reply.length) : (reply.size * size);
203 const GLint extra = 4 - (bytes & 3);
204
205 _XRead(dpy, dest, bytes);
206 if ( extra < 4 ) {
207 _XEatData(dpy, extra);
208 }
209 }
210 else {
211 (void) memcpy( dest, &(reply.pad3), size);
212 }
213 }
214
215 return reply.retval;
216 }
217
218 NOINLINE void
219 __glXReadPixelReply( Display *dpy, struct glx_context * gc, unsigned max_dim,
220 GLint width, GLint height, GLint depth, GLenum format, GLenum type,
221 void * dest, GLboolean dimensions_in_reply )
222 {
223 xGLXSingleReply reply;
224 GLint size;
225
226 (void) _XReply(dpy, (xReply *) & reply, 0, False);
227
228 if ( dimensions_in_reply ) {
229 width = reply.pad3;
230 height = reply.pad4;
231 depth = reply.pad5;
232
233 if ((height == 0) || (max_dim < 2)) { height = 1; }
234 if ((depth == 0) || (max_dim < 3)) { depth = 1; }
235 }
236
237 size = reply.length * 4;
238 if (size != 0) {
239 void * buf = malloc( size );
240
241 if ( buf == NULL ) {
242 _XEatData(dpy, size);
243 __glXSetError(gc, GL_OUT_OF_MEMORY);
244 }
245 else {
246 const GLint extra = 4 - (size & 3);
247
248 _XRead(dpy, buf, size);
249 if ( extra < 4 ) {
250 _XEatData(dpy, extra);
251 }
252
253 __glEmptyImage(gc, 3, width, height, depth, format, type,
254 buf, dest);
255 free(buf);
256 }
257 }
258 }
259
260 #define X_GLXSingle 0
261
262 NOINLINE FASTCALL GLubyte *
263 __glXSetupSingleRequest( struct glx_context * gc, GLint sop, GLint cmdlen )
264 {
265 xGLXSingleReq * req;
266 Display * const dpy = gc->currentDpy;
267
268 (void) __glXFlushRenderBuffer(gc, gc->pc);
269 LockDisplay(dpy);
270 GetReqExtra(GLXSingle, cmdlen, req);
271 req->reqType = gc->majorOpcode;
272 req->contextTag = gc->currentContextTag;
273 req->glxCode = sop;
274 return (GLubyte *)(req) + sz_xGLXSingleReq;
275 }
276
277 NOINLINE FASTCALL GLubyte *
278 __glXSetupVendorRequest( struct glx_context * gc, GLint code, GLint vop, GLint cmdlen )
279 {
280 xGLXVendorPrivateReq * req;
281 Display * const dpy = gc->currentDpy;
282
283 (void) __glXFlushRenderBuffer(gc, gc->pc);
284 LockDisplay(dpy);
285 GetReqExtra(GLXVendorPrivate, cmdlen, req);
286 req->reqType = gc->majorOpcode;
287 req->glxCode = code;
288 req->vendorCode = vop;
289 req->contextTag = gc->currentContextTag;
290 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
291 }
292
293 const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
294
295 #define zero (__glXDefaultPixelStore+0)
296 #define one (__glXDefaultPixelStore+8)
297 #define default_pixel_store_1D (__glXDefaultPixelStore+4)
298 #define default_pixel_store_1D_size 20
299 #define default_pixel_store_2D (__glXDefaultPixelStore+4)
300 #define default_pixel_store_2D_size 20
301 #define default_pixel_store_3D (__glXDefaultPixelStore+0)
302 #define default_pixel_store_3D_size 36
303 #define default_pixel_store_4D (__glXDefaultPixelStore+0)
304 #define default_pixel_store_4D_size 36
305 """
306
307 for size in self.generic_sizes:
308 self.print_generic_function(size)
309 return
310
311
312 def printBody(self, api):
313
314 self.pixel_stubs = {}
315 generated_stubs = []
316
317 for func in api.functionIterateGlx():
318 if func.client_handcode: continue
319
320 # If the function is a pixel function with a certain
321 # GLX protocol signature, create a fake stub function
322 # for it. For example, create a single stub function
323 # that is used to implement both glTexImage1D and
324 # glTexImage2D.
325
326 if func.glx_rop != 0:
327 do_it = 0
328 for image in func.get_images():
329 if image.img_pad_dimensions:
330 do_it = 1
331 break
332
333
334 if do_it:
335 [h, n] = hash_pixel_function(func)
336
337
338 self.pixel_stubs[ func.name ] = n
339 if h not in generated_stubs:
340 generated_stubs.append(h)
341
342 fake_func = glx_pixel_function_stub( func, n )
343 self.printFunction(fake_func, fake_func.name)
344
345
346 self.printFunction(func, func.name)
347 if func.glx_sop and func.glx_vendorpriv:
348 self.printFunction(func, func.glx_vendorpriv_names[0])
349
350 self.printGetProcAddress(api)
351 return
352
353 def printGetProcAddress(self, api):
354 procs = {}
355 for func in api.functionIterateGlx():
356 for n in func.entry_points:
357 if func.has_different_protocol(n):
358 procs[n] = func.static_glx_name(n)
359
360 print """
361 #ifdef GLX_SHARED_GLAPI
362
363 static const struct proc_pair
364 {
365 const char *name;
366 _glapi_proc proc;
367 } proc_pairs[%d] = {""" % len(procs)
368 names = procs.keys()
369 names.sort()
370 for i in xrange(len(names)):
371 comma = ',' if i < len(names) - 1 else ''
372 print ' { "%s", (_glapi_proc) gl%s }%s' % (names[i], procs[names[i]], comma)
373 print """};
374
375 static int
376 __indirect_get_proc_compare(const void *key, const void *memb)
377 {
378 const struct proc_pair *pair = (const struct proc_pair *) memb;
379 return strcmp((const char *) key, pair->name);
380 }
381
382 _glapi_proc
383 __indirect_get_proc_address(const char *name)
384 {
385 const struct proc_pair *pair;
386
387 /* skip "gl" */
388 name += 2;
389
390 pair = (const struct proc_pair *) bsearch((const void *) name,
391 (const void *) proc_pairs, ARRAY_SIZE(proc_pairs), sizeof(proc_pairs[0]),
392 __indirect_get_proc_compare);
393
394 return (pair) ? pair->proc : NULL;
395 }
396
397 #endif /* GLX_SHARED_GLAPI */
398 """
399 return
400
401
402 def printFunction(self, func, name):
403 footer = '}\n'
404 if func.glx_rop == ~0:
405 print 'static %s' % (func.return_type)
406 print '%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())
407 print '{'
408 else:
409 if func.has_different_protocol(name):
410 if func.return_type == "void":
411 ret_string = ''
412 else:
413 ret_string = "return "
414
415 func_name = func.static_glx_name(name)
416 print '#define %s %d' % (func.opcode_vendor_name(name), func.glx_vendorpriv)
417 print '%s gl%s(%s)' % (func.return_type, func_name, func.get_parameter_string())
418 print '{'
419 print ' struct glx_context * const gc = __glXGetCurrentContext();'
420 print ''
421 print '#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)'
422 print ' if (gc->isDirect) {'
423 print ' const _glapi_proc *const disp_table = (_glapi_proc *)GET_DISPATCH();'
424 print ' PFNGL%sPROC p =' % (name.upper())
425 print ' (PFNGL%sPROC) disp_table[%d];' % (name.upper(), func.offset)
426 print ' %sp(%s);' % (ret_string, 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 because 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:
682 if output.is_image():
683 [dim, w, h, d, junk] = output.get_dimensions()
684 if f.dimensions_in_reply:
685 w = "reply->width"
686 h = "reply->height"
687 d = "reply->depth"
688 if dim < 2:
689 h = "1"
690 else:
691 print ' if (%s == 0) { %s = 1; }' % (h, h)
692 if dim < 3:
693 d = "1"
694 else:
695 print ' if (%s == 0) { %s = 1; }' % (d, d)
696
697 print ' __glEmptyImage(gc, 3, %s, %s, %s, %s, %s, %s_data(reply), %s);' % (w, h, d, output.img_format, output.img_type, xcb_name, output.name)
698 else:
699 if f.reply_always_array:
700 print ' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
701 else:
702 print ' /* the XXX_data_length() xcb function name is misleading, it returns the number */'
703 print ' /* of elements, not the length of the data part. A single element is embedded. */'
704 print ' if (%s_data_length(reply) == 1)' % (xcb_name)
705 print ' (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)
706 print ' else'
707 print ' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
708
709 if f.return_type != 'void':
710 print ' retval = reply->ret_val;'
711 print ' free(reply);'
712 else:
713 print ' ' + xcb_request + ';'
714 print '#else'
715 # End of XCB specific.
716
717
718 if f.parameters != []:
719 pc_decl = "GLubyte const * pc ="
720 else:
721 pc_decl = "(void)"
722
723 if name in f.glx_vendorpriv_names:
724 print ' %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_vendor_name(name))
725 else:
726 print ' %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
727
728 self.common_emit_args(f, "pc", 0, 0)
729
730 images = f.get_images()
731
732 for img in images:
733 if img.is_output:
734 o = f.command_fixed_length() - 4
735 print ' *(int32_t *)(pc + %u) = 0;' % (o)
736 if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
737 print ' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
738
739 if f.img_reset:
740 print ' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
741
742
743 return_name = ''
744 if f.needs_reply():
745 if f.return_type != 'void':
746 return_name = " retval"
747 return_str = " retval = (%s)" % (f.return_type)
748 else:
749 return_str = " (void)"
750
751 got_reply = 0
752
753 for p in f.parameterIterateOutputs():
754 if p.is_image():
755 [dim, w, h, d, junk] = p.get_dimensions()
756 if f.dimensions_in_reply:
757 print " __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)
758 else:
759 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)
760
761 got_reply = 1
762 else:
763 if f.reply_always_array:
764 aa = "GL_TRUE"
765 else:
766 aa = "GL_FALSE"
767
768 # gl_parameter.size() returns the size
769 # of the entire data item. If the
770 # item is a fixed-size array, this is
771 # the size of the whole array. This
772 # is not what __glXReadReply wants. It
773 # wants the size of a single data
774 # element in the reply packet.
775 # Dividing by the array size (1 for
776 # non-arrays) gives us this.
777
778 s = p.size() / p.get_element_count()
779 print " %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)
780 got_reply = 1
781
782
783 # If a reply wasn't read to fill an output parameter,
784 # read a NULL reply to get the return value.
785
786 if not got_reply:
787 print " %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)
788
789
790 elif self.debug:
791 # Only emit the extra glFinish call for functions
792 # that don't already require a reply from the server.
793 print ' __indirect_glFinish();'
794
795 if self.debug:
796 print ' printf( "Exit %%s.\\n", "gl%s" );' % (name)
797
798
799 print ' UnlockDisplay(dpy); SyncHandle();'
800
801 if name not in f.glx_vendorpriv_names:
802 print '#endif /* USE_XCB */'
803
804 print ' }'
805 print ' return%s;' % (return_name)
806 return
807
808
809 def printPixelFunction(self, f):
810 if self.pixel_stubs.has_key( f.name ):
811 # Normally gl_function::get_parameter_string could be
812 # used. However, this call needs to have the missing
813 # dimensions (e.g., a fake height value for
814 # glTexImage1D) added in.
815
816 p_string = ""
817 for param in f.parameterIterateGlxSend():
818 if param.is_padding:
819 continue
820
821 p_string += ", " + param.name
822
823 if param.is_image():
824 [dim, junk, junk, junk, junk] = param.get_dimensions()
825
826 if f.pad_after(param):
827 p_string += ", 1"
828
829 print ' %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)
830 return
831
832
833 if self.common_func_print_just_start(f, None):
834 trailer = " }"
835 else:
836 trailer = None
837
838
839 if f.can_be_large:
840 print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
841 print ' if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
842 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
843 print ' }'
844
845 if f.glx_rop == ~0:
846 opcode = "opcode"
847 else:
848 opcode = f.opcode_real_name()
849
850 print 'emit_header(gc->pc, %s, cmdlen);' % (opcode)
851
852 self.pixel_emit_args( f, "gc->pc", 0 )
853 print 'gc->pc += cmdlen;'
854 print 'if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
855
856 if f.can_be_large:
857 print '}'
858 print 'else {'
859
860 self.large_emit_begin(f, opcode)
861 self.pixel_emit_args(f, "pc", 1)
862
863 print '}'
864
865 if trailer: print trailer
866 return
867
868
869 def printRenderFunction(self, f):
870 # There is a class of GL functions that take a single pointer
871 # as a parameter. This pointer points to a fixed-size chunk
872 # of data, and the protocol for this functions is very
873 # regular. Since they are so regular and there are so many
874 # of them, special case them with generic functions. On
875 # x86, this saves about 26KB in the libGL.so binary.
876
877 if f.variable_length_parameter() == None and len(f.parameters) == 1:
878 p = f.parameters[0]
879 if p.is_pointer():
880 cmdlen = f.command_fixed_length()
881 if cmdlen in self.generic_sizes:
882 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
883 return
884
885 if self.common_func_print_just_start(f, None):
886 trailer = " }"
887 else:
888 trailer = None
889
890 if self.debug:
891 print 'printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
892
893 if f.can_be_large:
894 print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
895 print ' if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
896 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
897 print ' }'
898
899 print 'emit_header(gc->pc, %s, cmdlen);' % (f.opcode_real_name())
900
901 self.common_emit_args(f, "gc->pc", 4, 0)
902 print 'gc->pc += cmdlen;'
903 print 'if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
904
905 if f.can_be_large:
906 print '}'
907 print 'else {'
908
909 self.large_emit_begin(f)
910 self.common_emit_args(f, "pc", 8, 1)
911
912 p = f.variable_length_parameter()
913 print ' __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (p.offset + 8, p.name, p.size_string())
914 print '}'
915
916 if self.debug:
917 print '__indirect_glFinish();'
918 print 'printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
919
920 if trailer: print trailer
921 return
922
923
924 class PrintGlxProtoInit_c(gl_XML.gl_print_base):
925 def __init__(self):
926 gl_XML.gl_print_base.__init__(self)
927
928 self.name = "glX_proto_send.py (from Mesa)"
929 self.license = license.bsd_license_template % ( \
930 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
931 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
932 return
933
934
935 def printRealHeader(self):
936 print """/**
937 * \\file indirect_init.c
938 * Initialize indirect rendering dispatch table.
939 *
940 * \\author Kevin E. Martin <kevin@precisioninsight.com>
941 * \\author Brian Paul <brian@precisioninsight.com>
942 * \\author Ian Romanick <idr@us.ibm.com>
943 */
944
945 #include "indirect_init.h"
946 #include "indirect.h"
947 #include "glapi.h"
948 #include <assert.h>
949
950 #ifndef GLX_USE_APPLEGL
951
952 /**
953 * No-op function used to initialize functions that have no GLX protocol
954 * support.
955 */
956 static int NoOp(void)
957 {
958 return 0;
959 }
960
961 /**
962 * Create and initialize a new GL dispatch table. The table is initialized
963 * with GLX indirect rendering protocol functions.
964 */
965 struct _glapi_table * __glXNewIndirectAPI( void )
966 {
967 _glapi_proc *table;
968 unsigned entries;
969 unsigned i;
970 int o;
971
972 entries = _glapi_get_dispatch_table_size();
973 table = malloc(entries * sizeof(_glapi_proc));
974 if (table == NULL)
975 return NULL;
976
977 /* first, set all entries to point to no-op functions */
978 for (i = 0; i < entries; i++) {
979 table[i] = (_glapi_proc) NoOp;
980 }
981
982 /* now, initialize the entries we understand */"""
983
984 def printRealFooter(self):
985 print """
986 return (struct _glapi_table *) table;
987 }
988
989 #endif
990 """
991 return
992
993
994 def printBody(self, api):
995 for [name, number] in api.categoryIterate():
996 if number != None:
997 preamble = '\n /* %3u. %s */\n' % (int(number), name)
998 else:
999 preamble = '\n /* %s */\n' % (name)
1000
1001 for func in api.functionIterateByCategory(name):
1002 if func.client_supported_for_indirect():
1003 if preamble:
1004 print preamble
1005 preamble = None
1006
1007 if func.is_abi():
1008 print ' table[{offset}] = (_glapi_proc) __indirect_gl{name};'.format(name = func.name, offset = func.offset)
1009 else:
1010 print ' o = _glapi_get_proc_offset("gl{0}");'.format(func.name)
1011 print ' assert(o > 0);'
1012 print ' table[o] = (_glapi_proc) __indirect_gl{0};'.format(func.name)
1013
1014 return
1015
1016
1017 class PrintGlxProtoInit_h(gl_XML.gl_print_base):
1018 def __init__(self):
1019 gl_XML.gl_print_base.__init__(self)
1020
1021 self.name = "glX_proto_send.py (from Mesa)"
1022 self.license = license.bsd_license_template % ( \
1023 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
1024 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
1025 self.header_tag = "_INDIRECT_H_"
1026
1027 self.last_category = ""
1028 return
1029
1030
1031 def printRealHeader(self):
1032 print """/**
1033 * \\file
1034 * Prototypes for indirect rendering functions.
1035 *
1036 * \\author Kevin E. Martin <kevin@precisioninsight.com>
1037 * \\author Ian Romanick <idr@us.ibm.com>
1038 */
1039 """
1040 self.printFastcall()
1041 self.printNoinline()
1042
1043 print """
1044 #include <X11/Xfuncproto.h>
1045 #include "glxclient.h"
1046
1047 extern _X_HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
1048 void * dest, GLboolean reply_is_always_array );
1049
1050 extern _X_HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
1051 struct glx_context * gc, unsigned max_dim, GLint width, GLint height,
1052 GLint depth, GLenum format, GLenum type, void * dest,
1053 GLboolean dimensions_in_reply );
1054
1055 extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
1056 struct glx_context * gc, GLint sop, GLint cmdlen );
1057
1058 extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
1059 struct glx_context * gc, GLint code, GLint vop, GLint cmdlen );
1060 """
1061
1062
1063 def printBody(self, api):
1064 for func in api.functionIterateGlx():
1065 params = func.get_parameter_string()
1066
1067 print 'extern _X_HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params)
1068
1069 for n in func.entry_points:
1070 if func.has_different_protocol(n):
1071 asdf = func.static_glx_name(n)
1072 if asdf not in func.static_entry_points:
1073 print 'extern _X_HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params)
1074 # give it a easy-to-remember name
1075 if func.client_handcode:
1076 print '#define gl_dispatch_stub_%s gl%s' % (n, asdf)
1077 else:
1078 print 'GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params)
1079
1080 break
1081
1082 print ''
1083 print '#ifdef GLX_SHARED_GLAPI'
1084 print 'extern _X_HIDDEN void (*__indirect_get_proc_address(const char *name))(void);'
1085 print '#endif'
1086
1087
1088 def show_usage():
1089 print "Usage: %s [-f input_file_name] [-m output_mode] [-d]" % sys.argv[0]
1090 print " -m output_mode Output mode can be one of 'proto', 'init_c' or 'init_h'."
1091 print " -d Enable extra debug information in the generated code."
1092 sys.exit(1)
1093
1094
1095 if __name__ == '__main__':
1096 file_name = "gl_API.xml"
1097
1098 try:
1099 (args, trail) = getopt.getopt(sys.argv[1:], "f:m:d")
1100 except Exception,e:
1101 show_usage()
1102
1103 debug = 0
1104 mode = "proto"
1105 for (arg,val) in args:
1106 if arg == "-f":
1107 file_name = val
1108 elif arg == "-m":
1109 mode = val
1110 elif arg == "-d":
1111 debug = 1
1112
1113 if mode == "proto":
1114 printer = PrintGlxProtoStubs()
1115 elif mode == "init_c":
1116 printer = PrintGlxProtoInit_c()
1117 elif mode == "init_h":
1118 printer = PrintGlxProtoInit_h()
1119 else:
1120 show_usage()
1121
1122
1123 printer.debug = debug
1124 api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() )
1125
1126 printer.Print( api )