8b3d8d756b8d4c0a55f03625cd16b999310e44a3
[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 # Copyright (c) 2015 Intel Corporation
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a
8 # copy of this software and associated documentation files (the "Software"),
9 # to deal in the Software without restriction, including without limitation
10 # on the rights to use, copy, modify, merge, publish, distribute, sub
11 # license, and/or sell copies of the Software, and to permit persons to whom
12 # the Software is furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice (including the next
15 # paragraph) shall be included in all copies or substantial portions of the
16 # Software.
17 #
18 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 # FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 # IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 # IN THE SOFTWARE.
25 #
26 # Authors:
27 # Ian Romanick <idr@us.ibm.com>
28 # Jeremy Kolb <jkolb@brandeis.edu>
29
30 import argparse
31
32 import gl_XML, glX_XML, glX_proto_common, license
33 import copy, string
34
35 def convertStringForXCB(str):
36 tmp = ""
37 special = [ "ARB" ]
38 i = 0
39 while i < len(str):
40 if str[i:i+3] in special:
41 tmp = '%s_%s' % (tmp, string.lower(str[i:i+3]))
42 i = i + 2;
43 elif str[i].isupper():
44 tmp = '%s_%s' % (tmp, string.lower(str[i]))
45 else:
46 tmp = '%s%s' % (tmp, str[i])
47 i += 1
48 return tmp
49
50 def hash_pixel_function(func):
51 """Generate a 'unique' key for a pixel function. The key is based on
52 the parameters written in the command packet. This includes any
53 padding that might be added for the original function and the 'NULL
54 image' flag."""
55
56
57 h = ""
58 hash_pre = ""
59 hash_suf = ""
60 for param in func.parameterIterateGlxSend():
61 if param.is_image():
62 [dim, junk, junk, junk, junk] = param.get_dimensions()
63
64 d = (dim + 1) & ~1
65 hash_pre = "%uD%uD_" % (d - 1, d)
66
67 if param.img_null_flag:
68 hash_suf = "_NF"
69
70 h += "%u" % (param.size())
71
72 if func.pad_after(param):
73 h += "4"
74
75
76 n = func.name.replace("%uD" % (dim), "")
77 n = "__glx_%s_%uD%uD" % (n, d - 1, d)
78
79 h = hash_pre + h + hash_suf
80 return [h, n]
81
82
83 class glx_pixel_function_stub(glX_XML.glx_function):
84 """Dummy class used to generate pixel "utility" functions that are
85 shared by multiple dimension image functions. For example, these
86 objects are used to generate shared functions used to send GLX
87 protocol for TexImage1D and TexImage2D, TexSubImage1D and
88 TexSubImage2D, etc."""
89
90 def __init__(self, func, name):
91 # The parameters to the utility function are the same as the
92 # parameters to the real function except for the added "pad"
93 # parameters.
94
95 self.name = name
96 self.images = []
97 self.parameters = []
98 self.parameters_by_name = {}
99 for _p in func.parameterIterator():
100 p = copy.copy(_p)
101 self.parameters.append(p)
102 self.parameters_by_name[ p.name ] = p
103
104
105 if p.is_image():
106 self.images.append(p)
107 p.height = "height"
108
109 if p.img_yoff == None:
110 p.img_yoff = "yoffset"
111
112 if p.depth:
113 if p.extent == None:
114 p.extent = "extent"
115
116 if p.img_woff == None:
117 p.img_woff = "woffset"
118
119
120 pad_name = func.pad_after(p)
121 if pad_name:
122 pad = copy.copy(p)
123 pad.name = pad_name
124 self.parameters.append(pad)
125 self.parameters_by_name[ pad.name ] = pad
126
127
128 self.return_type = func.return_type
129
130 self.glx_rop = ~0
131 self.glx_sop = 0
132 self.glx_vendorpriv = 0
133
134 self.glx_doubles_in_order = func.glx_doubles_in_order
135
136 self.vectorequiv = None
137 self.output = None
138 self.can_be_large = func.can_be_large
139 self.reply_always_array = func.reply_always_array
140 self.dimensions_in_reply = func.dimensions_in_reply
141 self.img_reset = None
142
143 self.server_handcode = 0
144 self.client_handcode = 0
145 self.ignore = 0
146
147 self.count_parameter_list = func.count_parameter_list
148 self.counter_list = func.counter_list
149 self.offsets_calculated = 0
150 return
151
152
153 class PrintGlxProtoStubs(glX_proto_common.glx_print_proto):
154 def __init__(self):
155 glX_proto_common.glx_print_proto.__init__(self)
156 self.name = "glX_proto_send.py (from Mesa)"
157 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
158
159
160 self.last_category = ""
161 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
162 self.pixel_stubs = {}
163 self.debug = 0
164 return
165
166 def printRealHeader(self):
167 print ''
168 print '#include <GL/gl.h>'
169 print '#include "indirect.h"'
170 print '#include "glxclient.h"'
171 print '#include "indirect_size.h"'
172 print '#include "glapi.h"'
173 print '#include <GL/glxproto.h>'
174 print '#include <X11/Xlib-xcb.h>'
175 print '#include <xcb/xcb.h>'
176 print '#include <xcb/glx.h>'
177 print '#include <limits.h>'
178
179 print ''
180 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
181 print ''
182 self.printFastcall()
183 self.printNoinline()
184 print ''
185
186 print 'static _X_INLINE int safe_add(int a, int b)'
187 print '{'
188 print ' if (a < 0 || b < 0) return -1;'
189 print ' if (INT_MAX - a < b) return -1;'
190 print ' return a + b;'
191 print '}'
192 print 'static _X_INLINE int safe_mul(int a, int b)'
193 print '{'
194 print ' if (a < 0 || b < 0) return -1;'
195 print ' if (a == 0 || b == 0) return 0;'
196 print ' if (a > INT_MAX / b) return -1;'
197 print ' return a * b;'
198 print '}'
199 print 'static _X_INLINE int safe_pad(int a)'
200 print '{'
201 print ' int ret;'
202 print ' if (a < 0) return -1;'
203 print ' if ((ret = safe_add(a, 3)) < 0) return -1;'
204 print ' return ret & (GLuint)~3;'
205 print '}'
206 print ''
207
208 print '#ifndef __GNUC__'
209 print '# define __builtin_expect(x, y) x'
210 print '#endif'
211 print ''
212 print '/* If the size and opcode values are known at compile-time, this will, on'
213 print ' * x86 at least, emit them with a single instruction.'
214 print ' */'
215 print '#define emit_header(dest, op, size) \\'
216 print ' do { union { short s[2]; int i; } temp; \\'
217 print ' temp.s[0] = (size); temp.s[1] = (op); \\'
218 print ' *((int *)(dest)) = temp.i; } while(0)'
219 print ''
220 print """NOINLINE CARD32
221 __glXReadReply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
222 {
223 xGLXSingleReply reply;
224
225 (void) _XReply(dpy, (xReply *) & reply, 0, False);
226 if (size != 0) {
227 if ((reply.length > 0) || reply_is_always_array) {
228 const GLint bytes = (reply_is_always_array)
229 ? (4 * reply.length) : (reply.size * size);
230 const GLint extra = 4 - (bytes & 3);
231
232 _XRead(dpy, dest, bytes);
233 if ( extra < 4 ) {
234 _XEatData(dpy, extra);
235 }
236 }
237 else {
238 (void) memcpy( dest, &(reply.pad3), size);
239 }
240 }
241
242 return reply.retval;
243 }
244
245 NOINLINE void
246 __glXReadPixelReply( Display *dpy, struct glx_context * gc, unsigned max_dim,
247 GLint width, GLint height, GLint depth, GLenum format, GLenum type,
248 void * dest, GLboolean dimensions_in_reply )
249 {
250 xGLXSingleReply reply;
251 GLint size;
252
253 (void) _XReply(dpy, (xReply *) & reply, 0, False);
254
255 if ( dimensions_in_reply ) {
256 width = reply.pad3;
257 height = reply.pad4;
258 depth = reply.pad5;
259
260 if ((height == 0) || (max_dim < 2)) { height = 1; }
261 if ((depth == 0) || (max_dim < 3)) { depth = 1; }
262 }
263
264 size = reply.length * 4;
265 if (size != 0) {
266 void * buf = malloc( size );
267
268 if ( buf == NULL ) {
269 _XEatData(dpy, size);
270 __glXSetError(gc, GL_OUT_OF_MEMORY);
271 }
272 else {
273 const GLint extra = 4 - (size & 3);
274
275 _XRead(dpy, buf, size);
276 if ( extra < 4 ) {
277 _XEatData(dpy, extra);
278 }
279
280 __glEmptyImage(gc, 3, width, height, depth, format, type,
281 buf, dest);
282 free(buf);
283 }
284 }
285 }
286
287 #define X_GLXSingle 0
288
289 NOINLINE FASTCALL GLubyte *
290 __glXSetupSingleRequest( struct glx_context * gc, GLint sop, GLint cmdlen )
291 {
292 xGLXSingleReq * req;
293 Display * const dpy = gc->currentDpy;
294
295 (void) __glXFlushRenderBuffer(gc, gc->pc);
296 LockDisplay(dpy);
297 GetReqExtra(GLXSingle, cmdlen, req);
298 req->reqType = gc->majorOpcode;
299 req->contextTag = gc->currentContextTag;
300 req->glxCode = sop;
301 return (GLubyte *)(req) + sz_xGLXSingleReq;
302 }
303
304 NOINLINE FASTCALL GLubyte *
305 __glXSetupVendorRequest( struct glx_context * gc, GLint code, GLint vop, GLint cmdlen )
306 {
307 xGLXVendorPrivateReq * req;
308 Display * const dpy = gc->currentDpy;
309
310 (void) __glXFlushRenderBuffer(gc, gc->pc);
311 LockDisplay(dpy);
312 GetReqExtra(GLXVendorPrivate, cmdlen, req);
313 req->reqType = gc->majorOpcode;
314 req->glxCode = code;
315 req->vendorCode = vop;
316 req->contextTag = gc->currentContextTag;
317 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
318 }
319
320 const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
321
322 #define zero (__glXDefaultPixelStore+0)
323 #define one (__glXDefaultPixelStore+8)
324 #define default_pixel_store_1D (__glXDefaultPixelStore+4)
325 #define default_pixel_store_1D_size 20
326 #define default_pixel_store_2D (__glXDefaultPixelStore+4)
327 #define default_pixel_store_2D_size 20
328 #define default_pixel_store_3D (__glXDefaultPixelStore+0)
329 #define default_pixel_store_3D_size 36
330 #define default_pixel_store_4D (__glXDefaultPixelStore+0)
331 #define default_pixel_store_4D_size 36
332 """
333
334 for size in self.generic_sizes:
335 self.print_generic_function(size)
336 return
337
338
339 def printBody(self, api):
340
341 self.pixel_stubs = {}
342 generated_stubs = []
343
344 for func in api.functionIterateGlx():
345 if func.client_handcode: continue
346
347 # If the function is a pixel function with a certain
348 # GLX protocol signature, create a fake stub function
349 # for it. For example, create a single stub function
350 # that is used to implement both glTexImage1D and
351 # glTexImage2D.
352
353 if func.glx_rop != 0:
354 do_it = 0
355 for image in func.get_images():
356 if image.img_pad_dimensions:
357 do_it = 1
358 break
359
360
361 if do_it:
362 [h, n] = hash_pixel_function(func)
363
364
365 self.pixel_stubs[ func.name ] = n
366 if h not in generated_stubs:
367 generated_stubs.append(h)
368
369 fake_func = glx_pixel_function_stub( func, n )
370 self.printFunction(fake_func, fake_func.name)
371
372
373 self.printFunction(func, func.name)
374 if func.glx_sop and func.glx_vendorpriv:
375 self.printFunction(func, func.glx_vendorpriv_names[0])
376
377 self.printGetProcAddress(api)
378 return
379
380 def printGetProcAddress(self, api):
381 procs = {}
382 for func in api.functionIterateGlx():
383 for n in func.entry_points:
384 if func.has_different_protocol(n):
385 procs[n] = func.static_glx_name(n)
386
387 print """
388 #ifdef GLX_SHARED_GLAPI
389
390 static const struct proc_pair
391 {
392 const char *name;
393 _glapi_proc proc;
394 } proc_pairs[%d] = {""" % len(procs)
395 names = procs.keys()
396 names.sort()
397 for i in xrange(len(names)):
398 comma = ',' if i < len(names) - 1 else ''
399 print ' { "%s", (_glapi_proc) gl%s }%s' % (names[i], procs[names[i]], comma)
400 print """};
401
402 static int
403 __indirect_get_proc_compare(const void *key, const void *memb)
404 {
405 const struct proc_pair *pair = (const struct proc_pair *) memb;
406 return strcmp((const char *) key, pair->name);
407 }
408
409 _glapi_proc
410 __indirect_get_proc_address(const char *name)
411 {
412 const struct proc_pair *pair;
413
414 /* skip "gl" */
415 name += 2;
416
417 pair = (const struct proc_pair *) bsearch((const void *) name,
418 (const void *) proc_pairs, ARRAY_SIZE(proc_pairs), sizeof(proc_pairs[0]),
419 __indirect_get_proc_compare);
420
421 return (pair) ? pair->proc : NULL;
422 }
423
424 #endif /* GLX_SHARED_GLAPI */
425 """
426 return
427
428
429 def printFunction(self, func, name):
430 footer = '}\n'
431 if func.glx_rop == ~0:
432 print 'static %s' % (func.return_type)
433 print '%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())
434 print '{'
435 else:
436 if func.has_different_protocol(name):
437 if func.return_type == "void":
438 ret_string = ''
439 else:
440 ret_string = "return "
441
442 func_name = func.static_glx_name(name)
443 print '#define %s %d' % (func.opcode_vendor_name(name), func.glx_vendorpriv)
444 print '%s gl%s(%s)' % (func.return_type, func_name, func.get_parameter_string())
445 print '{'
446 print ' struct glx_context * const gc = __glXGetCurrentContext();'
447 print ''
448 print '#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)'
449 print ' if (gc->isDirect) {'
450 print ' const _glapi_proc *const disp_table = (_glapi_proc *)GET_DISPATCH();'
451 print ' PFNGL%sPROC p =' % (name.upper())
452 print ' (PFNGL%sPROC) disp_table[%d];' % (name.upper(), func.offset)
453 print ' %sp(%s);' % (ret_string, func.get_called_parameter_string())
454 print ' } else'
455 print '#endif'
456 print ' {'
457
458 footer = '}\n}\n'
459 else:
460 print '#define %s %d' % (func.opcode_name(), func.opcode_value())
461
462 print '%s __indirect_gl%s(%s)' % (func.return_type, name, func.get_parameter_string())
463 print '{'
464
465
466 if func.glx_rop != 0 or func.vectorequiv != None:
467 if len(func.images):
468 self.printPixelFunction(func)
469 else:
470 self.printRenderFunction(func)
471 elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
472 self.printSingleFunction(func, name)
473 pass
474 else:
475 print "/* Missing GLX protocol for %s. */" % (name)
476
477 print footer
478 return
479
480
481 def print_generic_function(self, n):
482 size = (n + 3) & ~3
483 print """static FASTCALL NOINLINE void
484 generic_%u_byte( GLint rop, const void * ptr )
485 {
486 struct glx_context * const gc = __glXGetCurrentContext();
487 const GLuint cmdlen = %u;
488
489 emit_header(gc->pc, rop, cmdlen);
490 (void) memcpy((void *)(gc->pc + 4), ptr, %u);
491 gc->pc += cmdlen;
492 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
493 }
494 """ % (n, size + 4, size)
495 return
496
497
498 def common_emit_one_arg(self, p, pc, adjust, extra_offset):
499 if p.is_array():
500 src_ptr = p.name
501 else:
502 src_ptr = "&" + p.name
503
504 if p.is_padding:
505 print '(void) memset((void *)(%s + %u), 0, %s);' \
506 % (pc, p.offset + adjust, p.size_string() )
507 elif not extra_offset:
508 print '(void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
509 % (pc, p.offset + adjust, src_ptr, p.size_string() )
510 else:
511 print '(void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \
512 % (pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() )
513
514 def common_emit_args(self, f, pc, adjust, skip_vla):
515 extra_offset = None
516
517 for p in f.parameterIterateGlxSend( not skip_vla ):
518 if p.name != f.img_reset:
519 self.common_emit_one_arg(p, pc, adjust, extra_offset)
520
521 if p.is_variable_length():
522 temp = p.size_string()
523 if extra_offset:
524 extra_offset += " + %s" % (temp)
525 else:
526 extra_offset = temp
527
528 return
529
530
531 def pixel_emit_args(self, f, pc, large):
532 """Emit the arguments for a pixel function. This differs from
533 common_emit_args in that pixel functions may require padding
534 be inserted (i.e., for the missing width field for
535 TexImage1D), and they may also require a 'NULL image' flag
536 be inserted before the image data."""
537
538 if large:
539 adjust = 8
540 else:
541 adjust = 4
542
543 for param in f.parameterIterateGlxSend():
544 if not param.is_image():
545 self.common_emit_one_arg(param, pc, adjust, None)
546
547 if f.pad_after(param):
548 print '(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset + param.size()) + adjust)
549
550 else:
551 [dim, width, height, depth, extent] = param.get_dimensions()
552 if f.glx_rop == ~0:
553 dim_str = "dim"
554 else:
555 dim_str = str(dim)
556
557 if param.is_padding:
558 print '(void) memset((void *)(%s + %u), 0, %s);' \
559 % (pc, (param.offset - 4) + adjust, param.size_string() )
560
561 if param.img_null_flag:
562 if large:
563 print '(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset - 4) + adjust)
564 else:
565 print '(void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (pc, (param.offset - 4) + adjust, param.name)
566
567
568 pixHeaderPtr = "%s + %u" % (pc, adjust)
569 pcPtr = "%s + %u" % (pc, param.offset + adjust)
570
571 if not large:
572 if param.img_send_null:
573 condition = '(compsize > 0) && (%s != NULL)' % (param.name)
574 else:
575 condition = 'compsize > 0'
576
577 print 'if (%s) {' % (condition)
578 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)
579 print '} else {'
580 print ' (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (pixHeaderPtr, dim, dim)
581 print '}'
582 else:
583 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)
584
585 return
586
587
588 def large_emit_begin(self, f, op_name = None):
589 if not op_name:
590 op_name = f.opcode_real_name()
591
592 print 'const GLint op = %s;' % (op_name)
593 print 'const GLuint cmdlenLarge = cmdlen + 4;'
594 print 'GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);'
595 print '(void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);'
596 print '(void) memcpy((void *)(pc + 4), (void *)(&op), 4);'
597 return
598
599
600 def common_func_print_just_start(self, f, name):
601 print ' struct glx_context * const gc = __glXGetCurrentContext();'
602
603 # The only reason that single and vendor private commands need
604 # a variable called 'dpy' is because they use the SyncHandle
605 # macro. For whatever brain-dead reason, that macro is hard-
606 # coded to use a variable called 'dpy' instead of taking a
607 # parameter.
608
609 # FIXME Simplify the logic related to skip_condition and
610 # FIXME condition_list in this function. Basically, remove
611 # FIXME skip_condition, and just append the "dpy != NULL" type
612 # FIXME condition to condition_list from the start. The only
613 # FIXME reason it's done in this confusing way now is to
614 # FIXME minimize the diffs in the generated code.
615
616 if not f.glx_rop:
617 for p in f.parameterIterateOutputs():
618 if p.is_image() and (p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP"):
619 print ' const __GLXattribute * const state = gc->client_state_private;'
620 break
621
622 print ' Display * const dpy = gc->currentDpy;'
623 skip_condition = "dpy != NULL"
624 elif f.can_be_large:
625 skip_condition = "gc->currentDpy != NULL"
626 else:
627 skip_condition = None
628
629
630 if f.return_type != 'void':
631 print ' %s retval = (%s) 0;' % (f.return_type, f.return_type)
632
633
634 if name != None and name not in f.glx_vendorpriv_names:
635 print '#ifndef USE_XCB'
636 self.emit_packet_size_calculation(f, 0)
637 if name != None and name not in f.glx_vendorpriv_names:
638 print '#endif'
639
640 condition_list = []
641 for p in f.parameterIterateCounters():
642 condition_list.append( "%s >= 0" % (p.name) )
643 # 'counter' parameters cannot be negative
644 print " if (%s < 0) {" % p.name
645 print " __glXSetError(gc, GL_INVALID_VALUE);"
646 if f.return_type != 'void':
647 print " return 0;"
648 else:
649 print " return;"
650 print " }"
651
652 if skip_condition:
653 condition_list.append( skip_condition )
654
655 if len( condition_list ) > 0:
656 if len( condition_list ) > 1:
657 skip_condition = "(%s)" % (string.join( condition_list, ") && (" ))
658 else:
659 skip_condition = "%s" % (condition_list.pop(0))
660
661 print ' if (__builtin_expect(%s, 1)) {' % (skip_condition)
662 return 1
663 else:
664 return 0
665
666
667 def printSingleFunction(self, f, name):
668 self.common_func_print_just_start(f, name)
669
670 if self.debug:
671 print ' printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
672
673 if name not in f.glx_vendorpriv_names:
674
675 # XCB specific:
676 print '#ifdef USE_XCB'
677 if self.debug:
678 print ' printf("\\tUsing XCB.\\n");'
679 print ' xcb_connection_t *c = XGetXCBConnection(dpy);'
680 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
681 xcb_name = 'xcb_glx%s' % convertStringForXCB(name)
682
683 iparams=[]
684 extra_iparams = []
685 output = None
686 for p in f.parameterIterator():
687 if p.is_output:
688 output = p
689
690 if p.is_image():
691 if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP":
692 extra_iparams.append("state->storePack.swapEndian")
693 else:
694 extra_iparams.append("0")
695
696 # Hardcode this in. lsb_first param (apparently always GL_FALSE)
697 # also present in GetPolygonStipple, but taken care of above.
698 if xcb_name == "xcb_glx_read_pixels":
699 extra_iparams.append("0")
700 else:
701 iparams.append(p.name)
702
703
704 xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams))
705
706 if f.needs_reply():
707 print ' %s_reply_t *reply = %s_reply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request)
708 if output:
709 if output.is_image():
710 [dim, w, h, d, junk] = output.get_dimensions()
711 if f.dimensions_in_reply:
712 w = "reply->width"
713 h = "reply->height"
714 d = "reply->depth"
715 if dim < 2:
716 h = "1"
717 else:
718 print ' if (%s == 0) { %s = 1; }' % (h, h)
719 if dim < 3:
720 d = "1"
721 else:
722 print ' if (%s == 0) { %s = 1; }' % (d, d)
723
724 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)
725 else:
726 if f.reply_always_array:
727 print ' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
728 else:
729 print ' /* the XXX_data_length() xcb function name is misleading, it returns the number */'
730 print ' /* of elements, not the length of the data part. A single element is embedded. */'
731 print ' if (%s_data_length(reply) == 1)' % (xcb_name)
732 print ' (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)
733 print ' else'
734 print ' (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
735
736 if f.return_type != 'void':
737 print ' retval = reply->ret_val;'
738 print ' free(reply);'
739 else:
740 print ' ' + xcb_request + ';'
741 print '#else'
742 # End of XCB specific.
743
744
745 if f.parameters != []:
746 pc_decl = "GLubyte const * pc ="
747 else:
748 pc_decl = "(void)"
749
750 if name in f.glx_vendorpriv_names:
751 print ' %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_vendor_name(name))
752 else:
753 print ' %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
754
755 self.common_emit_args(f, "pc", 0, 0)
756
757 images = f.get_images()
758
759 for img in images:
760 if img.is_output:
761 o = f.command_fixed_length() - 4
762 print ' *(int32_t *)(pc + %u) = 0;' % (o)
763 if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
764 print ' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
765
766 if f.img_reset:
767 print ' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
768
769
770 return_name = ''
771 if f.needs_reply():
772 if f.return_type != 'void':
773 return_name = " retval"
774 return_str = " retval = (%s)" % (f.return_type)
775 else:
776 return_str = " (void)"
777
778 got_reply = 0
779
780 for p in f.parameterIterateOutputs():
781 if p.is_image():
782 [dim, w, h, d, junk] = p.get_dimensions()
783 if f.dimensions_in_reply:
784 print " __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)
785 else:
786 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)
787
788 got_reply = 1
789 else:
790 if f.reply_always_array:
791 aa = "GL_TRUE"
792 else:
793 aa = "GL_FALSE"
794
795 # gl_parameter.size() returns the size
796 # of the entire data item. If the
797 # item is a fixed-size array, this is
798 # the size of the whole array. This
799 # is not what __glXReadReply wants. It
800 # wants the size of a single data
801 # element in the reply packet.
802 # Dividing by the array size (1 for
803 # non-arrays) gives us this.
804
805 s = p.size() / p.get_element_count()
806 print " %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)
807 got_reply = 1
808
809
810 # If a reply wasn't read to fill an output parameter,
811 # read a NULL reply to get the return value.
812
813 if not got_reply:
814 print " %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)
815
816
817 elif self.debug:
818 # Only emit the extra glFinish call for functions
819 # that don't already require a reply from the server.
820 print ' __indirect_glFinish();'
821
822 if self.debug:
823 print ' printf( "Exit %%s.\\n", "gl%s" );' % (name)
824
825
826 print ' UnlockDisplay(dpy); SyncHandle();'
827
828 if name not in f.glx_vendorpriv_names:
829 print '#endif /* USE_XCB */'
830
831 print ' }'
832 print ' return%s;' % (return_name)
833 return
834
835
836 def printPixelFunction(self, f):
837 if self.pixel_stubs.has_key( f.name ):
838 # Normally gl_function::get_parameter_string could be
839 # used. However, this call needs to have the missing
840 # dimensions (e.g., a fake height value for
841 # glTexImage1D) added in.
842
843 p_string = ""
844 for param in f.parameterIterateGlxSend():
845 if param.is_padding:
846 continue
847
848 p_string += ", " + param.name
849
850 if param.is_image():
851 [dim, junk, junk, junk, junk] = param.get_dimensions()
852
853 if f.pad_after(param):
854 p_string += ", 1"
855
856 print ' %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)
857 return
858
859
860 if self.common_func_print_just_start(f, None):
861 trailer = " }"
862 else:
863 trailer = None
864
865
866 if f.can_be_large:
867 print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
868 print ' if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
869 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
870 print ' }'
871
872 if f.glx_rop == ~0:
873 opcode = "opcode"
874 else:
875 opcode = f.opcode_real_name()
876
877 print 'emit_header(gc->pc, %s, cmdlen);' % (opcode)
878
879 self.pixel_emit_args( f, "gc->pc", 0 )
880 print 'gc->pc += cmdlen;'
881 print 'if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
882
883 if f.can_be_large:
884 print '}'
885 print 'else {'
886
887 self.large_emit_begin(f, opcode)
888 self.pixel_emit_args(f, "pc", 1)
889
890 print '}'
891
892 if trailer: print trailer
893 return
894
895
896 def printRenderFunction(self, f):
897 # There is a class of GL functions that take a single pointer
898 # as a parameter. This pointer points to a fixed-size chunk
899 # of data, and the protocol for this functions is very
900 # regular. Since they are so regular and there are so many
901 # of them, special case them with generic functions. On
902 # x86, this saves about 26KB in the libGL.so binary.
903
904 if f.variable_length_parameter() == None and len(f.parameters) == 1:
905 p = f.parameters[0]
906 if p.is_pointer():
907 cmdlen = f.command_fixed_length()
908 if cmdlen in self.generic_sizes:
909 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
910 return
911
912 if self.common_func_print_just_start(f, None):
913 trailer = " }"
914 else:
915 trailer = None
916
917 if self.debug:
918 print 'printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
919
920 if f.can_be_large:
921 print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
922 print ' if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
923 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
924 print ' }'
925
926 print 'emit_header(gc->pc, %s, cmdlen);' % (f.opcode_real_name())
927
928 self.common_emit_args(f, "gc->pc", 4, 0)
929 print 'gc->pc += cmdlen;'
930 print 'if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
931
932 if f.can_be_large:
933 print '}'
934 print 'else {'
935
936 self.large_emit_begin(f)
937 self.common_emit_args(f, "pc", 8, 1)
938
939 p = f.variable_length_parameter()
940 print ' __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (p.offset + 8, p.name, p.size_string())
941 print '}'
942
943 if self.debug:
944 print '__indirect_glFinish();'
945 print 'printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
946
947 if trailer: print trailer
948 return
949
950
951 class PrintGlxProtoInit_c(gl_XML.gl_print_base):
952 def __init__(self):
953 gl_XML.gl_print_base.__init__(self)
954
955 self.name = "glX_proto_send.py (from Mesa)"
956 self.license = license.bsd_license_template % ( \
957 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
958 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
959 return
960
961
962 def printRealHeader(self):
963 print """/**
964 * \\file indirect_init.c
965 * Initialize indirect rendering dispatch table.
966 *
967 * \\author Kevin E. Martin <kevin@precisioninsight.com>
968 * \\author Brian Paul <brian@precisioninsight.com>
969 * \\author Ian Romanick <idr@us.ibm.com>
970 */
971
972 #include "indirect_init.h"
973 #include "indirect.h"
974 #include "glapi.h"
975 #include <assert.h>
976
977 #ifndef GLX_USE_APPLEGL
978
979 /**
980 * No-op function used to initialize functions that have no GLX protocol
981 * support.
982 */
983 static int NoOp(void)
984 {
985 return 0;
986 }
987
988 /**
989 * Create and initialize a new GL dispatch table. The table is initialized
990 * with GLX indirect rendering protocol functions.
991 */
992 struct _glapi_table * __glXNewIndirectAPI( void )
993 {
994 _glapi_proc *table;
995 unsigned entries;
996 unsigned i;
997 int o;
998
999 entries = _glapi_get_dispatch_table_size();
1000 table = malloc(entries * sizeof(_glapi_proc));
1001 if (table == NULL)
1002 return NULL;
1003
1004 /* first, set all entries to point to no-op functions */
1005 for (i = 0; i < entries; i++) {
1006 table[i] = (_glapi_proc) NoOp;
1007 }
1008
1009 /* now, initialize the entries we understand */"""
1010
1011 def printRealFooter(self):
1012 print """
1013 return (struct _glapi_table *) table;
1014 }
1015
1016 #endif
1017 """
1018 return
1019
1020
1021 def printBody(self, api):
1022 for [name, number] in api.categoryIterate():
1023 if number != None:
1024 preamble = '\n /* %3u. %s */\n' % (int(number), name)
1025 else:
1026 preamble = '\n /* %s */\n' % (name)
1027
1028 for func in api.functionIterateByCategory(name):
1029 if func.client_supported_for_indirect():
1030 if preamble:
1031 print preamble
1032 preamble = None
1033
1034 if func.is_abi():
1035 print ' table[{offset}] = (_glapi_proc) __indirect_gl{name};'.format(name = func.name, offset = func.offset)
1036 else:
1037 print ' o = _glapi_get_proc_offset("gl{0}");'.format(func.name)
1038 print ' assert(o > 0);'
1039 print ' table[o] = (_glapi_proc) __indirect_gl{0};'.format(func.name)
1040
1041 return
1042
1043
1044 class PrintGlxProtoInit_h(gl_XML.gl_print_base):
1045 def __init__(self):
1046 gl_XML.gl_print_base.__init__(self)
1047
1048 self.name = "glX_proto_send.py (from Mesa)"
1049 self.license = license.bsd_license_template % ( \
1050 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
1051 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
1052 self.header_tag = "_INDIRECT_H_"
1053
1054 self.last_category = ""
1055 return
1056
1057
1058 def printRealHeader(self):
1059 print """/**
1060 * \\file
1061 * Prototypes for indirect rendering functions.
1062 *
1063 * \\author Kevin E. Martin <kevin@precisioninsight.com>
1064 * \\author Ian Romanick <idr@us.ibm.com>
1065 */
1066 """
1067 self.printFastcall()
1068 self.printNoinline()
1069
1070 print """
1071 #include <X11/Xfuncproto.h>
1072 #include "glxclient.h"
1073
1074 extern _X_HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
1075 void * dest, GLboolean reply_is_always_array );
1076
1077 extern _X_HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
1078 struct glx_context * gc, unsigned max_dim, GLint width, GLint height,
1079 GLint depth, GLenum format, GLenum type, void * dest,
1080 GLboolean dimensions_in_reply );
1081
1082 extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
1083 struct glx_context * gc, GLint sop, GLint cmdlen );
1084
1085 extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
1086 struct glx_context * gc, GLint code, GLint vop, GLint cmdlen );
1087 """
1088
1089
1090 def printBody(self, api):
1091 for func in api.functionIterateGlx():
1092 params = func.get_parameter_string()
1093
1094 print 'extern _X_HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params)
1095
1096 for n in func.entry_points:
1097 if func.has_different_protocol(n):
1098 asdf = func.static_glx_name(n)
1099 if asdf not in func.static_entry_points:
1100 print 'extern _X_HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params)
1101 # give it a easy-to-remember name
1102 if func.client_handcode:
1103 print '#define gl_dispatch_stub_%s gl%s' % (n, asdf)
1104 else:
1105 print 'GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params)
1106
1107 break
1108
1109 print ''
1110 print '#ifdef GLX_SHARED_GLAPI'
1111 print 'extern _X_HIDDEN void (*__indirect_get_proc_address(const char *name))(void);'
1112 print '#endif'
1113
1114
1115 def _parser():
1116 """Parse input and returned a parsed namespace."""
1117 parser = argparse.ArgumentParser()
1118 parser.add_argument('-f',
1119 default='gl_API.xml',
1120 dest='filename',
1121 help='An XML file describing an API')
1122 parser.add_argument('-m',
1123 required=True,
1124 dest='mode',
1125 choices=frozenset(['proto', 'init_c', 'init_h']),
1126 help='which file to generate')
1127 parser.add_argument('-d',
1128 action='store_true',
1129 dest='debug',
1130 help='turn debug mode on.')
1131 return parser.parse_args()
1132
1133
1134 def main():
1135 """Main function."""
1136 args = _parser()
1137
1138 if args.mode == "proto":
1139 printer = PrintGlxProtoStubs()
1140 elif args.mode == "init_c":
1141 printer = PrintGlxProtoInit_c()
1142 elif args.mode == "init_h":
1143 printer = PrintGlxProtoInit_h()
1144
1145 printer.debug = args.debug
1146 api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
1147
1148 printer.Print( api )
1149
1150
1151 if __name__ == '__main__':
1152 main()